rqt_play_motion_builder.cpp
Go to the documentation of this file.
2 
3 #include <play_motion_builder_msgs/ListJointGroups.h>
4 #include <play_motion_builder_msgs/ChangeJoints.h>
5 
6 #include <QCheckBox>
7 #include <QRadioButton>
8 #include <QMessageBox>
9 #include <QInputDialog>
10 
12 
13 #define JOINT_PRECISION 4
14 #define TIME_PRECISION 2
15 
16 namespace pal
17 {
18 const std::string RQTPlayMotionBuilder::GOTO_MENU = "Go To Position";
19 const std::string RQTPlayMotionBuilder::DELETE_MENU = "Delete";
20 const std::string RQTPlayMotionBuilder::SET_TO_CURRENT_MENU = "Recapture frame";
21 const std::string RQTPlayMotionBuilder::COPY_BELOW_MENU = "Copy Below";
22 const std::string RQTPlayMotionBuilder::COPY_LAST_MENU = "Copy as Last";
23 
25  : rqt_gui_cpp::Plugin(), widget_(0), editing_(false), updating_list_(false), editing_motion_("")
26 {
27  setObjectName("RQTPlayMotionBuilder");
28 }
29 
31 {
32  // create QWidget
33  widget_ = new QWidget();
34  // extend the widget with all attributes and children from UI file
35  ui_.setupUi(widget_);
36  // Prepare group scroll area
37  // Prepare scroll area
38  QWidget *g_scroll_w = new QWidget();
39  QVBoxLayout *g_scroll_l = new QVBoxLayout();
40  g_scroll_w->setLayout(g_scroll_l);
41  ui_.group_area_->setWidget(g_scroll_w);
42  ui_.group_area_->setWidgetResizable(true);
43  // Prepare joint scroll area
44  QWidget *scroll_w = new QWidget();
45  QVBoxLayout *scroll_l = new QVBoxLayout();
46  scroll_w->setLayout(scroll_l);
47  ui_.joint_area_->setWidget(scroll_w);
48  ui_.joint_area_->setWidgetResizable(true);
49  // add widget to the user interface
50  context.addWidget(widget_);
51 
52  // Setup properties dialog
54 
55  // Setup buttons
56  connect(ui_.capture_btn_, SIGNAL(pressed()), this, SLOT(onCaptureClicked()));
57  connect(ui_.play_btn_, SIGNAL(pressed()), this, SLOT(onPlayClicked()));
58  connect(ui_.save_btn_, SIGNAL(pressed()), this, SLOT(onSaveClicked()));
59  connect(ui_.movement_table_, SIGNAL(cellChanged(int, int)), this,
60  SLOT(onCellChanged(int, int)));
61 
62  // Set up context menu
63  ui_.movement_table_->setContextMenuPolicy(Qt::CustomContextMenu);
64  // Setup menus
65  table_menu_.addAction(QString::fromStdString(GOTO_MENU));
66  table_menu_.addAction(QString::fromStdString(SET_TO_CURRENT_MENU));
67  table_menu_.addSeparator();
68  table_menu_.addAction(QString::fromStdString(COPY_BELOW_MENU));
69  table_menu_.addAction(QString::fromStdString(COPY_LAST_MENU));
70  table_menu_.addSeparator();
71  table_menu_.addAction(QString::fromStdString(DELETE_MENU));
72  connect(ui_.movement_table_, SIGNAL(customContextMenuRequested(const QPoint &)), this,
73  SLOT(onContextMenuRequested(const QPoint &)));
74 
75  connect(this, SIGNAL(goToSelected(int)), this, SLOT(onGotoSelected(int)));
76  connect(this, SIGNAL(deleteSelected(int)), this, SLOT(onDeleteSelected(int)));
77  connect(this, SIGNAL(setToCurrentSelected(int)), this, SLOT(onSetToCurrentSelected(int)));
78  connect(this, SIGNAL(copyBelowSelected(int)), this, SLOT(onCopyBelowSelected(int)));
79  connect(this, SIGNAL(copyLastSelected(int)), this, SLOT(onCopyLastSelected(int)));
80 
81  connect(ui_.new_btn_, SIGNAL(pressed()), this, SLOT(onNewPressed()));
82  connect(ui_.load_btn_, SIGNAL(pressed()), this, SLOT(onLoadPressed()));
83 
84  connect(properties_dialog_, SIGNAL(motionStored(QString)), this,
85  SLOT(onMotionStored(QString)));
86 
87  // Connect action client
88  builder_client_.reset(new BMAC(getNodeHandle(), "/play_motion_builder_node/build"));
89  run_motion_client_.reset(new RMAC(getNodeHandle(), "/play_motion_builder_node/run"));
90  list_joints_client_ = getNodeHandle().serviceClient<play_motion_builder_msgs::ListJointGroups>(
91  "/play_motion_builder_node/list_joint_groups");
92  edit_motion_client_ = getNodeHandle().serviceClient<play_motion_builder_msgs::EditMotion>(
93  "/play_motion_builder_node/edit_motion");
94  change_joints_client_ = getNodeHandle().serviceClient<play_motion_builder_msgs::ChangeJoints>(
95  "/play_motion_builder_node/change_joints");
97 }
98 
100 {
101  if (editing_)
102  {
103  builder_client_->cancelAllGoals();
104  }
105 }
106 
108 {
109  if (!builder_client_->waitForServer(ros::Duration(5.0)))
110  {
111  ROS_ERROR_STREAM("Couldn't contact builder server");
112  }
113  else
114  {
115  play_motion_builder_msgs::BuildMotionGoal goal; // Empty goal for new motion
116  builder_client_->sendGoal(goal);
117  editing_ = true;
118  enableBtns();
119  ros::Duration(0.1).sleep(); // Wait for a bit
120 
121  play_motion_builder_msgs::ListJointGroups ljg_service;
122  if (list_joints_client_.call(ljg_service))
123  {
124  qDeleteAll(ui_.group_area_->widget()->findChildren<QWidget *>());
125  // Load Group table
126  for (const auto &group : ljg_service.response.groups)
127  {
128  // Load joint table
129  QRadioButton *jsc = new QRadioButton();
130  jsc->setChecked(false);
131  jsc->setProperty("group_name", QString::fromStdString(group));
132  connect(jsc, SIGNAL(toggled(bool)), this, SLOT(onGroupToggled(bool)));
133  jsc->setText(QString::fromStdString(group));
134  ui_.group_area_->widget()->layout()->addWidget(jsc);
135  ROS_DEBUG_STREAM("Group found: " << group);
136  }
137  qDeleteAll(ui_.joint_area_->widget()->findChildren<QWidget *>());
138  for (const auto &joint : ljg_service.response.additional_joints)
139  {
140  // Load joint table
141  QCheckBox *jsc = new QCheckBox();
142  jsc->setChecked(false);
143  jsc->setProperty("joint_name", QString::fromStdString(joint));
144  connect(jsc, SIGNAL(toggled(bool)), this, SLOT(onJointToggled(bool)));
145  jsc->setText(QString::fromStdString(joint));
146  ui_.joint_area_->widget()->layout()->addWidget(jsc);
147  ROS_DEBUG_STREAM("Extra joint found: " << joint);
148  }
149 
150  play_motion_builder_msgs::EditMotion em;
151  em.request.action = play_motion_builder_msgs::EditMotion::Request::LIST;
152  if (edit_motion_client_.call(em))
153  {
154  if (em.response.ok)
155  {
156  loadMotion(em.response.motion);
157  editing_motion_ = "";
158  }
159  else
160  {
161  ROS_ERROR_STREAM("ERROR: " << em.response.message);
162  }
163  }
164  else
165  {
166  ROS_ERROR_STREAM("There was an error contacting the edit motion service");
167  }
168  }
169  }
170 }
171 
172 void RQTPlayMotionBuilder::loadMotion(const play_motion_builder_msgs::Motion &motion)
173 {
174  updating_list_ = true;
175  ROS_DEBUG_STREAM("Begin motion loading");
176  // Select group
177  ROS_DEBUG_STREAM("Using group " << motion.used_group);
178  for (auto &group : ui_.group_area_->widget()->findChildren<QRadioButton *>())
179  {
180  if (group->property("group_name").toString().toStdString() == motion.used_group)
181  {
182  ROS_DEBUG_STREAM("Changing group " << motion.used_group);
183  group->setChecked(true);
184  continue; // Motion will be reloaded in reaction to the group change
185  }
186  }
187 
188  // Generate headers
189  ROS_DEBUG_STREAM("Set headers");
190  ui_.movement_table_->setColumnCount(motion.joints.size() + 1);
191  // Prepare table headers
192  QStringList headers;
193  headers << QString("Time");
194  for (const auto &joint : motion.joints)
195  {
196  headers << QString::fromStdString(joint.substr(0, joint.size() - 6));
197  ROS_DEBUG_STREAM("Joint found: " << joint);
198  }
199  ui_.movement_table_->setHorizontalHeaderLabels(headers);
200  // Fully reload the table to get the proper column order
201  ui_.movement_table_->setRowCount(0);
202 
203  // Check which extra joints are used
204  for (auto &extra_joint : ui_.joint_area_->widget()->findChildren<QCheckBox *>())
205  {
206  if (std::find(motion.joints.begin(), motion.joints.end(),
207  extra_joint->property("joint_name").toString().toStdString()) !=
208  motion.joints.end())
209  {
210  extra_joint->setChecked(true);
211  ROS_DEBUG_STREAM("Changing extra joint state "
212  << extra_joint->property("joint_name").toString().toStdString());
213  }
214  }
215 
216  ui_.movement_table_->setRowCount(motion.keyframes.size());
217  for (unsigned int i = 0; i < motion.keyframes.size(); ++i)
218  {
219  ROS_DEBUG_STREAM("Processing keyframe " << i);
220  // Time
221  QTableWidgetItem *time_item =
222  new QTableWidgetItem(QString::number(motion.keyframes[i].time_from_last, 'f', 2));
223  ui_.movement_table_->setItem(i, 0, time_item);
224 
225 
226  // Add joints in proper order
227  for (int j = 1; j < ui_.movement_table_->columnCount(); ++j)
228  {
229  ROS_DEBUG_STREAM("Processing joint " << j);
230  QTableWidgetItem *joint_position_item = new QTableWidgetItem(QString::number(
231  getJointPosition(motion.joints, motion.keyframes[i].pose,
232  ui_.movement_table_->horizontalHeaderItem(j)->text().toStdString()),
233  'f', JOINT_PRECISION));
234  joint_position_item->setFlags(joint_position_item->flags() ^ Qt::ItemIsEditable); // Non-editable
235 
236  ui_.movement_table_->setItem(i, j, joint_position_item);
237  }
238  }
239 
240  updating_list_ = false;
241  ROS_DEBUG_STREAM("Motion loaded");
242 }
243 
245 {
246  play_motion_builder_msgs::EditMotion em;
247  em.request.action = play_motion_builder_msgs::EditMotion::Request::LIST;
248  if (edit_motion_client_.call(em))
249  {
250  if (em.response.ok)
251  {
252  ROS_DEBUG_STREAM("List current motion");
253  loadMotion(em.response.motion);
254  }
255  else
256  {
257  ROS_ERROR_STREAM("ERROR: " << em.response.message);
258  }
259  }
260  else
261  {
262  ROS_ERROR_STREAM("There was an error contacting the edit motion service");
263  }
264 }
265 
267 {
268  ui_.play_btn_->setText("Play");
269  ui_.play_btn_->setEnabled(true);
270  ui_.downshift_->setEnabled(true);
271  ui_.capture_btn_->setEnabled(true);
272  ui_.save_btn_->setEnabled(true);
273 }
274 
276 {
277  ui_.play_btn_->setText("Stop");
278  ui_.downshift_->setEnabled(false);
279  ui_.capture_btn_->setEnabled(false);
280  ui_.save_btn_->setEnabled(false);
281 }
282 
284  const play_motion_builder_msgs::RunMotionResultConstPtr &)
285 {
286  enableBtns();
287 }
288 
289 double RQTPlayMotionBuilder::getJointPosition(const std::vector<std::string> &joints,
290  const std::vector<double> &poses,
291  const std::string &joint_header)
292 {
293  for (unsigned int i = 0; i < joints.size(); ++i)
294  {
295  if (joints[i] == joint_header + "_joint")
296  return poses[i];
297  }
298 
299  return 0.0;
300 }
301 
303 {
304  // Open popup with options
305  QStringList motions;
307  getNodeHandle().getParam("/play_motion/motions", param);
309  {
310  QMessageBox::critical(widget_, tr("Error"), tr("Could not load motions from ROS."));
311  return;
312  }
313 
314  for (auto it : param)
315  {
316  motions << tr(it.first.c_str());
317  }
318 
319  bool ok;
320  QString motion = QInputDialog::getItem(widget_, tr("Load a motion"), tr("Motion:"),
321  motions, 0, false, &ok);
322 
323  if (ok && !motion.isEmpty())
324  {
325  if (!builder_client_->waitForServer(ros::Duration(5.0)))
326  {
327  ROS_ERROR_STREAM("Couldn't contact builder server");
328  }
329  else
330  {
331  play_motion_builder_msgs::BuildMotionGoal goal; // Empty goal for new motion
332  goal.motion = motion.toStdString();
333  builder_client_->sendGoal(goal);
334  editing_ = true;
335  enableBtns();
336  ros::Duration(0.1).sleep(); // Wait for a bit
337 
338  play_motion_builder_msgs::ListJointGroups ljg_service;
339  if (list_joints_client_.call(ljg_service))
340  {
341  // Load Group table
342  qDeleteAll(ui_.group_area_->widget()->findChildren<QWidget *>());
343  for (const auto &group : ljg_service.response.groups)
344  {
345  QRadioButton *jsc = new QRadioButton();
346  jsc->setChecked(false);
347  jsc->setProperty("group_name", QString::fromStdString(group));
348  connect(jsc, SIGNAL(toggled(bool)), this, SLOT(onGroupToggled(bool)));
349  jsc->setText(QString::fromStdString(group));
350  ui_.group_area_->widget()->layout()->addWidget(jsc);
351  ROS_INFO_STREAM("Group found: " << group);
352  }
353  // Load joint table
354  qDeleteAll(ui_.joint_area_->widget()->findChildren<QWidget *>());
355  for (const auto &joint : ljg_service.response.additional_joints)
356  {
357  QCheckBox *jsc = new QCheckBox();
358  jsc->setChecked(false);
359  jsc->setProperty("joint_name", QString::fromStdString(joint));
360  connect(jsc, SIGNAL(toggled(bool)), this, SLOT(onJointToggled(bool)));
361  jsc->setText(QString::fromStdString(joint));
362  ui_.joint_area_->widget()->layout()->addWidget(jsc);
363  ROS_INFO_STREAM("Extra joint found: " << joint);
364  }
365 
366  play_motion_builder_msgs::EditMotion em;
367  em.request.action = play_motion_builder_msgs::EditMotion::Request::LIST;
368  if (edit_motion_client_.call(em))
369  {
370  if (em.response.ok)
371  {
372  loadMotion(em.response.motion);
373  editing_motion_ = motion.toStdString();
374  }
375  else
376  {
377  ROS_ERROR_STREAM("ERROR: " << em.response.message);
378  }
379  }
380  else
381  {
382  ROS_ERROR_STREAM("There was an error contacting the edit motion service");
383  }
384  }
385  }
386  }
387 }
388 
390 {
391  play_motion_builder_msgs::EditMotion em;
392  em.request.action = play_motion_builder_msgs::EditMotion::Request::APPEND;
393  if (edit_motion_client_.call(em))
394  {
395  if (em.response.ok)
396  {
397  loadMotion(em.response.motion);
398  }
399  else
400  {
401  ROS_ERROR_STREAM("ERROR: " << em.response.message);
402  }
403  }
404  else
405  {
406  ROS_ERROR_STREAM("Error calling the edit_motion service to append keyframe");
407  }
408 }
409 
411 {
412  if (!motion_running_)
413  {
414  play_motion_builder_msgs::RunMotionGoal goal;
415  goal.run_mode = play_motion_builder_msgs::RunMotionGoal::RUN_MOTION;
416  goal.downshift = ui_.downshift_->value();
417 
418  disableBtns();
419  motion_running_ = true;
420  run_motion_client_->sendGoal(goal, boost::bind(&RQTPlayMotionBuilder::runDone, this, _1,
421  _2)); // Add done callback to unlock
422  }
423  else
424  {
425  run_motion_client_->cancelAllGoals();
426  motion_running_ = false;
427  }
428 }
429 
431 {
432  if (!editing_motion_.empty())
433  {
435  // Load config
437  if (getNodeHandle().getParam("/play_motion/motions/" + editing_motion_ + "/meta", param))
438  {
439  properties_dialog_->loadMeta(static_cast<std::string>(param["name"]),
440  static_cast<std::string>(param["usage"]),
441  static_cast<std::string>(param["description"]));
442  }
443  }
444  else
445  {
447  }
448  properties_dialog_->exec();
449 }
450 
452 {
453  QTableWidgetItem *clicked = ui_.movement_table_->itemAt(point);
454  if (clicked)
455  {
456  int row = clicked->row();
457  ROS_DEBUG_STREAM("Called on row" << row);
458 
459  QAction *selectedItem = table_menu_.exec(QCursor::pos());
460  if (selectedItem)
461  {
462  ROS_DEBUG_STREAM("Item selected is " << selectedItem->text().toStdString());
463 
464  if (selectedItem->text().toStdString() == GOTO_MENU)
465  {
466  emit goToSelected(row);
467  }
468  else if (selectedItem->text().toStdString() == DELETE_MENU)
469  {
470  emit deleteSelected(row);
471  }
472  else if (selectedItem->text().toStdString() == SET_TO_CURRENT_MENU)
473  {
474  emit setToCurrentSelected(row);
475  }
476  else if (selectedItem->text().toStdString() == COPY_BELOW_MENU)
477  {
478  emit copyBelowSelected(row);
479  }
480  else if (selectedItem->text().toStdString() == COPY_LAST_MENU)
481  {
482  emit copyLastSelected(row);
483  }
484  else
485  {
486  ROS_ERROR_STREAM("Selected unknown menu " << selectedItem->text().toStdString());
487  }
488  }
489  }
490 }
492 {
493  play_motion_builder_msgs::RunMotionGoal goal;
494  goal.run_mode = play_motion_builder_msgs::RunMotionGoal::GO_TO_STEP;
495  goal.step_id = frame;
496 
497  disableBtns();
498  motion_running_ = true;
499  run_motion_client_->sendGoal(goal, boost::bind(&RQTPlayMotionBuilder::runDone, this, _1, _2)); // Add done callback to unlock
500 }
501 
503 {
504  play_motion_builder_msgs::EditMotion em;
505  em.request.action = play_motion_builder_msgs::EditMotion::Request::REMOVE;
506  em.request.step_id = frame;
507  if (edit_motion_client_.call(em))
508  {
509  if (em.response.ok)
510  {
511  loadMotion(em.response.motion);
512  }
513  else
514  {
515  ROS_ERROR_STREAM("ERROR: " << em.response.message);
516  }
517  }
518  else
519  {
520  ROS_ERROR_STREAM("Error calling the edit_motion service to edit keyframe");
521  }
522 }
524 {
525  play_motion_builder_msgs::EditMotion em;
526  em.request.action = play_motion_builder_msgs::EditMotion::Request::EDIT;
527  em.request.step_id = frame;
528  if (edit_motion_client_.call(em))
529  {
530  if (em.response.ok)
531  {
532  loadMotion(em.response.motion);
533  }
534  else
535  {
536  ROS_ERROR_STREAM("ERROR: " << em.response.message);
537  }
538  }
539  else
540  {
541  ROS_ERROR_STREAM("Error calling the edit_motion service to edit keyframe");
542  }
543 }
545 {
546  play_motion_builder_msgs::EditMotion em;
547  em.request.action = play_motion_builder_msgs::EditMotion::Request::COPY_AS_NEXT;
548  em.request.step_id = frame;
549  if (edit_motion_client_.call(em))
550  {
551  if (em.response.ok)
552  {
553  loadMotion(em.response.motion);
554  }
555  else
556  {
557  ROS_ERROR_STREAM("ERROR: " << em.response.message);
558  }
559  }
560  else
561  {
562  ROS_ERROR_STREAM("Error calling the edit_motion service to copy keyframe");
563  }
564 }
566 {
567  play_motion_builder_msgs::EditMotion em;
568  em.request.action = play_motion_builder_msgs::EditMotion::Request::COPY_AS_LAST;
569  em.request.step_id = frame;
570  if (edit_motion_client_.call(em))
571  {
572  if (em.response.ok)
573  {
574  loadMotion(em.response.motion);
575  }
576  else
577  {
578  ROS_ERROR_STREAM("ERROR: " << em.response.message);
579  }
580  }
581  else
582  {
583  ROS_ERROR_STREAM("Error calling the edit_motion service to copy-as-last keyframe");
584  }
585 }
586 
588 {
589  if (state && !updating_list_)
590  {
591  QString group = sender()->property("group_name").toString();
592  ROS_DEBUG_STREAM("Change group " << group.toStdString() << " to active");
593 
594  play_motion_builder_msgs::ChangeJoints cj;
595  cj.request.group = group.toStdString();
596  if (change_joints_client_.call(cj))
597  {
598  if (cj.response.ok)
599  {
600  listMotion();
601  }
602  else
603  {
604  ROS_ERROR_STREAM("ERROR: " << cj.response.message);
605  }
606  }
607  else
608  {
609  ROS_ERROR_STREAM("Error calling the edit_motion service to copy-as-last keyframe");
610  }
611  }
612 }
613 
615 {
616  if (!updating_list_)
617  {
618  QString joint = sender()->property("joint_name").toString();
619  ROS_DEBUG_STREAM("Change joint " << joint.toStdString() << " to "
620  << (state ? "active" : "inactive"));
621 
622  play_motion_builder_msgs::ChangeJoints cj;
623  if (state)
624  cj.request.joints_to_add.push_back(joint.toStdString());
625  else
626  cj.request.joints_to_remove.push_back(joint.toStdString());
627 
628  if (change_joints_client_.call(cj))
629  {
630  if (cj.response.ok)
631  {
632  listMotion();
633  }
634  else
635  {
636  ROS_ERROR_STREAM("ERROR: " << cj.response.message);
637  }
638  }
639  else
640  {
641  ROS_ERROR_STREAM("Error calling the edit_motion service to copy-as-last keyframe");
642  }
643  }
644 }
645 
647 {
648  if (col == 0 && !updating_list_)
649  {
650  ROS_DEBUG_STREAM("Changing time");
651  play_motion_builder_msgs::EditMotion em;
652  em.request.action = play_motion_builder_msgs::EditMotion::Request::EDIT_TIME;
653  em.request.step_id = row;
654  em.request.time = ui_.movement_table_->item(row, col)->text().toDouble();
655 
656  if (edit_motion_client_.call(em))
657  {
658  if (em.response.ok)
659  {
660  loadMotion(em.response.motion);
661  }
662  else
663  {
664  ROS_ERROR_STREAM("ERROR: " << em.response.message);
665  }
666  }
667  else
668  {
669  ROS_ERROR_STREAM("Error calling the edit_motion service to copy-as-last keyframe");
670  }
671  }
672 }
673 
674 void RQTPlayMotionBuilder::onMotionStored(QString motion_name)
675 {
676  editing_motion_ = motion_name.toStdString();
677  properties_dialog_->close();
678 }
679 
680 } // namespace pal
681 
void loadMotion(const play_motion_builder_msgs::Motion &motion)
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
ros::ServiceClient edit_motion_client_
void copyLastSelected(int row)
bool param(const std::string &param_name, T &param_val, const T &default_val)
std::unique_ptr< BMAC > builder_client_
ros::NodeHandle & getNodeHandle() const
static const std::string DELETE_MENU
void init(ros::NodeHandle &nh)
bool call(MReq &req, MRes &res)
actionlib::SimpleActionClient< play_motion_builder_msgs::RunMotionAction > RMAC
static const std::string COPY_LAST_MENU
void addWidget(QWidget *widget)
actionlib::SimpleActionClient< play_motion_builder_msgs::BuildMotionAction > BMAC
virtual void initPlugin(qt_gui_cpp::PluginContext &context) override
std::unique_ptr< RMAC > run_motion_client_
ros::ServiceClient change_joints_client_
void setToCurrentSelected(int row)
void onMotionStored(QString motion_name)
Type const & getType() const
void goToSelected(int row)
ros::ServiceClient list_joints_client_
bool getParam(const std::string &key, std::string &s) const
ROSCPP_DECL bool ok()
#define JOINT_PRECISION
virtual void shutdownPlugin() override
void runDone(const actionlib::SimpleClientGoalState &state, const play_motion_builder_msgs::RunMotionResultConstPtr &result)
void onContextMenuRequested(const QPoint &point)
double getJointPosition(const std::vector< std::string > &joints, const std::vector< double > &poses, const std::string &joint_header)
#define ROS_DEBUG_STREAM(args)
static const std::string SET_TO_CURRENT_MENU
void deleteSelected(int row)
void loadYamlName(const std::string &yaml_name)
#define ROS_INFO_STREAM(args)
static const std::string GOTO_MENU
void onCellChanged(int row, int col)
bool sleep() const
#define ROS_ERROR_STREAM(args)
static const std::string COPY_BELOW_MENU
void loadMeta(const std::string &name, const std::string &usage, const std::string &description)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
MotionProperties * properties_dialog_
void copyBelowSelected(int row)


rqt_play_motion_builder
Author(s):
autogenerated on Mon Feb 28 2022 23:13:41