handeye_control_widget.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2019, Intel Corporation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Yu Yan */
36 
39 
40 namespace moveit_rviz_plugin
41 {
42 const std::string LOGNAME = "handeye_control_widget";
43 
44 ProgressBarWidget::ProgressBarWidget(QWidget* parent, int min, int max, int value) : QWidget(parent)
45 {
46  QHBoxLayout* row = new QHBoxLayout(this);
47  row->setContentsMargins(0, 10, 0, 10);
48 
49  // QLabel init
50  name_label_ = new QLabel("Recorded joint state progress:", this);
51  name_label_->setContentsMargins(0, 0, 0, 0);
52  row->addWidget(name_label_);
53 
54  value_label_ = new QLabel(QString::number(value), this);
55  value_label_->setContentsMargins(0, 0, 0, 0);
56  row->addWidget(value_label_);
57 
58  // QProgressBar init
59  bar_ = new QProgressBar(this);
60  bar_->setTextVisible(true);
61  bar_->setMinimum(min);
62  bar_->setMaximum(max);
63  bar_->setValue(value);
64  bar_->setContentsMargins(0, 0, 0, 0);
65  bar_->setDisabled(max == 0);
66  row->addWidget(bar_);
67 
68  max_label_ = new QLabel(QString::number(max), this);
69  max_label_->setContentsMargins(0, 0, 0, 0);
70  row->addWidget(max_label_);
71 
72  this->setLayout(row);
73 }
74 
75 void ProgressBarWidget::setMax(int value)
76 {
77  bar_->setMaximum(value);
78  bar_->setDisabled(value == 0);
79  max_label_->setText(QString::number(value));
80 }
81 
82 void ProgressBarWidget::setMin(int value)
83 {
84  bar_->setMinimum(value);
85 }
86 
87 void ProgressBarWidget::setValue(int value)
88 {
89  bar_->setValue(value);
90  value_label_->setText(QString::number(value));
91 }
92 
94 {
95  return bar_->value();
96 }
97 
98 ControlTabWidget::ControlTabWidget(HandEyeCalibrationDisplay* pdisplay, QWidget* parent)
99  : QWidget(parent)
100  , calibration_display_(pdisplay)
101  , tf_buffer_(new tf2_ros::Buffer())
102  , tf_listener_(*tf_buffer_)
103  , sensor_mount_type_(mhc::EYE_TO_HAND)
104  , from_frame_tag_("base")
105  , solver_plugins_loader_(nullptr)
106  , solver_(nullptr)
107  , move_group_(nullptr)
108  , camera_robot_pose_(Eigen::Isometry3d::Identity())
109  , auto_started_(false)
110  , planning_res_(ControlTabWidget::SUCCESS)
111 // spinner_(0, &callback_queue_)
112 {
113  QVBoxLayout* layout = new QVBoxLayout();
114  this->setLayout(layout);
115 
116  QHBoxLayout* calib_layout = new QHBoxLayout();
117  layout->addLayout(calib_layout);
118 
119  // Calibration progress
120  auto_progress_ = new ProgressBarWidget(this);
121  layout->addWidget(auto_progress_);
122 
123  // Pose sample tree view area
124  QGroupBox* sample_group = new QGroupBox("Pose samples");
125  sample_group->setMinimumWidth(280);
126  calib_layout->addWidget(sample_group);
127  QVBoxLayout* sample_layout = new QVBoxLayout();
128  sample_group->setLayout(sample_layout);
129 
130  sample_tree_view_ = new QTreeView(this);
131  sample_tree_view_->setAutoScroll(true);
132  sample_tree_view_->setAlternatingRowColors(true);
133  tree_view_model_ = new QStandardItemModel(sample_tree_view_);
134  sample_tree_view_->setModel(tree_view_model_);
135  sample_tree_view_->setHeaderHidden(true);
136  sample_tree_view_->setIndentation(10);
137  sample_layout->addWidget(sample_tree_view_);
138  reprojection_error_label_ = new QLabel("Reprojection error: N/A");
139  sample_layout->addWidget(reprojection_error_label_);
140 
141  // Settings area
142  QVBoxLayout* layout_right = new QVBoxLayout();
143  calib_layout->addLayout(layout_right);
144 
145  QGroupBox* setting_group = new QGroupBox("Settings");
146  layout_right->addWidget(setting_group);
147  QVBoxLayout* setting_layout = new QVBoxLayout();
148  setting_group->setLayout(setting_layout);
149  QFormLayout* setting_layout_top = new QFormLayout();
150  QGridLayout* setting_layout_bottom = new QGridLayout();
151  setting_layout->insertLayout(0, setting_layout_top);
152  setting_layout->insertLayout(1, setting_layout_bottom);
153 
154  calibration_solver_ = new QComboBox();
155  setting_layout_top->addRow("AX=XB Solver", calibration_solver_);
156 
157  group_name_ = new QComboBox();
158  connect(group_name_, SIGNAL(activated(const QString&)), this, SLOT(planningGroupNameChanged(const QString&)));
159  setting_layout_top->addRow("Planning Group", group_name_);
160 
161  load_joint_state_btn_ = new QPushButton("Load joint states");
162  connect(load_joint_state_btn_, SIGNAL(clicked(bool)), this, SLOT(loadJointStateBtnClicked(bool)));
163  setting_layout_bottom->addWidget(load_joint_state_btn_, 0, 0);
164 
165  save_joint_state_btn_ = new QPushButton("Save joint states");
166  connect(save_joint_state_btn_, SIGNAL(clicked(bool)), this, SLOT(saveJointStateBtnClicked(bool)));
167  setting_layout_bottom->addWidget(save_joint_state_btn_, 0, 1);
168 
169  load_samples_btn_ = new QPushButton("Load samples");
170  connect(load_samples_btn_, SIGNAL(clicked(bool)), this, SLOT(loadSamplesBtnClicked(bool)));
171  setting_layout_bottom->addWidget(load_samples_btn_, 1, 0);
172 
173  save_samples_btn_ = new QPushButton("Save samples");
174  connect(save_samples_btn_, SIGNAL(clicked(bool)), this, SLOT(saveSamplesBtnClicked(bool)));
175  setting_layout_bottom->addWidget(save_samples_btn_, 1, 1);
176 
177  save_camera_pose_btn_ = new QPushButton("Save camera pose");
178  connect(save_camera_pose_btn_, SIGNAL(clicked(bool)), this, SLOT(saveCameraPoseBtnClicked(bool)));
179  setting_layout_bottom->addWidget(save_camera_pose_btn_, 2, 0, 1, 2);
180 
181  // Manual calibration area
182  QGroupBox* manual_cal_group = new QGroupBox("Manual Calibration");
183  layout_right->addWidget(manual_cal_group);
184  QHBoxLayout* control_cal_layout = new QHBoxLayout();
185  manual_cal_group->setLayout(control_cal_layout);
186 
187  take_sample_btn_ = new QPushButton("Take sample");
188  take_sample_btn_->setMinimumHeight(35);
189  connect(take_sample_btn_, SIGNAL(clicked(bool)), this, SLOT(takeSampleBtnClicked(bool)));
190  control_cal_layout->addWidget(take_sample_btn_);
191 
192  reset_sample_btn_ = new QPushButton("Clear samples");
193  reset_sample_btn_->setMinimumHeight(35);
194  connect(reset_sample_btn_, SIGNAL(clicked(bool)), this, SLOT(clearSamplesBtnClicked(bool)));
195  control_cal_layout->addWidget(reset_sample_btn_);
196 
197  solve_btn_ = new QPushButton("Solve");
198  solve_btn_->setMinimumHeight(35);
199  connect(solve_btn_, SIGNAL(clicked(bool)), this, SLOT(solveBtnClicked(bool)));
200  control_cal_layout->addWidget(solve_btn_);
201 
202  // Auto calibration area
203  QGroupBox* auto_cal_group = new QGroupBox("Calibrate With Recorded Joint States");
204  layout_right->addWidget(auto_cal_group);
205  QVBoxLayout* auto_cal_layout = new QVBoxLayout();
206  auto_cal_group->setLayout(auto_cal_layout);
207 
208  QHBoxLayout* auto_btns_layout = new QHBoxLayout();
209  auto_cal_layout->addLayout(auto_btns_layout);
210  auto_plan_btn_ = new QPushButton("Plan");
211  auto_plan_btn_->setMinimumHeight(35);
212  auto_plan_btn_->setToolTip("Plan next calibration pose");
213  connect(auto_plan_btn_, SIGNAL(clicked(bool)), this, SLOT(autoPlanBtnClicked(bool)));
214  auto_btns_layout->addWidget(auto_plan_btn_);
215 
216  auto_execute_btn_ = new QPushButton("Execute");
217  auto_execute_btn_->setMinimumHeight(35);
218  auto_execute_btn_->setToolTip("Execute the planned motion to next calibration pose");
219  connect(auto_execute_btn_, SIGNAL(clicked(bool)), this, SLOT(autoExecuteBtnClicked(bool)));
220  auto_btns_layout->addWidget(auto_execute_btn_);
221 
222  auto_skip_btn_ = new QPushButton("Skip");
223  auto_skip_btn_->setMinimumHeight(35);
224  auto_skip_btn_->setToolTip("Skip the current robot state target");
225  connect(auto_skip_btn_, SIGNAL(clicked(bool)), this, SLOT(autoSkipBtnClicked(bool)));
226  auto_btns_layout->addWidget(auto_skip_btn_);
227 
228  // Initialize handeye solver plugins
229  std::vector<std::string> plugins;
230  if (loadSolverPlugin(plugins))
231  fillSolverTypes(plugins);
232 
233  // Connect PSM and get group names
234  fillPlanningGroupNameComboBox();
235 
236  // Set plan and execution watcher
237  plan_watcher_ = new QFutureWatcher<void>(this);
238  connect(plan_watcher_, &QFutureWatcher<void>::finished, this, &ControlTabWidget::planFinished);
239 
240  execution_watcher_ = new QFutureWatcher<void>(this);
241  connect(execution_watcher_, &QFutureWatcher<void>::finished, this, &ControlTabWidget::executeFinished);
242 
243  // Set initial status
244  calibration_display_->setStatus(rviz::StatusProperty::Ok, "Calibration", "Collect 5 samples to start calibration.");
245 }
246 
247 void ControlTabWidget::loadWidget(const rviz::Config& config)
248 {
249  QString group_name;
250  config.mapGetString("group", &group_name);
251  if (!group_name.isEmpty() && planning_scene_monitor_ && planning_scene_monitor_->getRobotModel())
252  {
253  const std::vector<std::string> groups = planning_scene_monitor_->getRobotModel()->getJointModelGroupNames();
254  std::vector<std::string>::const_iterator it = std::find(groups.begin(), groups.end(), group_name.toStdString());
255  if (it != groups.end())
256  {
257  group_name_->setCurrentText(group_name);
258  Q_EMIT group_name_->activated(group_name);
259  }
260  }
261  QString solver_name;
262  config.mapGetString("solver", &solver_name);
263  if (!solver_name.isEmpty())
264  {
265  for (size_t i = 0; i < calibration_solver_->count(); ++i)
266  {
267  if (calibration_solver_->itemText(i) == solver_name)
268  {
269  calibration_solver_->setCurrentText(solver_name);
270  Q_EMIT calibration_solver_->activated(solver_name);
271  break;
272  }
273  }
274  }
275 }
276 
278 {
279  config.mapSetValue("solver", calibration_solver_->currentText());
280  config.mapSetValue("group", group_name_->currentText());
281 }
282 
283 bool ControlTabWidget::loadSolverPlugin(std::vector<std::string>& plugins)
284 {
286  {
287  try
288  {
290  "moveit_calibration_plugins", "moveit_handeye_calibration::HandEyeSolverBase"));
291  }
293  {
295  "Couldn't create solver plugin loader.");
296  QMessageBox::warning(this, tr("Exception while creating handeye solver plugin loader "), tr(ex.what()));
297  return false;
298  }
299  }
300 
301  // Get available plugins
302  plugins = solver_plugins_loader_->getDeclaredClasses();
303  return !plugins.empty();
304 }
305 
306 bool ControlTabWidget::createSolverInstance(const std::string& plugin_name)
307 {
308  try
309  {
310  solver_ = solver_plugins_loader_->createUniqueInstance(plugin_name);
311  solver_->initialize();
312  }
314  {
315  calibration_display_->setStatus(rviz::StatusProperty::Error, "Calibration", "Couldn't load solver plugin.");
316  ROS_ERROR_STREAM_NAMED(LOGNAME, "Exception while loading handeye solver plugin: " << plugin_name << ex.what());
317  solver_ = nullptr;
318  }
319 
320  return solver_ != nullptr;
321 }
322 
323 void ControlTabWidget::fillSolverTypes(const std::vector<std::string>& plugins)
324 {
325  for (const std::string& plugin : plugins)
326  if (!plugin.empty() && createSolverInstance(plugin))
327  {
328  const std::vector<std::string>& solvers = solver_->getSolverNames();
329  for (const std::string& solver : solvers)
330  {
331  std::string solver_name = plugin + "/" + solver; // solver name format is "plugin_name/solver_name"
332  calibration_solver_->addItem(tr(solver_name.c_str()));
333  }
334  }
335 }
336 
337 std::string ControlTabWidget::parseSolverName(const std::string& solver_name, char delimiter)
338 {
339  std::vector<std::string> tokens;
340  std::string token;
341  std::istringstream tokenStream(solver_name);
342  while (std::getline(tokenStream, token, delimiter))
343  {
344  tokens.push_back(token);
345  }
346  return tokens.back();
347 }
348 
350 {
351  // Store the pair of two tf transforms and calculate camera_robot pose
352  try
353  {
354  geometry_msgs::TransformStamped camera_to_object_tf;
355  geometry_msgs::TransformStamped base_to_eef_tf;
356 
357  // Get the transform of the object w.r.t the camera
358  camera_to_object_tf = tf_buffer_->lookupTransform(frame_names_["sensor"], frame_names_["object"], ros::Time(0));
359 
360  // Get the transform of the end-effector w.r.t the robot base
361  base_to_eef_tf = tf_buffer_->lookupTransform(frame_names_["base"], frame_names_["eef"], ros::Time(0));
362 
363  // Renormalize quaternions, to avoid numerical issues
364  tf2::Quaternion tf2_quat;
365  tf2::fromMsg(camera_to_object_tf.transform.rotation, tf2_quat);
366  tf2_quat.normalize();
367  camera_to_object_tf.transform.rotation = tf2::toMsg(tf2_quat);
368  tf2::fromMsg(base_to_eef_tf.transform.rotation, tf2_quat);
369  tf2_quat.normalize();
370  base_to_eef_tf.transform.rotation = tf2::toMsg(tf2_quat);
371 
372  // save the pose samples
373  effector_wrt_world_.push_back(tf2::transformToEigen(base_to_eef_tf));
374  object_wrt_sensor_.push_back(tf2::transformToEigen(camera_to_object_tf));
375 
376  ControlTabWidget::addPoseSampleToTreeView(camera_to_object_tf, base_to_eef_tf, effector_wrt_world_.size());
377  }
378  catch (tf2::TransformException& e)
379  {
380  ROS_WARN("TF exception: %s", e.what());
381  return false;
382  }
383 
384  return true;
385 }
386 
387 void ControlTabWidget::solveBtnClicked(bool clicked)
388 {
390 }
391 
393 {
394  if (solver_ && !calibration_solver_->currentText().isEmpty())
395  {
396  std::string error_message;
398  parseSolverName(calibration_solver_->currentText().toStdString(), '/'), &error_message);
399  if (res)
400  {
401  camera_robot_pose_ = solver_->getCameraRobotPose();
402 
403  // Update camera pose guess in context tab
404  Eigen::Vector3d t = camera_robot_pose_.translation();
405  Eigen::Vector3d r = camera_robot_pose_.rotation().eulerAngles(0, 1, 2);
406  Q_EMIT sensorPoseUpdate(t[0], t[1], t[2], r[0], r[1], r[2]);
407 
408  // Calculate reprojection error
409  const auto& reproj_err = solver_->getReprojectionError(effector_wrt_world_, object_wrt_sensor_,
411  std::ostringstream reproj_err_text;
412  reproj_err_text << "Reprojection error:\n" << reproj_err.first << " m, " << reproj_err.second << " rad";
413  ROS_WARN_NAMED(LOGNAME, "%s", reproj_err_text.str().c_str());
414  reprojection_error_label_->setText(QString(reproj_err_text.str().c_str()));
415 
416  // Publish camera pose tf
417  const std::string& from_frame = frame_names_[from_frame_tag_];
418  const std::string& to_frame = frame_names_["sensor"];
419  if (!from_frame.empty() && !to_frame.empty())
420  {
421  tf_tools_->clearAllTransforms();
422  calibration_display_->setStatus(rviz::StatusProperty::Ok, "Calibration", "Calibration successful.");
423  ROS_INFO_STREAM_NAMED(LOGNAME, "Publish camera transformation" << std::endl
424  << camera_robot_pose_.matrix() << std::endl
425  << "from " << from_frame_tag_ << " frame '"
426  << from_frame << "'"
427  << "to sensor frame '" << to_frame << "'");
428  return tf_tools_->publishTransform(camera_robot_pose_, from_frame, to_frame);
429  }
430  else
431  {
432  // CLI warning message without formatting
433  {
434  std::stringstream warn_msg;
435  warn_msg << "Found camera pose:" << std::endl
436  << camera_robot_pose_.matrix() << std::endl
437  << "but " << from_frame_tag_ << " or sensor frame is undefined.";
438  ROS_ERROR_STREAM_NAMED(LOGNAME, warn_msg.str());
439  }
440  // GUI warning message with formatting
441  {
442  std::stringstream warn_msg;
443  warn_msg << "Found camera pose:<pre>" << std::endl
444  << camera_robot_pose_.matrix() << std::endl
445  << "</pre>but <b>" << from_frame_tag_ << "</b> or <b>sensor</b> frame is undefined.";
446  QMessageBox::warning(this, "Solver Failed", QString::fromStdString(warn_msg.str()));
447  }
449  "Calibration successful but frames are undefined.");
450  return false;
451  }
452  }
453  else
454  {
455  calibration_display_->setStatus(rviz::StatusProperty::Error, "Calibration", "Solver failed.");
456  QMessageBox::warning(this, tr("Solver Failed"), tr((std::string("Error: ") + error_message).c_str()));
457  return false;
458  }
459  }
460  else
461  {
462  calibration_display_->setStatus(rviz::StatusProperty::Error, "Calibration", "No solver available.");
463  QMessageBox::warning(this, tr("No Solver Available"), tr("No available handeye calibration solver instance."));
464  return false;
465  }
466 }
467 
469 {
470  // All of four frame names needed for getting the pair of two tf transforms
471  if (frame_names_["sensor"].empty() || frame_names_["object"].empty() || frame_names_["base"].empty() ||
472  frame_names_["eef"].empty())
473  {
474  QMessageBox::warning(this, tr("Empty Frame Name"), tr("At least one of the four frame names is empty."));
475  return true;
476  }
477  return false;
478 }
479 
481 {
482  if (joint_names_.empty() || joint_states_.empty())
483  return false;
484 
485  for (const std::vector<double>& state : joint_states_)
486  if (state.size() != joint_names_.size())
487  return false;
488 
489  return true;
490 }
491 
493 {
494  tf_tools_ = tf_pub;
495 }
496 
497 void ControlTabWidget::addPoseSampleToTreeView(const geometry_msgs::TransformStamped& camera_to_object_tf,
498  const geometry_msgs::TransformStamped& base_to_eef_tf, int id)
499 {
500  std::string item_name = "Sample " + std::to_string(id);
501  QStandardItem* parent = new QStandardItem(QString(item_name.c_str()));
502  tree_view_model_->appendRow(parent);
503 
504  std::ostringstream ss;
505 
506  QStandardItem* child_1 = new QStandardItem("TF base-to-eef");
507  ss << base_to_eef_tf.transform;
508  child_1->appendRow(new QStandardItem(ss.str().c_str()));
509  parent->appendRow(child_1);
510 
511  QStandardItem* child_2 = new QStandardItem("TF camera-to-target");
512  ss.str("");
513  ss << camera_to_object_tf.transform;
514  child_2->appendRow(new QStandardItem(ss.str().c_str()));
515  parent->appendRow(child_2);
516 }
517 
519 {
520  if (0 <= index && index <= 1)
521  {
523  switch (sensor_mount_type_)
524  {
525  case mhc::EYE_TO_HAND:
526  from_frame_tag_ = "base";
527  break;
528  case mhc::EYE_IN_HAND:
530  break;
531  default:
532  ROS_ERROR_STREAM_NAMED(LOGNAME, "Error sensor mount type.");
533  break;
534  }
535  }
536 }
537 
538 void ControlTabWidget::updateFrameNames(std::map<std::string, std::string> names)
539 {
540  frame_names_ = names;
541  ROS_DEBUG("Frame names changed:");
542  for (const std::pair<const std::string, std::string>& name : frame_names_)
543  ROS_DEBUG_STREAM(name.first << " : " << name.second);
544 }
545 
547 {
549  return;
550 
551  if (effector_wrt_world_.size() == object_wrt_sensor_.size() && effector_wrt_world_.size() > 4)
552  if (!solveCameraRobotPose())
553  return;
554 
555  // Save the joint values of current robot state
557  {
558  planning_scene_monitor_->waitForCurrentRobotState(ros::Time::now(), 0.1);
561  if (ps)
562  {
563  const robot_state::RobotState& state = ps->getCurrentState();
564  const moveit::core::JointModelGroup* jmg = state.getJointModelGroup(group_name_->currentText().toStdString());
565  const std::vector<std::string>& names = jmg->getActiveJointModelNames();
566  if (joint_names_.size() != names.size() || joint_names_ != names)
567  {
568  joint_names_.clear();
569  joint_states_.clear();
570  }
571  std::vector<double> state_joint_values;
572  state.copyJointGroupPositions(jmg, state_joint_values);
573  if (names.size() == state_joint_values.size())
574  {
575  joint_names_ = names;
576  joint_states_.push_back(state_joint_values);
578  }
579  }
580  }
581 }
582 
584 {
585  // Clear recorded transforms
586  effector_wrt_world_.clear();
587  object_wrt_sensor_.clear();
588  tree_view_model_->clear();
589 
590  // Clear recorded joint states
591  joint_states_.clear();
594 }
595 
597 {
598  std::string& from_frame = frame_names_[from_frame_tag_];
599  std::string& to_frame = frame_names_["sensor"];
600 
601  if (from_frame.empty() || to_frame.empty())
602  {
603  QMessageBox::warning(this, tr("Empty Frame Name"),
604  tr("Make sure you have selected the correct frames in the Context tab."));
605  return;
606  }
607 
608  // DontUseNativeDialog option set to avoid this issue: https://github.com/ros-planning/moveit/issues/2357
609  QString file_name =
610  QFileDialog::getSaveFileName(this, tr("Save Camera Robot Pose"), "", tr("Target File (*.launch);;All Files (*)"),
611  nullptr, QFileDialog::DontUseNativeDialog);
612 
613  if (file_name.isEmpty())
614  return;
615 
616  if (!file_name.endsWith(".launch"))
617  file_name += ".launch";
618 
619  QFile file(file_name);
620  if (!file.open(QIODevice::WriteOnly))
621  {
622  QMessageBox::warning(this, tr("Unable to open file"), file.errorString());
623  return;
624  }
625 
626  QTextStream out(&file);
627 
628  Eigen::Vector3d t = camera_robot_pose_.translation();
629  Eigen::Quaterniond r_quat(camera_robot_pose_.rotation());
630  Eigen::Vector3d r_euler = camera_robot_pose_.rotation().eulerAngles(0, 1, 2);
631  std::stringstream ss;
632  ss << "<launch>" << std::endl;
633  ss << " <!-- The rpy in the comment uses the extrinsic XYZ convention, which is the same as is used in a URDF. See"
634  << std::endl;
635  ss << " http://wiki.ros.org/geometry2/RotationMethods and https://en.wikipedia.org/wiki/Euler_angles for more "
636  "info. -->"
637  << std::endl;
638  ss << " <!-- xyz=\"" << t[0] << " " << t[1] << " " << t[2] << "\" rpy=\"" << r_euler[0] << " " << r_euler[1] << " "
639  << r_euler[2] << "\" -->" << std::endl;
640  ss << " <node pkg=\"tf2_ros\" type=\"static_transform_publisher\" name=\"camera_link_broadcaster\"" << std::endl;
641  ss << " args=\"" << t[0] << " " << t[1] << " " << t[2] << " " << r_quat.x() << " " << r_quat.y() << " "
642  << r_quat.z() << " " << r_quat.w() << " " << from_frame << " " << to_frame << "\" />" << std::endl;
643  ss << "</launch>" << std::endl;
644  out << ss.str().c_str();
645 }
646 
647 void ControlTabWidget::planningGroupNameChanged(const QString& text)
648 {
649  if (!text.isEmpty())
650  {
651  setGroupName(text.toStdString());
652  }
653  else
654  {
655  QMessageBox::warning(this, tr("Invalid Group Name"), "Group name is empty");
656  }
657 }
658 
659 void ControlTabWidget::setGroupName(const std::string& group_name)
660 {
661  if (move_group_ && move_group_->getName() == group_name)
662  return;
663 
664  try
665  {
669 
670  // Clear the joint values from any previous group
671  joint_states_.clear();
673  }
674  catch (std::exception& ex)
675  {
676  ROS_ERROR_NAMED(LOGNAME, "%s", ex.what());
677  }
678 }
679 
681 {
682  group_name_->clear();
683  // Fill in available planning group names
685  new planning_scene_monitor::PlanningSceneMonitor("robot_description", tf_buffer_, "planning_scene_monitor"));
687  {
692  if (planning_scene_monitor_->requestPlanningSceneState(service_name))
693  {
694  const robot_model::RobotModelConstPtr& kmodel = planning_scene_monitor_->getRobotModel();
695  for (const std::string& group_name : kmodel->getJointModelGroupNames())
696  {
697  group_name_->addItem(group_name.c_str());
698  }
699  if (!group_name_->currentText().isEmpty())
700  setGroupName(group_name_->currentText().toStdString());
701  }
702  }
703 }
704 
706 {
707  if (!checkJointStates())
708  {
709  QMessageBox::warning(this, tr("Error"), tr("No joint states or joint state dosen't match joint names."));
710  return;
711  }
712 
713  // DontUseNativeDialog option set to avoid this issue: https://github.com/ros-planning/moveit/issues/2357
714  QString file_name =
715  QFileDialog::getSaveFileName(this, tr("Save Joint States"), "", tr("Target File (*.yaml);;All Files (*)"),
716  nullptr, QFileDialog::DontUseNativeDialog);
717 
718  if (file_name.isEmpty())
719  return;
720 
721  if (!file_name.endsWith(".yaml"))
722  file_name += ".yaml";
723 
724  QFile file(file_name);
725  if (!file.open(QIODevice::WriteOnly))
726  {
727  QMessageBox::warning(this, tr("Unable to open file"), file.errorString());
728  return;
729  }
730 
731  YAML::Emitter emitter;
732  emitter << YAML::BeginMap;
733 
734  // Joint Names
735  emitter << YAML::Key << "joint_names";
736  emitter << YAML::Value << YAML::BeginSeq;
737  for (size_t i = 0; i < joint_names_.size(); ++i)
738  emitter << YAML::Value << joint_names_[i];
739  emitter << YAML::EndSeq;
740 
741  // Joint Values
742  emitter << YAML::Key << "joint_values";
743  emitter << YAML::Value << YAML::BeginSeq;
744  for (size_t i = 0; i < joint_states_.size(); ++i)
745  {
746  emitter << YAML::BeginSeq;
747  for (size_t j = 0; j < joint_states_[i].size(); ++j)
748  emitter << YAML::Value << joint_states_[i][j];
749  emitter << YAML::EndSeq;
750  }
751  emitter << YAML::EndSeq;
752 
753  emitter << YAML::EndMap;
754 
755  QTextStream out(&file);
756  out << emitter.c_str();
757 }
758 
760 {
761  QString file_name = QFileDialog::getOpenFileName(this, tr("Load Samples"), "", tr("Target File (*.yaml)"), nullptr,
762  QFileDialog::DontUseNativeDialog);
763 
764  if (file_name.isEmpty())
765  return;
766 
767  effector_wrt_world_.clear();
768  object_wrt_sensor_.clear();
769 
770  // transformations are serialised as 4x4 row-major matrices
771  typedef Eigen::Matrix<double, 4, 4, Eigen::RowMajor> Matrix4d_rm;
772 
773  YAML::Node yaml_states = YAML::LoadFile(file_name.toStdString());
774  try
775  {
776  for (std::size_t i = 0; i < yaml_states.size(); i++)
777  {
778  effector_wrt_world_.emplace_back(
779  Eigen::Map<const Matrix4d_rm>(yaml_states[i]["effector_wrt_world"].as<std::vector<double>>().data()));
780 
781  object_wrt_sensor_.emplace_back(
782  Eigen::Map<const Matrix4d_rm>(yaml_states[i]["object_wrt_sensor"].as<std::vector<double>>().data()));
783 
784  // add to GUI
787  effector_wrt_world_.size());
788  }
789 
790  auto_progress_->setMax(yaml_states.size());
791  auto_progress_->setValue(yaml_states.size());
792  }
793  catch (const YAML::Exception& e)
794  {
795  QMessageBox::critical(this, "YAML Exception",
796  QString::fromStdString("YAML exception: " + std::string(e.what()) +
797  "\nCheck that the sample file has the correct format."));
798  }
799 }
800 
802 {
803  if (effector_wrt_world_.size() != object_wrt_sensor_.size())
804  {
805  ROS_ERROR_STREAM_NAMED(LOGNAME, "Different number of poses");
806  return;
807  }
808 
809  // DontUseNativeDialog option set to avoid this issue: https://github.com/ros-planning/moveit/issues/2357
810  QString file_name =
811  QFileDialog::getSaveFileName(this, tr("Save Samples"), "", tr("Target File (*.yaml);;All Files (*)"), nullptr,
812  QFileDialog::DontUseNativeDialog);
813 
814  if (file_name.isEmpty())
815  return;
816 
817  if (!file_name.endsWith(".yaml"))
818  file_name += ".yaml";
819 
820  QFile file(file_name);
821  if (!file.open(QIODevice::WriteOnly))
822  {
823  QMessageBox::warning(this, tr("Unable to open file"), file.errorString());
824  return;
825  }
826 
827  YAML::Emitter emitter;
828  emitter << YAML::BeginSeq;
829  for (size_t i = 0; i < effector_wrt_world_.size(); i++)
830  {
831  emitter << YAML::Value << YAML::BeginMap;
832  emitter << YAML::Key << "effector_wrt_world";
833  emitter << YAML::Value << YAML::BeginSeq;
834  for (size_t y = 0; y < 4; y++)
835  {
836  for (size_t x = 0; x < 4; x++)
837  {
838  emitter << YAML::Value << effector_wrt_world_[i](y, x);
839  }
840  }
841  emitter << YAML::EndSeq;
842  emitter << YAML::Key << "object_wrt_sensor";
843  emitter << YAML::Value << YAML::BeginSeq;
844  for (size_t y = 0; y < 4; y++)
845  {
846  for (size_t x = 0; x < 4; x++)
847  {
848  emitter << YAML::Value << object_wrt_sensor_[i](y, x);
849  }
850  }
851  emitter << YAML::EndSeq;
852  emitter << YAML::EndMap;
853  }
854  emitter << YAML::EndSeq;
855 
856  QTextStream out(&file);
857  out << emitter.c_str();
858 }
859 
861 {
862  // DontUseNativeDialog option set to avoid this issue: https://github.com/ros-planning/moveit/issues/2357
863  QString file_name =
864  QFileDialog::getOpenFileName(this, tr("Load Joint States"), "", tr("Target File (*.yaml);;All Files (*)"),
865  nullptr, QFileDialog::DontUseNativeDialog);
866 
867  if (file_name.isEmpty() || !file_name.endsWith(".yaml"))
868  return;
869 
870  QFile file(file_name);
871  if (!file.open(QIODevice::ReadOnly))
872  {
873  QMessageBox::warning(this, tr("Unable to open file"), file.errorString());
874  return;
875  }
876 
877  // Begin parsing
878  try
879  {
880  ROS_DEBUG_STREAM_NAMED(LOGNAME, "Load joint states from file: " << file_name.toStdString().c_str());
881  YAML::Node doc = YAML::LoadFile(file_name.toStdString());
882  if (!doc.IsMap())
883  return;
884 
885  // Read joint names
886  const YAML::Node& names = doc["joint_names"];
887  if (!names.IsNull() && names.IsSequence())
888  {
889  joint_names_.clear();
890  for (YAML::const_iterator it = names.begin(); it != names.end(); ++it)
891  joint_names_.push_back(it->as<std::string>());
892  }
893  else
894  {
895  ROS_ERROR_STREAM_NAMED(LOGNAME, "Can't find 'joint_names' in the openned file.");
896  return;
897  }
898 
899  // Read joint values
900  const YAML::Node& values = doc["joint_values"];
901  if (!values.IsNull() && values.IsSequence())
902  {
903  joint_states_.clear();
904  for (YAML::const_iterator state_it = values.begin(); state_it != values.end(); ++state_it)
905  {
906  std::vector<double> jv;
907  if (!state_it->IsNull() && state_it->IsSequence())
908  for (YAML::const_iterator joint_it = state_it->begin(); joint_it != state_it->end(); ++joint_it)
909  jv.push_back(joint_it->as<double>());
910  if (jv.size() == joint_names_.size())
911  joint_states_.push_back(jv);
912  }
913  }
914  else
915  {
916  ROS_ERROR_STREAM_NAMED(LOGNAME, "Can't find 'joint_values' in the openned file.");
917  return;
918  }
919  }
920  catch (YAML::ParserException& e) // Catch errors
921  {
922  ROS_ERROR_STREAM_NAMED(LOGNAME, e.what());
923  return;
924  }
925 
926  if (joint_states_.size() > 0)
927  {
930  }
931  ROS_INFO_STREAM_NAMED(LOGNAME, "Loaded and parsed: " << file_name.toStdString());
932 }
933 
934 void ControlTabWidget::autoPlanBtnClicked(bool clicked)
935 {
936  auto_plan_btn_->setEnabled(false);
937  plan_watcher_->setFuture(QtConcurrent::run(this, &ControlTabWidget::computePlan));
938 }
939 
941 {
943  int max = auto_progress_->bar_->maximum();
944 
945  if (max != joint_states_.size() || auto_progress_->getValue() == max)
946  {
948  return;
949  }
950 
951  if (!checkJointStates())
952  {
954  return;
955  }
956 
958  {
960  return;
961  }
962 
963  if (!move_group_)
964  {
966  return;
967  }
968 
969  if (move_group_->getActiveJoints() != joint_names_)
970  {
972  return;
973  }
974 
975  // Get current joint state as start state
976  robot_state::RobotStatePtr start_state = move_group_->getCurrentState();
977  planning_scene_monitor_->waitForCurrentRobotState(ros::Time::now(), 0.1);
980  if (ps)
981  start_state.reset(new robot_state::RobotState(ps->getCurrentState()));
982 
983  // Plan motion to the recorded joint state target
984  if (auto_progress_->getValue() < joint_states_.size())
985  {
986  move_group_->setStartState(*start_state);
987  move_group_->setJointValueTarget(joint_states_[auto_progress_->getValue()]);
988  move_group_->setMaxVelocityScalingFactor(0.5);
989  move_group_->setMaxAccelerationScalingFactor(0.5);
991  planning_res_ = (move_group_->plan(*current_plan_) == moveit::planning_interface::MoveItErrorCode::SUCCESS) ?
994 
996  ROS_DEBUG_STREAM_NAMED(LOGNAME, "Planning succeed.");
997  else
998  ROS_ERROR_STREAM_NAMED(LOGNAME, "Planning failed.");
999  }
1000 }
1001 
1002 void ControlTabWidget::autoExecuteBtnClicked(bool clicked)
1003 {
1004  if (plan_watcher_->isRunning())
1005  {
1006  plan_watcher_->waitForFinished();
1007  }
1008 
1009  auto_execute_btn_->setEnabled(false);
1010  execution_watcher_->setFuture(QtConcurrent::run(this, &ControlTabWidget::computeExecution));
1011 }
1012 
1014 {
1015  if (move_group_ && current_plan_)
1016  planning_res_ = (move_group_->execute(*current_plan_) == moveit::planning_interface::MoveItErrorCode::SUCCESS) ?
1019 
1021  {
1022  ROS_DEBUG_STREAM_NAMED(LOGNAME, "Execution succeed.");
1023  }
1024  else
1025  ROS_ERROR_STREAM_NAMED(LOGNAME, "Execution failed.");
1026 }
1027 
1029 {
1030  auto_plan_btn_->setEnabled(true);
1031  switch (planning_res_)
1032  {
1034  QMessageBox::warning(this, tr("Error"),
1035  tr("Could not compute plan. No more prerecorded joint states to execute."));
1036  break;
1038  QMessageBox::warning(this, tr("Error"),
1039  tr("Could not compute plan. Invalid joint states (names wrong or missing)."));
1040  break;
1042  QMessageBox::warning(this, tr("Error"), tr("Could not compute plan. No planning scene monitor."));
1043  break;
1045  QMessageBox::warning(this, tr("Error"), tr("Could not compute plan. Missing move_group."));
1046  break;
1048  QMessageBox::warning(
1049  this, tr("Error"),
1050  tr("Could not compute plan. Joint names for recorded state do not match names from current planning group."));
1051  break;
1053  QMessageBox::warning(this, tr("Error"), tr("Could not compute plan. Planning failed."));
1054  break;
1056  break;
1057  }
1058  ROS_DEBUG_NAMED(LOGNAME, "Plan finished");
1059 }
1062 {
1063  auto_execute_btn_->setEnabled(true);
1065  {
1067  if (!frameNamesEmpty())
1069 
1070  if (effector_wrt_world_.size() == object_wrt_sensor_.size() && effector_wrt_world_.size() > 4)
1072  }
1073  ROS_DEBUG_NAMED(LOGNAME, "Execution finished");
1074 }
1075 
1076 void ControlTabWidget::autoSkipBtnClicked(bool clicked)
1077 {
1079 }
1080 
1081 } // namespace moveit_rviz_plugin
moveit_rviz_plugin::ProgressBarWidget::setMin
void setMin(int value)
Definition: handeye_control_widget.cpp:114
moveit_rviz_plugin::ControlTabWidget::saveWidget
void saveWidget(rviz::Config &config)
Definition: handeye_control_widget.cpp:309
handeye_control_widget.h
moveit_rviz_plugin::ControlTabWidget::reprojection_error_label_
QLabel * reprojection_error_label_
Definition: handeye_control_widget.h:242
moveit_rviz_plugin::ControlTabWidget::FAILURE_NO_PSM
@ FAILURE_NO_PSM
Definition: handeye_control_widget.h:142
Eigen
moveit_rviz_plugin::ControlTabWidget::saveJointStateBtnClicked
void saveJointStateBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:737
moveit_rviz_plugin::ControlTabWidget::joint_names_
std::vector< std::string > joint_names_
Definition: handeye_control_widget.h:283
moveit_rviz_plugin::ControlTabWidget::autoExecuteBtnClicked
void autoExecuteBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:1034
planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_SERVICE
static const std::string DEFAULT_PLANNING_SCENE_SERVICE
moveit_rviz_plugin::ProgressBarWidget::setValue
void setValue(int value)
Definition: handeye_control_widget.cpp:119
moveit_rviz_plugin::ControlTabWidget::clearSamplesBtnClicked
void clearSamplesBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:615
moveit_rviz_plugin::ControlTabWidget::FAILURE_NO_MOVE_GROUP
@ FAILURE_NO_MOVE_GROUP
Definition: handeye_control_widget.h:143
moveit_rviz_plugin::HandEyeCalibrationDisplay::planning_scene_topic_property_
rviz::RosTopicProperty * planning_scene_topic_property_
Definition: handeye_calibration_display.h:132
moveit_rviz_plugin::ProgressBarWidget::max_label_
QLabel * max_label_
Definition: handeye_control_widget.h:129
boost::shared_ptr< TFVisualTools >
moveit_rviz_plugin::ControlTabWidget::setGroupName
void setGroupName(const std::string &group_name)
Definition: handeye_control_widget.cpp:691
moveit_rviz_plugin::ControlTabWidget::UpdateSensorMountType
void UpdateSensorMountType(int index)
Definition: handeye_control_widget.cpp:550
moveit_rviz_plugin::ControlTabWidget::loadJointStateBtnClicked
void loadJointStateBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:892
moveit::planning_interface::MoveGroupInterface::Plan
rviz::StatusProperty::Error
Error
moveit::core::JointModelGroup::getActiveJointModelNames
const std::vector< std::string > & getActiveJointModelNames() const
moveit::planning_interface::MoveGroupInterface
moveit_rviz_plugin::ControlTabWidget::ControlTabWidget
ControlTabWidget(HandEyeCalibrationDisplay *pdisplay, QWidget *parent=Q_NULLPTR)
Definition: handeye_control_widget.cpp:130
moveit_rviz_plugin::ControlTabWidget::calibration_solver_
QComboBox * calibration_solver_
Definition: handeye_control_widget.h:245
tf2::fromMsg
void fromMsg(const A &, B &b)
ROS_DEBUG_STREAM_NAMED
#define ROS_DEBUG_STREAM_NAMED(name, args)
moveit_rviz_plugin::ControlTabWidget::takeSampleBtnClicked
void takeSampleBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:578
y
y
moveit_rviz_plugin::ControlTabWidget::tree_view_model_
QStandardItemModel * tree_view_model_
Definition: handeye_control_widget.h:243
moveit_rviz_plugin::ControlTabWidget::autoPlanBtnClicked
void autoPlanBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:966
r
r
data
data
ROS_DEBUG
#define ROS_DEBUG(...)
moveit_rviz_plugin::ControlTabWidget::loadSolverPlugin
bool loadSolverPlugin(std::vector< std::string > &plugins)
Definition: handeye_control_widget.cpp:315
moveit_rviz_plugin::ControlTabWidget::planning_scene_monitor_
planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_
Definition: handeye_control_widget.h:299
tf2::Quaternion::normalize
Quaternion & normalize()
moveit_rviz_plugin::ControlTabWidget::solveBtnClicked
void solveBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:419
ROS_ERROR_NAMED
#define ROS_ERROR_NAMED(name,...)
moveit_rviz_plugin::ControlTabWidget::computeExecution
void computeExecution()
Definition: handeye_control_widget.cpp:1045
moveit_rviz_plugin::ControlTabWidget::SUCCESS
@ SUCCESS
Definition: handeye_control_widget.h:139
EYE_TO_HAND
EYE_TO_HAND
moveit_rviz_plugin::ControlTabWidget::fillSolverTypes
void fillSolverTypes(const std::vector< std::string > &plugins)
Definition: handeye_control_widget.cpp:355
ROS_DEBUG_STREAM
#define ROS_DEBUG_STREAM(args)
moveit_rviz_plugin::ControlTabWidget::FAILURE_WRONG_MOVE_GROUP
@ FAILURE_WRONG_MOVE_GROUP
Definition: handeye_control_widget.h:144
moveit_rviz_plugin::ControlTabWidget::createSolverInstance
bool createSolverInstance(const std::string &plugin_name)
Definition: handeye_control_widget.cpp:338
planning_scene_monitor::PlanningSceneMonitor
moveit_rviz_plugin::ControlTabWidget::addPoseSampleToTreeView
void addPoseSampleToTreeView(const geometry_msgs::TransformStamped &camera_to_object_tf, const geometry_msgs::TransformStamped &base_to_eef_tf, int id)
Definition: handeye_control_widget.cpp:529
moveit::planning_interface::MoveGroupInterface::Options
moveit_rviz_plugin::ControlTabWidget::autoSkipBtnClicked
void autoSkipBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:1108
tf2::eigenToTransform
geometry_msgs::TransformStamped eigenToTransform(const Eigen::Affine3d &T)
moveit_rviz_plugin::ControlTabWidget::solver_
pluginlib::UniquePtr< moveit_handeye_calibration::HandEyeSolverBase > solver_
Definition: handeye_control_widget.h:298
moveit_rviz_plugin::ControlTabWidget::execution_watcher_
QFutureWatcher< void > * execution_watcher_
Definition: handeye_control_widget.h:269
pluginlib::PluginlibException
SUCCESS
SUCCESS
moveit_rviz_plugin::ProgressBarWidget::value_label_
QLabel * value_label_
Definition: handeye_control_widget.h:128
moveit_rviz_plugin::ProgressBarWidget::ProgressBarWidget
ProgressBarWidget(QWidget *parent, int min=0, int max=0, int value=0)
Definition: handeye_control_widget.cpp:76
moveit_rviz_plugin::ProgressBarWidget::getValue
int getValue()
Definition: handeye_control_widget.cpp:125
rviz::Display::setStatus
virtual void setStatus(StatusProperty::Level level, const QString &name, const QString &text)
moveit_rviz_plugin::ControlTabWidget::saveCameraPoseBtnClicked
void saveCameraPoseBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:628
moveit_rviz_plugin::LOGNAME
const std::string LOGNAME
Definition: handeye_context_widget.cpp:74
res
res
moveit_rviz_plugin::ControlTabWidget::checkJointStates
bool checkJointStates()
Definition: handeye_control_widget.cpp:512
moveit_rviz_plugin::ControlTabWidget
Definition: handeye_control_widget.h:133
tf2_ros
moveit_rviz_plugin::ControlTabWidget::fillPlanningGroupNameComboBox
void fillPlanningGroupNameComboBox()
Definition: handeye_control_widget.cpp:712
ROS_DEBUG_NAMED
#define ROS_DEBUG_NAMED(name,...)
moveit_rviz_plugin::ControlTabWidget::FAILURE_PLAN_FAILED
@ FAILURE_PLAN_FAILED
Definition: handeye_control_widget.h:145
moveit_rviz_plugin::ControlTabWidget::planning_res_
PLANNING_RESULT planning_res_
Definition: handeye_control_widget.h:285
moveit_rviz_plugin::ControlTabWidget::auto_execute_btn_
QPushButton * auto_execute_btn_
Definition: handeye_control_widget.h:262
ROS_ERROR_STREAM_NAMED
#define ROS_ERROR_STREAM_NAMED(name, args)
moveit_handeye_calibration::SensorMountType
SensorMountType
rviz::StringProperty::getStdString
std::string getStdString()
rviz::StatusProperty::Ok
Ok
rviz::StatusProperty::Warn
Warn
moveit_rviz_plugin::ControlTabWidget::computePlan
void computePlan()
Definition: handeye_control_widget.cpp:972
moveit_rviz_plugin::ControlTabWidget::frame_names_
std::map< std::string, std::string > frame_names_
Definition: handeye_control_widget.h:276
moveit_rviz_plugin::ControlTabWidget::camera_robot_pose_
Eigen::Isometry3d camera_robot_pose_
Definition: handeye_control_widget.h:281
moveit_rviz_plugin::ControlTabWidget::sensorPoseUpdate
void sensorPoseUpdate(double x, double y, double z, double rx, double ry, double rz)
moveit_rviz_plugin::ControlTabWidget::auto_progress_
ProgressBarWidget * auto_progress_
Definition: handeye_control_widget.h:266
value
float value
ROS_WARN
#define ROS_WARN(...)
moveit_rviz_plugin::ControlTabWidget::takeTransformSamples
bool takeTransformSamples()
Definition: handeye_control_widget.cpp:381
x
x
moveit_rviz_plugin::ControlTabWidget::updateFrameNames
void updateFrameNames(std::map< std::string, std::string > names)
Definition: handeye_control_widget.cpp:570
moveit_rviz_plugin::ControlTabWidget::loadSamplesBtnClicked
void loadSamplesBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:791
moveit_rviz_plugin::ControlTabWidget::frameNamesEmpty
bool frameNamesEmpty()
Definition: handeye_control_widget.cpp:500
moveit_rviz_plugin::ControlTabWidget::loadWidget
void loadWidget(const rviz::Config &config)
Definition: handeye_control_widget.cpp:279
Identity
Identity
moveit_rviz_plugin::ControlTabWidget::sensor_mount_type_
mhc::SensorMountType sensor_mount_type_
Definition: handeye_control_widget.h:275
pluginlib::ClassLoader
name
name
moveit_rviz_plugin::ControlTabWidget::tf_buffer_
std::shared_ptr< tf2_ros::Buffer > tf_buffer_
Definition: handeye_control_widget.h:294
moveit_rviz_plugin::ControlTabWidget::planFinished
void planFinished()
Definition: handeye_control_widget.cpp:1060
tf2::transformToEigen
Eigen::Isometry3d transformToEigen(const geometry_msgs::Transform &t)
moveit_rviz_plugin::ControlTabWidget::planningGroupNameChanged
void planningGroupNameChanged(const QString &text)
Definition: handeye_control_widget.cpp:679
text
text
moveit_rviz_plugin::ControlTabWidget::saveSamplesBtnClicked
void saveSamplesBtnClicked(bool clicked)
Definition: handeye_control_widget.cpp:833
moveit_rviz_plugin
moveit_rviz_plugin::ControlTabWidget::setTFTool
void setTFTool(rviz_visual_tools::TFVisualToolsPtr &tf_pub)
Definition: handeye_control_widget.cpp:524
moveit_rviz_plugin::ControlTabWidget::group_name_
QComboBox * group_name_
Definition: handeye_control_widget.h:260
moveit_rviz_plugin::ControlTabWidget::from_frame_tag_
std::string from_frame_tag_
Definition: handeye_control_widget.h:280
ros::names::append
ROSCPP_DECL std::string append(const std::string &left, const std::string &right)
moveit_rviz_plugin::ProgressBarWidget::setMax
void setMax(int value)
Definition: handeye_control_widget.cpp:107
moveit_rviz_plugin::ProgressBarWidget::bar_
QProgressBar * bar_
Definition: handeye_control_widget.h:130
ros::Time
moveit_rviz_plugin::ControlTabWidget::solver_plugins_loader_
std::unique_ptr< pluginlib::ClassLoader< moveit_handeye_calibration::HandEyeSolverBase > > solver_plugins_loader_
Definition: handeye_control_widget.h:297
values
std::vector< double > values
moveit_handeye_calibration
moveit_rviz_plugin::ControlTabWidget::tf_tools_
rviz_visual_tools::TFVisualToolsPtr tf_tools_
Definition: handeye_control_widget.h:296
planning_scene_monitor::LockedPlanningSceneRO
moveit_rviz_plugin::ControlTabWidget::joint_states_
std::vector< std::vector< double > > joint_states_
Definition: handeye_control_widget.h:282
moveit_rviz_plugin::ControlTabWidget::move_group_
moveit::planning_interface::MoveGroupInterfacePtr move_group_
Definition: handeye_control_widget.h:300
moveit_rviz_plugin::ControlTabWidget::FAILURE_NO_JOINT_STATE
@ FAILURE_NO_JOINT_STATE
Definition: handeye_control_widget.h:140
ROS_WARN_NAMED
#define ROS_WARN_NAMED(name,...)
moveit::core::JointModelGroup
index
unsigned int index
tf2::Quaternion
ROS_INFO_STREAM_NAMED
#define ROS_INFO_STREAM_NAMED(name, args)
tf2_geometry_msgs.h
tf2::toMsg
B toMsg(const A &a)
moveit_rviz_plugin::ControlTabWidget::current_plan_
moveit::planning_interface::MoveGroupInterface::PlanPtr current_plan_
Definition: handeye_control_widget.h:301
moveit_rviz_plugin::ControlTabWidget::object_wrt_sensor_
std::vector< Eigen::Isometry3d > object_wrt_sensor_
Definition: handeye_control_widget.h:279
moveit_rviz_plugin::HandEyeCalibrationDisplay::move_group_ns_property_
rviz::StringProperty * move_group_ns_property_
Definition: handeye_calibration_display.h:131
moveit_rviz_plugin::ControlTabWidget::plan_watcher_
QFutureWatcher< void > * plan_watcher_
Definition: handeye_control_widget.h:268
moveit_rviz_plugin::ControlTabWidget::FAILURE_INVALID_JOINT_STATE
@ FAILURE_INVALID_JOINT_STATE
Definition: handeye_control_widget.h:141
ros::WallDuration
moveit_rviz_plugin::ControlTabWidget::effector_wrt_world_
std::vector< Eigen::Isometry3d > effector_wrt_world_
Definition: handeye_control_widget.h:278
tf2::TransformException
t
dictionary t
moveit_rviz_plugin::ControlTabWidget::calibration_display_
HandEyeCalibrationDisplay * calibration_display_
Definition: handeye_control_widget.h:235
config
config
rviz::Config
moveit_rviz_plugin::ControlTabWidget::solveCameraRobotPose
bool solveCameraRobotPose()
Definition: handeye_control_widget.cpp:424
moveit_rviz_plugin::ProgressBarWidget
Definition: handeye_control_widget.h:113
moveit_rviz_plugin::ControlTabWidget::parseSolverName
std::string parseSolverName(const std::string &solver_name, char delimiter)
Definition: handeye_control_widget.cpp:369
moveit_rviz_plugin::ControlTabWidget::auto_plan_btn_
QPushButton * auto_plan_btn_
Definition: handeye_control_widget.h:261
ros::NodeHandle
ros::Time::now
static Time now()
moveit_rviz_plugin::ControlTabWidget::executeFinished
void executeFinished()
Definition: handeye_control_widget.cpp:1093


moveit_calibration_gui
Author(s): Yu Yan
autogenerated on Fri Oct 18 2024 02:14:15