HandEyeCalibrationWidgetController.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * \package RobotComponents::gui-plugins::HandEyeCalibrationWidgetController
17  * \author Stefan Reither ( stef dot reither at web dot de )
18  * \date 2018
19  * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
24 
25 #include <cctype>
26 #include <iomanip>
27 
28 #include <QClipboard>
29 #include <QFileDialog>
30 #include <QFileInfo>
31 #include <QMessageBox>
32 
33 #include <pcl/common/transforms.h>
34 #include <pcl/filters/filter.h>
35 #include <pcl/filters/passthrough.h>
36 #include <VirtualRobot/MathTools.h>
37 
42 
47 
48 #include <VisionX/interface/components/Calibration.h>
49 
50 const QString defaultFileName("HandEyeCalib_Data.json");
51 
52 using namespace armarx;
53 
55 
56 
58 
59 void
61 {
62 }
63 
64 void
66 {
67 }
68 
69 QPointer<QDialog>
71 {
72  if (!dialog)
73  {
74  dialog = new SimpleConfigDialog(parent);
75  dialog->addProxyFinder<visionx::PointCloudProviderInterfacePrx>(
76  {"PointCloudProvider", "PointCloudProvider", "*"});
77  dialog->addProxyFinder<RobotStateComponentInterfacePrx>(
78  {"RobotStateComponent", "RobotStateComponent", "RobotState*"});
79  }
80  return qobject_cast<SimpleConfigDialog*>(dialog);
81 }
82 
83 void
85 {
86  providerName = dialog->getProxyName("PointCloudProvider");
87  robotStateComponentName = dialog->getProxyName("RobotStateComponent");
88 }
89 
90 void
92 {
93  ARMARX_INFO << "onInitPointCloudProcessor";
94 
95  QMetaObject::invokeMethod(this, "initUI");
96 
97  usingProxy(robotStateComponentName);
98 }
99 
100 void
101 HandEyeCalibrationWidgetController::initUI()
102 {
103  widget.setupUi(getWidget());
104  widget.lineEdit_file->setText(QDir::currentPath() + "/" + defaultFileName);
105  getWidget()->setEnabled(false);
106 }
107 
108 void
109 HandEyeCalibrationWidgetController::saveDatapoint()
110 {
111  if (activeEndEffector)
112  {
113  SimpleJsonLoggerEntry entry;
114  entry.Add("EndEffector", activeEndEffector->getName());
115 
116  std::map<std::string, float> config = localRobot->getConfig()->getRobotNodeJointValueMap();
117  entry.Add("RobotConfig", config);
118 
119  Eigen::Matrix4f offset = getOffsetMatrixForEEF(activeEndEffector);
120  entry.AddMatrix("Offset", offset);
121 
122  std::string fileName = widget.lineEdit_file->text().toStdString();
123  SimpleJsonLogger logger(fileName, true);
124  logger.log(entry);
125  logger.close();
126 
127  QMessageBox::information(
128  getWidget(), tr("HandEyeCalibration"), tr("Datapoint successful written to file."));
129  }
130 }
131 
132 void
133 HandEyeCalibrationWidgetController::selectFile()
134 {
135  QString fileName = QFileDialog::getOpenFileName(getWidget(),
136  tr("Select file for saving data points"),
137  QDir::currentPath(),
138  tr("JSON-File (*.json);; All Files (*)"));
139  if (!fileName.isEmpty())
140  {
141  widget.lineEdit_file->setText(fileName);
142  }
143 }
144 
146 HandEyeCalibrationWidgetController::getEEFRobot(VirtualRobot::EndEffectorPtr eef) const
147 {
148  if (eef && robotEEFMap.count(eef->getName()) == 1)
149  {
150  return robotEEFMap.at(eef->getName()).first;
151  }
152  return VirtualRobot::RobotPtr();
153 }
154 
156 HandEyeCalibrationWidgetController::getOffsetMatrixForEEF(
157  const VirtualRobot::EndEffectorPtr eef) const
158 {
159  if (eef && robotEEFMap.count(eef->getName()) == 1)
160  {
161  return robotEEFMap.at(eef->getName()).second;
162  }
163  return Eigen::Matrix4f::Identity();
164 }
165 
166 void
167 HandEyeCalibrationWidgetController::setOffsetMatrixForEEF(const VirtualRobot::EndEffectorPtr eef,
168  const Eigen::Matrix4f& offset)
169 {
170  if (eef && robotEEFMap.count(eef->getName()) == 1)
171  {
172  robotEEFMap.at(eef->getName()).second = offset;
173  }
174 }
175 
176 void
178 {
179  ARMARX_INFO << "onConnectPointCloudProcessor";
180 
181  robotStateComponentPrx =
182  getProxy<RobotStateComponentInterfacePrx>(robotStateComponentName, true);
183 
184  usingPointCloudProvider(providerName);
185  providerInfo = getPointCloudProvider(providerName, true);
186  referenceFrame = getProviderFrame();
187  providerBuffer.reset(new pcl::PointCloud<PointT>());
188 
189  localRobot = loadRobotFromFile();
190  try
191  {
192  pointcloudRobot = RemoteRobot::createLocalClone(robotStateComponentPrx);
193  }
194  catch (...)
195  {
197  << "Exception while creating local clone of robot in onConnectPointCLoudProcessor()";
199  }
200 
201  // Setup periodic tasks
202  taskEEFManipulation = new PeriodicTask<HandEyeCalibrationWidgetController>(
203  this, &HandEyeCalibrationWidgetController::taskEEFManipulationCB, 30.0f);
204  taskLocalRobotUpdate = new PeriodicTask<HandEyeCalibrationWidgetController>(
205  this, &HandEyeCalibrationWidgetController::taskLocalRobotUpdateCB, 50.0f);
206 
207  // Setup visualizations
208  QMetaObject::invokeMethod(this, "connectQt", Qt::BlockingQueuedConnection);
209 
210  // Finally connecting the signals and slots
211  connect(this, SIGNAL(pointCloudUpdated()), this, SLOT(processPointCloud()));
212  connect(widget.comboBox_endEffectorSelection,
213  SIGNAL(currentIndexChanged(QString)),
214  this,
215  SLOT(activeEndEffectorChanged(QString)));
216  connect(widget.horizontalSlider_croppingBox,
217  SIGNAL(valueChanged(int)),
218  this,
219  SLOT(slider_croppingRange_changed(int)));
220  connect(widget.checkBox_croppingActive,
221  SIGNAL(stateChanged(int)),
222  this,
223  SLOT(cb_croppingActive_changed(int)));
224 
225  connect(widget.checkBox_offsetInverted,
226  SIGNAL(toggled(bool)),
227  this,
228  SLOT(cb_inverted_changed(bool)));
229  connect(widget.pushButton_copyToClipboard,
230  SIGNAL(clicked()),
231  this,
232  SLOT(btn_copyToClipboard_pressed()));
233  connect(widget.pushButton_resetEndeffector,
234  SIGNAL(clicked()),
235  this,
236  SLOT(btn_resetToModel_pressed()));
237 
238  connect(widget.doubleSpinBox_camera_x,
239  SIGNAL(valueChanged(double)),
240  this,
241  SLOT(cameraNodeTransformationChanged(double)));
242  connect(widget.doubleSpinBox_camera_y,
243  SIGNAL(valueChanged(double)),
244  this,
245  SLOT(cameraNodeTransformationChanged(double)));
246  connect(widget.doubleSpinBox_camera_z,
247  SIGNAL(valueChanged(double)),
248  this,
249  SLOT(cameraNodeTransformationChanged(double)));
250  connect(widget.doubleSpinBox_camera_roll,
251  SIGNAL(valueChanged(double)),
252  this,
253  SLOT(cameraNodeTransformationChanged(double)));
254  connect(widget.doubleSpinBox_camera_pitch,
255  SIGNAL(valueChanged(double)),
256  this,
257  SLOT(cameraNodeTransformationChanged(double)));
258  connect(widget.doubleSpinBox_camera_yaw,
259  SIGNAL(valueChanged(double)),
260  this,
261  SLOT(cameraNodeTransformationChanged(double)));
262 
263  connect(widget.pushButton_backgroundColor,
264  SIGNAL(clicked()),
265  this,
266  SLOT(btn_backgroundColor_pressed()));
267  connect(widget.pushButton_pointcloudColor,
268  SIGNAL(clicked()),
269  this,
270  SLOT(btn_pointCloudColor_pressed()));
271  connect(
272  widget.spinBox_pointSize, SIGNAL(valueChanged(int)), this, SLOT(sB_pointSize_changed(int)));
273 
274  connect(widget.pushButton_changeFile, SIGNAL(clicked()), this, SLOT(selectFile()));
275  connect(widget.pushButton_saveDatapoint, SIGNAL(clicked()), this, SLOT(saveDatapoint()));
276 
277  taskEEFManipulation->start();
278  taskLocalRobotUpdate->start();
279  enableMainWidgetAsync(true);
280 }
281 
282 void
283 HandEyeCalibrationWidgetController::connectQt()
284 {
285  pointCloudVisu = new PointCloudVisualization();
286  widget.displayWidget->getDisplay()->getRootNode()->addChild(pointCloudVisu);
287 
288  manipulatorVisu = new ManipulatorVisualization();
289  widget.displayWidget->getDisplay()->getRootNode()->addChild((SoNode*)manipulatorVisu);
290 
291  widget.displayWidget->getDisplay()->cameraViewAll();
292 
293  if (manipulatorVisu)
294  {
295  setupEndEffectorSelection(localRobot);
296  }
297  else
298  {
299  ARMARX_WARNING << "ManipulatorVisu not present";
300  }
301  setupCameraNodeSlider(pointcloudRobot);
302  disableGuiElements();
303 }
304 
305 void
307 {
308  ARMARX_INFO << "onDisconnectPointCloudProcessor";
309 
310  taskEEFManipulation->stop();
311  taskLocalRobotUpdate->stop();
312 
313  releasePointCloudProvider(providerName);
314  QMetaObject::invokeMethod(this, "disconnectQt");
315 
316  localRobot.reset();
317  pointcloudRobot.reset();
318  activeEndEffector.reset();
319  providerBuffer.reset();
320 }
321 
322 void
323 HandEyeCalibrationWidgetController::disconnectQt()
324 {
325  disableGuiElements();
326 
327  widget.comboBox_endEffectorSelection->clear();
328  manipulatorVisu->removeVisualization();
329  pointCloudVisu->removeAllChildren();
330  widget.displayWidget->getDisplay()->getRootNode()->removeAllChildren();
331 
332  // disconnect signals that would interfere with the gui setup
333  QObject::disconnect(widget.comboBox_endEffectorSelection, 0, 0, 0);
334 }
335 
336 void
338 {
339  ARMARX_INFO << "onExitPointCloudProcessor";
340 }
341 
342 void
343 HandEyeCalibrationWidgetController::setupEndEffectorSelection(VirtualRobot::RobotPtr robot)
344 {
345  try
346  {
347  armarx::RemoteRobot::synchronizeLocalClone(robot, robotStateComponentPrx);
348  }
349  catch (...)
350  {
352  }
353 
354  std::vector<VirtualRobot::EndEffectorPtr> endEffectors;
355  robot->getEndEffectors(endEffectors);
356  for (VirtualRobot::EndEffectorPtr e : endEffectors)
357  {
358  widget.comboBox_endEffectorSelection->addItem(QString::fromStdString(e->getName()));
359  VirtualRobot::RobotPtr r = e->createEefRobot(e->getName(), e->getName());
360  r->setGlobalPoseForRobotNode(r->getRobotNode(e->getTcp()->getName()),
361  e->getTcp()->getGlobalPose());
362  robotEEFMap.insert(
363  std::make_pair(e->getName(), std::make_pair(r, Eigen::Matrix4f::Identity())));
364  }
365  widget.comboBox_endEffectorSelection->setCurrentIndex(-1);
366 }
367 
368 bool
369 HandEyeCalibrationWidgetController::findStringIC(const std::string& strHaystack,
370  const std::string& strNeedle) const
371 {
372  auto it =
373  std::search(strHaystack.begin(),
374  strHaystack.end(),
375  strNeedle.begin(),
376  strNeedle.end(),
377  [](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); });
378  return (it != strHaystack.end());
379 }
380 
381 void
382 HandEyeCalibrationWidgetController::setupCameraNodeSlider(VirtualRobot::RobotPtr robot)
383 {
384  if (robot)
385  {
386  ARMARX_CHECK_EXPRESSION(robot->hasRobotNode(referenceFrame))
387  << "Robot " + robot->getName() + " does not have node with name " + referenceFrame;
388  widget.label_cameraNodeName->setText(QString::fromStdString((referenceFrame)));
389 
390  cameraNode = robot->getRobotNode(referenceFrame);
391  auto trans = VirtualRobot::MathTools::eigen4f2posrpy(cameraNode->getLocalTransformation());
392 
393  widget.doubleSpinBox_camera_x->setValue(trans(0));
394  widget.doubleSpinBox_camera_y->setValue(trans(1));
395  widget.doubleSpinBox_camera_z->setValue(trans(2));
396  widget.doubleSpinBox_camera_roll->setValue(VirtualRobot::MathTools::rad2deg(trans(3)));
397  widget.doubleSpinBox_camera_pitch->setValue(VirtualRobot::MathTools::rad2deg(trans(4)));
398  widget.doubleSpinBox_camera_yaw->setValue(VirtualRobot::MathTools::rad2deg(trans(5)));
399  }
400 }
401 
403 HandEyeCalibrationWidgetController::loadRobotFromFile() const
404 {
405  Ice::StringSeq includePaths;
406 
407  try
408  {
409  Ice::StringSeq packages = robotStateComponentPrx->getArmarXPackages();
410  packages.push_back(Application::GetProjectName());
411 
412  for (const std::string& projectName : packages)
413  {
414  if (projectName.empty())
415  {
416  continue;
417  }
418 
419  CMakePackageFinder project(projectName);
420  auto pathsString = project.getDataDir();
421  Ice::StringSeq projectIncludePaths = armarx::Split(pathsString, ";,", true, true);
422  includePaths.insert(
423  includePaths.end(), projectIncludePaths.begin(), projectIncludePaths.end());
424  }
425  }
426  catch (...)
427  {
428  ARMARX_ERROR << "Unable to retrieve robot filename." << std::endl;
429  return VirtualRobot::RobotPtr();
430  }
431 
432  try
433  {
434  std::string rfile = robotStateComponentPrx->getRobotFilename();
435  ArmarXDataPath::getAbsolutePath(rfile, rfile, includePaths);
436  return VirtualRobot::RobotIO::loadRobot(rfile);
437  }
438  catch (...)
439  {
440  ARMARX_ERROR << "Unable to load robot from file" << std::endl;
441  return VirtualRobot::RobotPtr();
442  }
443 }
444 
445 std::string
446 HandEyeCalibrationWidgetController::getProviderFrame() const
447 {
448  std::string frame = "Global";
449  try
450  {
451  visionx::ReferenceFrameInterfacePrx refFramePrx =
452  visionx::ReferenceFrameInterfacePrx::checkedCast(providerInfo.proxy);
453  if (refFramePrx)
454  {
455  frame = refFramePrx->getReferenceFrame();
456  }
457  }
458  catch (...)
459  {
461  }
462  return frame;
463 }
464 
465 std::string
466 HandEyeCalibrationWidgetController::formatTransformationMatrix(Eigen::Matrix4f mat,
467  int decimalPlacesOrientation,
468  int decimalPlacesPosition) const
469 {
470  std::stringstream ss;
471  ss.imbue(std::locale::classic());
472  ss << std::fixed;
473 
474  // The first three rows behave the same
475  for (int i = 0; i < 3; i++)
476  {
477  float x0 = mat(i, 0);
478  float x1 = mat(i, 1);
479  float x2 = mat(i, 2);
480  ss << std::setprecision(decimalPlacesOrientation);
481  if (!std::signbit(x0))
482  {
483  ss << " ";
484  }
485  ss << x0 << " ";
486  if (!std::signbit(x1))
487  {
488  ss << " ";
489  }
490  ss << x1 << " ";
491  if (!std::signbit(x2))
492  {
493  ss << " ";
494  }
495  ss << x2 << " ";
496 
497  ss << std::setprecision(decimalPlacesPosition);
498  if (!std::signbit(mat(i, 3)))
499  {
500  ss << " ";
501  }
502  ss << mat(i, 3);
503  ss << std::endl;
504  }
505  return ss.str();
506 }
507 
508 void
509 HandEyeCalibrationWidgetController::enableGuiElements()
510 {
511  widget.horizontalSlider_croppingBox->setEnabled(true);
512  widget.horizontalSlider_x->setEnabled(true);
513  widget.horizontalSlider_y->setEnabled(true);
514  widget.horizontalSlider_z->setEnabled(true);
515  widget.checkBox_croppingActive->setEnabled(true);
516  widget.checkBox_offsetInverted->setEnabled(true);
517  widget.pushButton_copyToClipboard->setEnabled(true);
518  widget.pushButton_resetEndeffector->setEnabled(true);
519  widget.pushButton_pointcloudColor->setEnabled(true);
520  widget.pushButton_backgroundColor->setEnabled(true);
521  widget.spinBox_pointSize->setEnabled(true);
522  widget.pushButton_changeFile->setEnabled(true);
523  widget.pushButton_saveDatapoint->setEnabled(true);
524  widget.lineEdit_file->setEnabled(true);
525 
526  widget.doubleSpinBox_camera_x->setEnabled(true);
527  widget.doubleSpinBox_camera_y->setEnabled(true);
528  widget.doubleSpinBox_camera_z->setEnabled(true);
529  widget.doubleSpinBox_camera_roll->setEnabled(true);
530  widget.doubleSpinBox_camera_pitch->setEnabled(true);
531  widget.doubleSpinBox_camera_yaw->setEnabled(true);
532 
533  widget.label_offsetMatrix->setText(QString("No Endeffector selected"));
534  widget.label_offsetMatrix->setStyleSheet("QLabel { color : black; }");
535 
536  showPointCloud = true;
537 }
538 
539 void
540 HandEyeCalibrationWidgetController::disableGuiElements()
541 {
542  widget.horizontalSlider_croppingBox->setEnabled(false);
543  widget.horizontalSlider_x->setEnabled(false);
544  widget.horizontalSlider_y->setEnabled(false);
545  widget.horizontalSlider_z->setEnabled(false);
546  widget.checkBox_croppingActive->setEnabled(false);
547  widget.checkBox_offsetInverted->setEnabled(false);
548  widget.pushButton_copyToClipboard->setEnabled(false);
549  widget.pushButton_resetEndeffector->setEnabled(false);
550  widget.pushButton_pointcloudColor->setEnabled(false);
551  widget.pushButton_backgroundColor->setEnabled(false);
552  widget.spinBox_pointSize->setEnabled(false);
553  widget.pushButton_changeFile->setEnabled(false);
554  widget.pushButton_saveDatapoint->setEnabled(false);
555  widget.lineEdit_file->setEnabled(false);
556 
557  widget.doubleSpinBox_camera_x->setEnabled(false);
558  widget.doubleSpinBox_camera_y->setEnabled(false);
559  widget.doubleSpinBox_camera_z->setEnabled(false);
560  widget.doubleSpinBox_camera_roll->setEnabled(false);
561  widget.doubleSpinBox_camera_pitch->setEnabled(false);
562  widget.doubleSpinBox_camera_yaw->setEnabled(false);
563 
564  widget.label_offsetMatrix->setText(QString("No Endeffector selected"));
565  widget.label_offsetMatrix->setStyleSheet("QLabel { color : red; }");
566 
567  showPointCloud = false;
568 }
569 
570 void
571 HandEyeCalibrationWidgetController::updateManipulatorVisualization()
572 {
573  if (activeEndEffector && manipulatorVisu)
574  {
575  Eigen::Matrix4f modelPoseInRoot =
576  localRobot->getRobotNode(activeEndEffector->getTcp()->getName())->getPoseInRootFrame();
577  Eigen::Matrix4f offset = getOffsetMatrixForEEF(activeEndEffector);
578  // Apply offset in root frame (multiplication order matters!!)
579  Eigen::Matrix4f pointCloudInRoot = offset * modelPoseInRoot;
580  Eigen::Matrix4f pointCloudGlobal = localRobot->getGlobalPose() * pointCloudInRoot;
581 
582  // Apply global pose to manipulator visu
583  manipulatorVisu->setUserDesiredPose(pointCloudGlobal);
584 
585  // Update the local eefRobot
586  getEEFRobot(activeEndEffector)
587  ->setGlobalPoseForRobotNode(activeEndEffector->getTcp(), pointCloudGlobal);
588 
589  // Update Matrix label
590  if (widget.checkBox_offsetInverted->isChecked())
591  {
592  offset = offset.inverse();
593  }
594  widget.label_offsetMatrix->setText(
595  QString::fromStdString(formatTransformationMatrix(offset)));
596  }
597 }
598 
599 void
601 {
602  if (!waitForPointClouds(providerName, 500))
603  {
604  ARMARX_WARNING << "Timeout or error in waiting for pointclouds from provider: "
605  << providerName;
606  }
607  else
608  {
609  getPointClouds(providerName, providerBuffer);
610 
611  emit pointCloudUpdated();
612  }
613 }
614 
615 void
616 HandEyeCalibrationWidgetController::processPointCloud()
617 {
618  if (showPointCloud && pointcloudRobot)
619  {
620  // Copy buffer to be able to edit it
621  pcl::PointCloud<PointT>::Ptr localBufferIn(new pcl::PointCloud<PointT>());
622  pcl::copyPointCloud(*providerBuffer, *localBufferIn);
623  pcl::PointCloud<PointT>::Ptr localBufferOut(new pcl::PointCloud<PointT>());
624 
625  Eigen::Matrix4f sourceFrameGlobalPose = Eigen::Matrix4f::Identity();
626  if (referenceFrame != "Global")
627  {
628  visionx::MetaPointCloudFormatPtr info = this->getPointCloudFormat(providerName);
629 
630  try
631  {
633  pointcloudRobot, robotStateComponentPrx, info->timeProvided);
634  }
635  catch (...)
636  {
637  ARMARX_ERROR << "Exception while synchronizing robot for pointcloud-processing";
639  }
640 
641  sourceFrameGlobalPose = pointcloudRobot->getRobotNode(referenceFrame)->getGlobalPose();
642  }
643  Eigen::Matrix4f cameraToGlobal = sourceFrameGlobalPose;
644 
645  // Crop pointcloud around endeffector
646  if (croppingActive && manipulatorVisu && manipulatorVisu->getIsVisualizing())
647  {
648  Eigen::Matrix4f eefGlobal = manipulatorVisu->getUserDesiredPose();
649  Eigen::Matrix4f eefInReferenceFrame = sourceFrameGlobalPose.inverse() * eefGlobal;
650 
651  float cropRange = (float)widget.horizontalSlider_croppingBox->value();
652 
653  Eigen::Vector3f cropMin;
654  cropMin << eefInReferenceFrame(0, 3) - cropRange, eefInReferenceFrame(1, 3) - cropRange,
655  eefInReferenceFrame(2, 3) - cropRange;
656  Eigen::Vector3f cropMax;
657  cropMax << eefInReferenceFrame(0, 3) + cropRange, eefInReferenceFrame(1, 3) + cropRange,
658  eefInReferenceFrame(2, 3) + cropRange;
659 
660  pcl::PassThrough<PointT> pass;
661 
662  pass.setInputCloud(localBufferIn);
663  pass.setFilterFieldName("z");
664  pass.setFilterLimits(cropMin(2), cropMax(2));
665  pass.filter(*localBufferOut);
666  localBufferOut.swap(localBufferIn);
667 
668  pass.setInputCloud(localBufferIn);
669  pass.setFilterFieldName("x");
670  pass.setFilterLimits(cropMin(0), cropMax(0));
671  pass.filter(*localBufferOut);
672  localBufferOut.swap(localBufferIn);
673 
674  pass.setInputCloud(localBufferIn);
675  pass.setFilterFieldName("y");
676  pass.setFilterLimits(cropMin(1), cropMax(1));
677  pass.filter(*localBufferOut);
678  localBufferOut.swap(localBufferIn);
679  }
680 
681 
682  // Transform pointcloud into GlobalFrame
683  pcl::transformPointCloud(*localBufferIn, *localBufferOut, cameraToGlobal);
684  localBufferOut.swap(localBufferIn);
685 
686  if (pointCloudVisu)
687  {
688  pointCloudVisu->setVisualization(localBufferIn);
689  }
690  }
691 }
692 
693 void
694 HandEyeCalibrationWidgetController::cb_inverted_changed(bool checked)
695 {
696  if (checked)
697  {
698  widget.label_titleOffsetMatrix->setText("Offset from Pointcloud to Model:");
699  }
700  else
701  {
702  widget.label_titleOffsetMatrix->setText("Offset from Model to Pointcloud:");
703  }
704 }
705 
706 void
707 HandEyeCalibrationWidgetController::btn_copyToClipboard_pressed()
708 {
709  if (activeEndEffector)
710  {
711  Eigen::Matrix4f offset = this->getOffsetMatrixForEEF(activeEndEffector);
712 
713  if (widget.checkBox_offsetInverted->isChecked())
714  {
715  offset = offset.inverse();
716  }
717 
718  PosePtr pose = new Pose(offset);
719 
720  JSONObjectPtr obj = new JSONObject();
721  obj->serializeIceObject(pose);
722 
723  QClipboard* clipboard = QApplication::clipboard();
724  clipboard->setText(QString::fromStdString(obj->asString(true)));
725  }
726 }
727 
728 void
729 HandEyeCalibrationWidgetController::btn_resetToModel_pressed()
730 {
731  if (activeEndEffector)
732  {
733  setOffsetMatrixForEEF(activeEndEffector, Eigen::Matrix4f::Identity());
734  updateManipulatorVisualization();
735  widget.displayWidget->getDisplay()->cameraViewNode((SoNode*)manipulatorVisu, 1.0);
736  }
737 }
738 
739 void
740 HandEyeCalibrationWidgetController::btn_backgroundColor_pressed()
741 {
742  QColor selectedColor = this->colorDialog.getColor();
743  widget.displayWidget->getDisplay()->setBackgroundColor(SbColor(selectedColor.red() / 255.0f,
744  selectedColor.green() / 255.0f,
745  selectedColor.blue() / 255.0f));
746 }
747 
748 void
749 HandEyeCalibrationWidgetController::btn_pointCloudColor_pressed()
750 {
751  QColor selectedColor = this->colorDialog.getColor();
752  this->pointCloudVisu->setDrawColor(SbColor(selectedColor.red() / 255.0f,
753  selectedColor.green() / 255.0f,
754  selectedColor.blue() / 255.0f));
755 }
756 
757 void
758 HandEyeCalibrationWidgetController::sB_pointSize_changed(int value)
759 {
760  this->pointCloudVisu->setPointSize(value);
761 }
762 
763 void
764 HandEyeCalibrationWidgetController::cameraNodeTransformationChanged(double value)
765 {
766  if (cameraNode)
767  {
768  auto t = VirtualRobot::MathTools::eigen4f2posrpy(cameraNode->getLocalTransformation());
769  QObject* obj = sender();
770  if (obj == widget.doubleSpinBox_camera_x)
771  {
772  t(0) = (float)value;
773  }
774  else if (obj == widget.doubleSpinBox_camera_y)
775  {
776  t(1) = (float)value;
777  }
778  else if (obj == widget.doubleSpinBox_camera_z)
779  {
780  t(2) = (float)value;
781  }
782  else if (obj == widget.doubleSpinBox_camera_roll)
783  {
784  t(3) = VirtualRobot::MathTools::deg2rad((float)value);
785  }
786  else if (obj == widget.doubleSpinBox_camera_pitch)
787  {
788  t(4) = VirtualRobot::MathTools::deg2rad((float)value);
789  }
790  else if (obj == widget.doubleSpinBox_camera_yaw)
791  {
792  t(5) = VirtualRobot::MathTools::deg2rad((float)value);
793  }
794  Eigen::Matrix4f transformation =
795  VirtualRobot::MathTools::posrpy2eigen4f(t(0), t(1), t(2), t(3), t(4), t(5));
796  cameraNode->setLocalTransformation(transformation);
797  }
798 }
799 
800 void
801 HandEyeCalibrationWidgetController::taskEEFManipulationCB()
802 {
803  float x[3];
804  x[0] = (float)widget.horizontalSlider_x->value();
805  x[1] = (float)widget.horizontalSlider_y->value();
806  x[2] = (float)widget.horizontalSlider_z->value();
807  if (activeEndEffector)
808  {
810  offsetInRoot(0, 3) = x[0];
811  offsetInRoot(1, 3) = x[1];
812  offsetInRoot(2, 3) = x[2];
813 
814  setOffsetMatrixForEEF(activeEndEffector, offsetInRoot);
815  }
816 }
817 
818 void
819 HandEyeCalibrationWidgetController::taskLocalRobotUpdateCB()
820 {
821  if (!robotStateComponentPrx)
822  {
823  return;
824  }
825  try
826  {
827  RemoteRobot::synchronizeLocalClone(localRobot, robotStateComponentPrx);
828  updateManipulatorVisualization();
829  }
830  catch (...)
831  {
832  }
833 }
834 
835 void
836 HandEyeCalibrationWidgetController::activeEndEffectorChanged(QString endEffectorName)
837 {
838  if (localRobot && manipulatorVisu)
839  {
840  std::string eefName = endEffectorName.toStdString();
841  if (!eefName.empty())
842  {
843  if (robotEEFMap.count(eefName) == 1)
844  {
845  activeEndEffector = robotEEFMap.at(eefName).first->getEndEffector(eefName);
846  manipulatorVisu->setVisualization(activeEndEffector);
847  widget.displayWidget->getDisplay()->cameraViewNode((SoNode*)manipulatorVisu, 1.0);
848  enableGuiElements();
849  }
850  else
851  {
852  ARMARX_ERROR << "Robot " << localRobot->getName()
853  << " does not have endeffector with name " << eefName;
854  }
855  }
856  }
857 }
858 
859 void
860 HandEyeCalibrationWidgetController::slider_croppingRange_changed(int value)
861 {
862  this->widget.label_croppingBoxValue->setText(QString::fromStdString(ValueToString(value)));
863 }
864 
865 void
866 HandEyeCalibrationWidgetController::cb_croppingActive_changed(int state)
867 {
868  if (state == Qt::Unchecked)
869  {
870  this->croppingActive = true;
871  }
872  else
873  {
874  this->croppingActive = false;
875  }
876 }
armarx::PointCloudVisualization::setDrawColor
void setDrawColor(SbColor color)
Definition: PointCloudVisualization.cpp:118
RemoteRobot.h
armarx::HandEyeCalibrationWidgetController::onExitPointCloudProcessor
void onExitPointCloudProcessor() override
Exit the ImapeProcessor component.
Definition: HandEyeCalibrationWidgetController.cpp:337
armarx::Application::GetProjectName
static const std::string & GetProjectName()
Definition: Application.cpp:879
armarx::HandEyeCalibrationWidgetController::onInitPointCloudProcessor
void onInitPointCloudProcessor() override
Setup the vision component.
Definition: HandEyeCalibrationWidgetController.cpp:91
armarx::PointCloudVisualization
Definition: PointCloudVisualization.h:37
visionx::PointCloudProcessor::getPointCloudFormat
MetaPointCloudFormatPtr getPointCloudFormat(std::string providerName)
Definition: PointCloudProcessor.cpp:534
JSONObject.h
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
armarx::HandEyeCalibrationWidgetController::onDisconnectPointCloudProcessor
void onDisconnectPointCloudProcessor() override
Implement this method in the PointCloudProcessor in order execute parts when the component looses net...
Definition: HandEyeCalibrationWidgetController.cpp:306
armarx::RemoteRobot::synchronizeLocalClone
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
Definition: RemoteRobot.cpp:522
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:650
Pose.h
SimpleJsonLogger.h
armarx::JSONObject
The JSONObject class is used to represent and (de)serialize JSON objects.
Definition: JSONObject.h:43
visionx::PointCloudProviderInfo::proxy
PointCloudProviderInterfacePrx proxy
Proxy to PointCloud provider.
Definition: PointCloudProcessor.h:86
armarx::Split
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelperTemplates.h:36
armarx::HandEyeCalibrationWidgetController::~HandEyeCalibrationWidgetController
virtual ~HandEyeCalibrationWidgetController()
Controller destructor.
armarx::SimpleJsonLoggerEntry::AddMatrix
void AddMatrix(const std::string &key, const Eigen::MatrixXf &mat)
Definition: SimpleJsonLoggerEntry.cpp:59
armarx::HandEyeCalibrationWidgetController::HandEyeCalibrationWidgetController
HandEyeCalibrationWidgetController()
Controller Constructor.
armarx::CMakePackageFinder
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
Definition: CMakePackageFinder.h:52
defaultFileName
const QString defaultFileName("HandEyeCalib_Data.json")
armarx::SimpleJsonLogger
Definition: SimpleJsonLogger.h:42
project
std::string project
Definition: VisualizationRobot.cpp:85
StringHelpers.h
IceInternal::Handle< Pose >
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
armarx::ValueToString
std::string ValueToString(const T &value)
Definition: StringHelpers.h:61
visionx::PointCloudProcessor::waitForPointClouds
bool waitForPointClouds(int milliseconds=1000)
Wait for new PointClouds.
Definition: PointCloudProcessor.cpp:458
armarx::HandEyeCalibrationWidgetController::onConnectPointCloudProcessor
void onConnectPointCloudProcessor() override
Implement this method in the PointCloudProcessor in order execute parts when the component is fully i...
Definition: HandEyeCalibrationWidgetController.cpp:177
armarx::SimpleJsonLoggerEntry::Add
void Add(const std::string &key, const std::string &value)
Definition: SimpleJsonLoggerEntry.cpp:65
SimpleJsonLoggerEntry.h
armarx::HandEyeCalibrationWidgetController::getConfigDialog
QPointer< QDialog > getConfigDialog(QWidget *parent=0) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
Definition: HandEyeCalibrationWidgetController.cpp:70
armarx::HandEyeCalibrationWidgetController::process
void process() override
Process the vision component.
Definition: HandEyeCalibrationWidgetController.cpp:600
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
visionx::PointCloudProcessor::getPointClouds
int getPointClouds(const PointCloudPtrT &pointCloudPtr)
Poll PointClouds from provider.
Definition: PointCloudProcessor.h:380
armarx::PointCloudVisualization::setPointSize
void setPointSize(int size)
Definition: PointCloudVisualization.cpp:125
armarx::PointCloudVisualization::setVisualization
void setVisualization(pcl::PointCloud< PointT >::ConstPtr cloud)
Definition: PointCloudVisualization.cpp:51
CMakePackageFinder.h
visionx::PointCloudProcessor::releasePointCloudProvider
void releasePointCloudProvider(std::string providerName)
Removes topic subscription and provider proxy dependency to release a point cloud provider.
Definition: PointCloudProcessor.cpp:295
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::HandEyeCalibrationWidgetController::configured
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
Definition: HandEyeCalibrationWidgetController.cpp:84
float
#define float
Definition: 16_Level.h:22
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::ArmarXWidgetController::enableMainWidgetAsync
void enableMainWidgetAsync(bool enable)
This function enables/disables the main widget asynchronously (if called from a non qt thread).
Definition: ArmarXWidgetController.cpp:191
armarx::RemoteRobot::createLocalClone
VirtualRobot::RobotPtr createLocalClone()
Clones the structure of this remote robot to a local instance.
Definition: RemoteRobot.cpp:381
armarx::RemoteRobot::synchronizeLocalCloneToTimestamp
static bool synchronizeLocalCloneToTimestamp(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx, Ice::Long timestamp)
Synchronizes a local robot to a robot state at timestamp.
Definition: RemoteRobot.cpp:566
visionx::PointCloudProcessor::usingPointCloudProvider
void usingPointCloudProvider(std::string providerName)
Registers a delayed topic subscription and a delayed provider proxy retrieval which will be available...
Definition: PointCloudProcessor.cpp:279
IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface >
armarx::ManipulatorVisualization
Definition: ManipulatorVisualization.h:55
armarx::ArmarXWidgetController::getWidget
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
Definition: ArmarXWidgetController.cpp:54
visionx::PointCloudProcessor::getPointCloudProvider
PointCloudProviderInfo getPointCloudProvider(std::string name, bool waitForProxy=false)
Select an PointCloudProvider.
Definition: PointCloudProcessor.cpp:325
armarx::HandEyeCalibrationWidgetController::saveSettings
void saveSettings(QSettings *settings) override
Definition: HandEyeCalibrationWidgetController.cpp:65
armarx::HandEyeCalibrationWidgetController::pointCloudUpdated
void pointCloudUpdated()
armarx::ArmarXDataPath::getAbsolutePath
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
Definition: ArmarXDataPath.cpp:109
armarx::PeriodicTask
Definition: ArmarXManager.h:70
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:157
armarx::SimpleJsonLoggerEntry
Definition: SimpleJsonLoggerEntry.h:37
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::HandEyeCalibrationWidgetController::loadSettings
void loadSettings(QSettings *settings) override
Definition: HandEyeCalibrationWidgetController.cpp:60
HandEyeCalibrationWidgetController.h
armarx::ManagedIceObject::usingProxy
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Definition: ManagedIceObject.cpp:154
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
Application.h
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:19
armarx::SimpleConfigDialog
A config-dialog containing one (or multiple) proxy finders.
Definition: SimpleConfigDialog.h:84