moveit2
The MoveIt Motion Planning Framework for ROS 2.
motion_planning_display.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2008, Willow Garage, Inc.
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: Ioan Sucan, Dave Coleman, Adam Leeper, Sachin Chitta */
36 
42 
43 #include <rviz_default_plugins/robot/robot.hpp>
44 #include <rviz_default_plugins/robot/robot_link.hpp>
46 
47 #include <rviz_common/properties/property.hpp>
48 #include <rviz_common/properties/string_property.hpp>
49 #include <rviz_common/properties/bool_property.hpp>
50 #include <rviz_common/properties/float_property.hpp>
51 #include <rviz_common/properties/ros_topic_property.hpp>
52 #include <rviz_common/properties/editable_enum_property.hpp>
53 #include <rviz_common/properties/color_property.hpp>
54 #include <rviz_common/display_context.hpp>
55 #include <rviz_common/frame_manager_iface.hpp>
56 #include <rviz_common/panel_dock_widget.hpp>
57 #include <rviz_common/window_manager_interface.hpp>
58 #include <rviz_common/display.hpp>
59 #include <rviz_rendering/objects/movable_text.hpp>
60 
61 #include <OgreSceneManager.h>
62 #include <OgreSceneNode.h>
63 #include <rviz_rendering/objects/shape.hpp>
64 
67 
68 #include <boost/format.hpp>
69 #include <boost/algorithm/string/replace.hpp>
70 #include <boost/algorithm/string/trim.hpp>
71 
72 #include <QShortcut>
73 
74 #include "ui_motion_planning_rviz_plugin_frame.h"
76 
77 #include <rclcpp/qos.hpp>
78 
79 namespace moveit_rviz_plugin
80 {
81 static const rclcpp::Logger LOGGER = rclcpp::get_logger("moveit_ros_visualization.motion_planning_display");
82 
83 // ******************************************************************************************
84 // Base class constructor
85 // ******************************************************************************************
88  , text_to_display_(nullptr)
89  , frame_(nullptr)
90  , frame_dock_(nullptr)
91  , menu_handler_start_(std::make_shared<interactive_markers::MenuHandler>())
92  , menu_handler_goal_(std::make_shared<interactive_markers::MenuHandler>())
93  , int_marker_display_(nullptr)
94 {
95  // Category Groups
96  plan_category_ = new rviz_common::properties::Property("Planning Request", QVariant(), "", this);
97  metrics_category_ = new rviz_common::properties::Property("Planning Metrics", QVariant(), "", this);
98  path_category_ = new rviz_common::properties::Property("Planned Path", QVariant(), "", this);
99 
100  // Metrics category -----------------------------------------------------------------------------------------
102  new rviz_common::properties::BoolProperty("Show Weight Limit", false,
103  "Shows the weight limit at a particular pose for an end-effector",
104  metrics_category_, SLOT(changedShowWeightLimit()), this);
105 
107  new rviz_common::properties::BoolProperty("Show Manipulability Index", false,
108  "Shows the manipulability index for an end-effector", metrics_category_,
109  SLOT(changedShowManipulabilityIndex()), this);
110 
112  new rviz_common::properties::BoolProperty("Show Manipulability", false,
113  "Shows the manipulability for an end-effector", metrics_category_,
114  SLOT(changedShowManipulability()), this);
115 
117  new rviz_common::properties::BoolProperty("Show Joint Torques", false,
118  "Shows the joint torques for a given configuration and payload",
119  metrics_category_, SLOT(changedShowJointTorques()), this);
120 
122  new rviz_common::properties::FloatProperty("Payload", 1.0f, "Specify the payload at the end effector (kg)",
123  metrics_category_, SLOT(changedMetricsSetPayload()), this);
124  metrics_set_payload_property_->setMin(0.0);
125 
126  metrics_text_height_property_ = new rviz_common::properties::FloatProperty(
127  "TextHeight", 0.08f, "Text height", metrics_category_, SLOT(changedMetricsTextHeight()), this);
128  metrics_text_height_property_->setMin(0.001);
129 
130  // Planning request category -----------------------------------------------------------------------------------------
131 
132  planning_group_property_ = new rviz_common::properties::EditableEnumProperty(
133  "Planning Group", "", "The name of the group of links to plan for (from the ones defined in the SRDF)",
134  plan_category_, SLOT(changedPlanningGroup()), this);
135  show_workspace_property_ = new rviz_common::properties::BoolProperty("Show Workspace", false,
136  "Shows the axis-aligned bounding box for "
137  "the workspace allowed for planning",
138  plan_category_, SLOT(changedWorkspace()), this);
140  new rviz_common::properties::BoolProperty("Query Start State", false,
141  "Set a custom start state for the motion planning query",
142  plan_category_, SLOT(changedQueryStartState()), this);
144  new rviz_common::properties::BoolProperty("Query Goal State", true,
145  "Shows the goal state for the motion planning query", plan_category_,
146  SLOT(changedQueryGoalState()), this);
147  query_marker_scale_property_ = new rviz_common::properties::FloatProperty(
148  "Interactive Marker Size", 0.0f,
149  "Specifies scale of the interactive marker overlaid on the robot. 0 is auto scale.", plan_category_,
150  SLOT(changedQueryMarkerScale()), this);
151  query_marker_scale_property_->setMin(0.0f);
152 
154  new rviz_common::properties::ColorProperty("Start State Color", QColor(0, 255, 0),
155  "The highlight color for the start state", plan_category_,
156  SLOT(changedQueryStartColor()), this);
158  new rviz_common::properties::FloatProperty("Start State Alpha", 1.0f, "Specifies the alpha for the robot links",
159  plan_category_, SLOT(changedQueryStartAlpha()), this);
160  query_start_alpha_property_->setMin(0.0);
161  query_start_alpha_property_->setMax(1.0);
162 
164  new rviz_common::properties::ColorProperty("Goal State Color", QColor(250, 128, 0),
165  "The highlight color for the goal state", plan_category_,
166  SLOT(changedQueryGoalColor()), this);
167 
169  new rviz_common::properties::FloatProperty("Goal State Alpha", 1.0f, "Specifies the alpha for the robot links",
170  plan_category_, SLOT(changedQueryGoalAlpha()), this);
171  query_goal_alpha_property_->setMin(0.0);
172  query_goal_alpha_property_->setMax(1.0);
173 
175  new rviz_common::properties::ColorProperty("Colliding Link Color", QColor(255, 0, 0),
176  "The highlight color for colliding links", plan_category_,
177  SLOT(changedQueryCollidingLinkColor()), this);
178 
179  query_outside_joint_limits_link_color_property_ = new rviz_common::properties::ColorProperty(
180  "Joint Violation Color", QColor(255, 0, 255),
181  "The highlight color for child links of joints that are outside bounds", plan_category_,
182  SLOT(changedQueryJointViolationColor()), this);
183 
184  // Trajectory playback / planned path category ---------------------------------------------
185  trajectory_visual_ = std::make_shared<TrajectoryVisualization>(path_category_, this);
186 
187  // Start background jobs
189  const std::string& name) { backgroundJobUpdate(event, name); });
190 }
191 
192 // ******************************************************************************************
193 // Deconstructor
194 // ******************************************************************************************
196 {
198  clearJobs();
199 
200  query_robot_start_.reset();
201  query_robot_goal_.reset();
202 
203  delete text_to_display_;
204  delete int_marker_display_;
205  delete frame_dock_;
206 }
207 
209 {
211 
212  // Planned Path Display
213  trajectory_visual_->onInitialize(node_, planning_scene_node_, context_);
214  QColor qcolor = attached_body_color_property_->getColor();
215  trajectory_visual_->setDefaultAttachedObjectColor(qcolor);
216 
218  std::make_shared<RobotStateVisualization>(planning_scene_node_, context_, "Planning Request Start", nullptr);
219  query_robot_start_->setCollisionVisible(false);
220  query_robot_start_->setVisualVisible(true);
221  query_robot_start_->setVisible(query_start_state_property_->getBool());
222  std_msgs::msg::ColorRGBA color;
223  qcolor = query_start_color_property_->getColor();
224  color.r = qcolor.redF();
225  color.g = qcolor.greenF();
226  color.b = qcolor.blueF();
227  color.a = 1.0f;
228  query_robot_start_->setDefaultAttachedObjectColor(color);
229 
231  std::make_shared<RobotStateVisualization>(planning_scene_node_, context_, "Planning Request Goal", nullptr);
232  query_robot_goal_->setCollisionVisible(false);
233  query_robot_goal_->setVisualVisible(true);
234  query_robot_goal_->setVisible(query_goal_state_property_->getBool());
235  qcolor = query_goal_color_property_->getColor();
236  color.r = qcolor.redF();
237  color.g = qcolor.greenF();
238  color.b = qcolor.blueF();
239  query_robot_goal_->setDefaultAttachedObjectColor(color);
240 
241  rviz_common::WindowManagerInterface* window_context = context_->getWindowManager();
242  frame_ = new MotionPlanningFrame(this, context_, window_context ? window_context->getParentWindow() : nullptr);
243 
244  connect(frame_, SIGNAL(configChanged()), this->getModel(), SIGNAL(configChanged()));
246  addStatusText("Initialized.");
247 
248  // immediately switch to next trajectory display after planning
249  connect(frame_, SIGNAL(planningFinished()), trajectory_visual_.get(), SLOT(interruptCurrentDisplay()));
250 
251  if (window_context)
252  {
253  frame_dock_ = window_context->addPane(getName(), frame_);
254  connect(frame_dock_, SIGNAL(visibilityChanged(bool)), this, SLOT(motionPanelVisibilityChange(bool)));
255  frame_dock_->setIcon(getIcon());
256  }
257 
259  int_marker_display_->initialize(context_);
260 
261  text_display_scene_node_ = planning_scene_node_->createChildSceneNode();
262  text_to_display_ = new rviz_rendering::MovableText("EMPTY");
263  text_to_display_->setTextAlignment(rviz_rendering::MovableText::H_CENTER, rviz_rendering::MovableText::V_CENTER);
264  text_to_display_->setCharacterHeight(metrics_text_height_property_->getFloat());
265  text_to_display_->showOnTop();
266  text_to_display_->setVisible(false);
267  text_display_for_start_ = false;
269 
270  if (context_ && context_->getWindowManager() && context_->getWindowManager()->getParentWindow())
271  {
272  QShortcut* im_reset_shortcut =
273  new QShortcut(QKeySequence("Ctrl+I"), context_->getWindowManager()->getParentWindow());
274  connect(im_reset_shortcut, SIGNAL(activated()), this, SLOT(resetInteractiveMarkers()));
275  }
276 }
277 
278 void MotionPlanningDisplay::motionPanelVisibilityChange(bool enable)
279 {
280  if (enable)
281  setEnabled(true);
282 }
283 
285 {
286  if (enable)
287  {
288  planning_group_sub_ = node_->create_subscription<std_msgs::msg::String>(
289  "/rviz/moveit/select_planning_group", rclcpp::ServicesQoS(),
290  [this](const std_msgs::msg::String::ConstSharedPtr& msg) { return selectPlanningGroupCallback(msg); });
291  }
292  else
293  {
294  planning_group_sub_.reset();
295  }
296 }
297 
298 void MotionPlanningDisplay::selectPlanningGroupCallback(const std_msgs::msg::String::ConstSharedPtr& msg)
299 {
300  // synchronize ROS callback with main loop
301  addMainLoopJob([this, group = msg->data] { changePlanningGroup(group); });
302 }
303 
305 {
306  text_to_display_->setVisible(false);
307 
308  query_robot_start_->clear();
309  query_robot_goal_->clear();
310 
312 
313  // Planned Path Display
314  trajectory_visual_->reset();
315 
316  bool enabled = this->isEnabled();
317  frame_->disable();
318  if (enabled)
319  {
320  frame_->enable();
321  query_robot_start_->setVisible(query_start_state_property_->getBool());
322  query_robot_goal_->setVisible(query_goal_state_property_->getBool());
323  }
324 }
325 
327  const std::string& /*unused*/)
328 {
330 }
331 
333 {
334  if (!frame_)
335  return;
336  QProgressBar* p = frame_->ui_->background_job_progress;
338 
339  if (n == 0)
340  {
341  p->hide();
342  p->setMaximum(0);
343  p->setValue(0);
344  }
345  else
346  {
347  if (p->maximum() < n) // increase max
348  {
349  p->setMaximum(n);
350  if (n > 1) // only show bar if there will be a progress to show
351  p->show();
352  }
353  else // progress
354  p->setValue(p->maximum() - n);
355  p->update();
356  }
357 }
358 
359 void MotionPlanningDisplay::changedShowWeightLimit()
360 {
362  {
363  if (query_start_state_property_->getBool())
364  displayMetrics(true);
365  }
366  else
367  {
368  if (query_goal_state_property_->getBool())
369  displayMetrics(false);
370  }
371 }
372 
373 void MotionPlanningDisplay::changedShowManipulabilityIndex()
374 {
376  {
377  if (query_start_state_property_->getBool())
378  displayMetrics(true);
379  }
380  else
381  {
382  if (query_goal_state_property_->getBool())
383  displayMetrics(false);
384  }
385 }
386 
387 void MotionPlanningDisplay::changedShowManipulability()
388 {
390  {
391  if (query_start_state_property_->getBool())
392  displayMetrics(true);
393  }
394  else
395  {
396  if (query_goal_state_property_->getBool())
397  displayMetrics(false);
398  }
399 }
400 
401 void MotionPlanningDisplay::changedShowJointTorques()
402 {
404  {
405  if (query_start_state_property_->getBool())
406  displayMetrics(true);
407  }
408  else
409  {
410  if (query_goal_state_property_->getBool())
411  displayMetrics(false);
412  }
413 }
414 
415 void MotionPlanningDisplay::changedMetricsSetPayload()
416 {
418  {
419  if (query_start_state_property_->getBool())
420  displayMetrics(true);
421  }
422  else
423  {
424  if (query_goal_state_property_->getBool())
425  displayMetrics(false);
426  }
427 }
428 
429 void MotionPlanningDisplay::changedMetricsTextHeight()
430 {
431  text_to_display_->setCharacterHeight(metrics_text_height_property_->getFloat());
432 }
433 
434 void MotionPlanningDisplay::displayTable(const std::map<std::string, double>& values, const Ogre::ColourValue& color,
435  const Ogre::Vector3& pos, const Ogre::Quaternion& orient)
436 {
437  // the line we want to render
438  std::stringstream ss;
439  for (const std::pair<const std::string, double>& value : values)
440  ss << boost::format("%-10s %-4.2f") % value.first % value.second << '\n';
441 
442  if (ss.str().empty())
443  {
444  text_to_display_->setVisible(false);
445  return;
446  }
447 
448  text_to_display_->setCaption(ss.str());
449  text_to_display_->setColor(color);
450  text_display_scene_node_->setPosition(pos);
451  text_display_scene_node_->setOrientation(orient);
452 
453  // make sure the node is visible
454  text_to_display_->setVisible(true);
455 }
456 
458 {
459  if (!frame_ || !show_workspace_property_->getBool())
460  {
461  if (workspace_box_)
462  workspace_box_.reset();
463  return;
464  }
465 
466  if (!workspace_box_)
467  {
468  workspace_box_ = std::make_unique<rviz_rendering::Shape>(rviz_rendering::Shape::Cube, context_->getSceneManager(),
470  workspace_box_->setColor(0.0f, 0.0f, 0.6f, 0.3f);
471  }
472 
473  Ogre::Vector3 center(frame_->ui_->wcenter_x->value(), frame_->ui_->wcenter_y->value(),
474  frame_->ui_->wcenter_z->value());
475  Ogre::Vector3 extents(frame_->ui_->wsize_x->value(), frame_->ui_->wsize_y->value(), frame_->ui_->wsize_z->value());
476  workspace_box_->setScale(extents);
477  workspace_box_->setPosition(center);
478 }
479 
480 void MotionPlanningDisplay::computeMetrics(bool start, const std::string& group, double payload)
481 {
482  if (!robot_interaction_)
483  return;
484  const std::vector<robot_interaction::EndEffectorInteraction>& eef = robot_interaction_->getActiveEndEffectors();
485  if (eef.empty())
486  return;
487  std::scoped_lock slock(update_metrics_lock_);
488 
489  moveit::core::RobotStateConstPtr state = start ? getQueryStartState() : getQueryGoalState();
490  for (const robot_interaction::EndEffectorInteraction& ee : eef)
491  if (ee.parent_group == group)
492  computeMetricsInternal(computed_metrics_[std::make_pair(start, group)], ee, *state, payload);
493 }
494 
495 void MotionPlanningDisplay::computeMetricsInternal(std::map<std::string, double>& metrics,
497  const moveit::core::RobotState& state, double payload)
498 {
499  metrics.clear();
500  dynamics_solver::DynamicsSolverPtr ds;
501  std::map<std::string, dynamics_solver::DynamicsSolverPtr>::const_iterator it = dynamics_solver_.find(ee.parent_group);
502  if (it != dynamics_solver_.end())
503  ds = it->second;
504 
505  // Max payload
506  if (ds)
507  {
508  double max_payload;
509  unsigned int saturated_joint;
510  std::vector<double> joint_values;
511  state.copyJointGroupPositions(ee.parent_group, joint_values);
512  if (ds->getMaxPayload(joint_values, max_payload, saturated_joint))
513  {
514  metrics["max_payload"] = max_payload;
515  metrics["saturated_joint"] = saturated_joint;
516  }
517  std::vector<double> joint_torques;
518  joint_torques.resize(joint_values.size());
519  if (ds->getPayloadTorques(joint_values, payload, joint_torques))
520  {
521  for (std::size_t i = 0; i < joint_torques.size(); ++i)
522  {
523  std::stringstream stream;
524  stream << "torque[" << i << "]";
525  metrics[stream.str()] = joint_torques[i];
526  }
527  }
528  }
529 
531  {
532  if (position_only_ik_.find(ee.parent_group) == position_only_ik_.end())
533  node_->get_parameter_or(ee.parent_group + ".position_only_ik", position_only_ik_[ee.parent_group], false);
534 
535  double manipulability_index, manipulability;
536  bool position_ik = position_only_ik_[ee.parent_group];
537  if (kinematics_metrics_->getManipulabilityIndex(state, ee.parent_group, manipulability_index, position_ik))
538  metrics["manipulability_index"] = manipulability_index;
539  if (kinematics_metrics_->getManipulability(state, ee.parent_group, manipulability))
540  metrics["manipulability"] = manipulability;
541  }
542 }
543 
544 namespace
545 {
546 inline void copyItemIfExists(const std::map<std::string, double>& source, std::map<std::string, double>& dest,
547  const std::string& key)
548 {
549  std::map<std::string, double>::const_iterator it = source.find(key);
550  if (it != source.end())
551  dest[key] = it->second;
552 }
553 } // namespace
554 
556 {
558  return;
559 
560  static const Ogre::Quaternion ORIENTATION(1.0, 0.0, 0.0, 0.0);
561  const std::vector<robot_interaction::EndEffectorInteraction>& eef = robot_interaction_->getActiveEndEffectors();
562  if (eef.empty())
563  return;
564 
565  moveit::core::RobotStateConstPtr state = start ? getQueryStartState() : getQueryGoalState();
566 
567  for (const robot_interaction::EndEffectorInteraction& ee : eef)
568  {
569  Ogre::Vector3 position(0.0, 0.0, 0.0);
570  std::map<std::string, double> text_table;
571  const std::map<std::string, double>& metrics_table = computed_metrics_[std::make_pair(start, ee.parent_group)];
572  if (compute_weight_limit_property_->getBool())
573  {
574  copyItemIfExists(metrics_table, text_table, "max_payload");
575  copyItemIfExists(metrics_table, text_table, "saturated_joint");
576  }
578  copyItemIfExists(metrics_table, text_table, "manipulability_index");
579  if (show_manipulability_property_->getBool())
580  copyItemIfExists(metrics_table, text_table, "manipulability");
581  if (show_joint_torques_property_->getBool())
582  {
583  std::size_t nj = getRobotModel()->getJointModelGroup(ee.parent_group)->getJointModelNames().size();
584  for (size_t j = 0; j < nj; ++j)
585  {
586  std::stringstream stream;
587  stream << "torque[" << j << "]";
588  copyItemIfExists(metrics_table, text_table, stream.str());
589  }
590  }
591 
592  const moveit::core::LinkModel* lm = nullptr;
593  const moveit::core::JointModelGroup* jmg = getRobotModel()->getJointModelGroup(ee.parent_group);
594  if (jmg)
595  if (!jmg->getLinkModelNames().empty())
596  lm = state->getLinkModel(jmg->getLinkModelNames().back());
597  if (lm)
598  {
599  const Eigen::Vector3d& t = state->getGlobalLinkTransform(lm).translation();
600  position[0] = t.x();
601  position[1] = t.y();
602  position[2] = t.z() + 0.2; // \todo this should be a param
603  }
604  if (start)
605  displayTable(text_table, query_start_color_property_->getOgreColor(), position, ORIENTATION);
606  else
607  displayTable(text_table, query_goal_color_property_->getOgreColor(), position, ORIENTATION);
608  text_display_for_start_ = start;
609  }
610 }
611 
613 {
615  return;
616 
617  if (query_start_state_property_->getBool())
618  {
619  if (isEnabled())
620  {
621  moveit::core::RobotStateConstPtr state = getQueryStartState();
622 
623  // update link poses
624  query_robot_start_->update(state);
625  query_robot_start_->setVisible(true);
626 
627  // update link colors
628  std::vector<std::string> collision_links;
629  getPlanningSceneRO()->getCollidingLinks(collision_links, *state);
630  status_links_start_.clear();
631  for (const std::string& collision_link : collision_links)
632  status_links_start_[collision_link] = COLLISION_LINK;
633  if (!collision_links.empty())
634  {
636  getPlanningSceneRO()->getCollidingPairs(pairs, *state);
638  addStatusText("Start state colliding links:");
639  for (collision_detection::CollisionResult::ContactMap::const_iterator it = pairs.begin(); it != pairs.end();
640  ++it)
641  addStatusText(it->first.first + " - " + it->first.second);
642  addStatusText(".");
643  }
644  if (!getCurrentPlanningGroup().empty())
645  {
646  const moveit::core::JointModelGroup* jmg = state->getJointModelGroup(getCurrentPlanningGroup());
647  if (jmg)
648  {
649  std::vector<std::string> outside_bounds;
650  const std::vector<const moveit::core::JointModel*>& jmodels = jmg->getActiveJointModels();
651  for (const moveit::core::JointModel* jmodel : jmodels)
652  if (!state->satisfiesBounds(jmodel, jmodel->getMaximumExtent() * 1e-2))
653  {
654  outside_bounds.push_back(jmodel->getChildLinkModel()->getName());
655  status_links_start_[outside_bounds.back()] = OUTSIDE_BOUNDS_LINK;
656  }
657  if (!outside_bounds.empty())
658  {
660  addStatusText("Links descending from joints that are outside bounds in start state:");
661  addStatusText(outside_bounds);
662  }
663  }
664  }
666  // update metrics text
667  displayMetrics(true);
668  }
669  }
670  else
671  query_robot_start_->setVisible(false);
672  context_->queueRender();
673 }
674 
676 {
677  setStatusTextColor(Qt::darkGray);
678 }
679 
681 {
682  if (frame_)
683  frame_->ui_->status_text->setTextColor(color);
684 }
685 
687 {
688  if (frame_)
689  frame_->ui_->status_text->append(QString::fromStdString(text));
690 }
691 
692 void MotionPlanningDisplay::addStatusText(const std::vector<std::string>& text)
693 {
694  for (const std::string& it : text)
695  addStatusText(it);
696 }
697 
699 {
700  std::string group = planning_group_property_->getStdString();
701  if (!group.empty())
703 }
704 
706 {
707  std::string group = planning_group_property_->getStdString();
708  if (!group.empty())
710 }
711 
712 void MotionPlanningDisplay::changedQueryStartState()
713 {
715  return;
717  addStatusText("Changed start state");
719  addBackgroundJob([this] { publishInteractiveMarkers(true); }, "publishInteractiveMarkers");
720 }
721 
722 void MotionPlanningDisplay::changedQueryGoalState()
723 {
725  return;
727  addStatusText("Changed goal state");
729  addBackgroundJob([this] { publishInteractiveMarkers(true); }, "publishInteractiveMarkers");
730 }
731 
733 {
735  return;
736  if (query_goal_state_property_->getBool())
737  {
738  if (isEnabled())
739  {
740  moveit::core::RobotStateConstPtr state = getQueryGoalState();
741 
742  // update link poses
743  query_robot_goal_->update(state);
744  query_robot_goal_->setVisible(true);
745 
746  // update link colors
747  std::vector<std::string> collision_links;
748  getPlanningSceneRO()->getCollidingLinks(collision_links, *state);
749  status_links_goal_.clear();
750  for (const std::string& collision_link : collision_links)
751  status_links_goal_[collision_link] = COLLISION_LINK;
752  if (!collision_links.empty())
753  {
755  getPlanningSceneRO()->getCollidingPairs(pairs, *state);
757  addStatusText("Goal state colliding links:");
758  for (collision_detection::CollisionResult::ContactMap::const_iterator it = pairs.begin(); it != pairs.end();
759  ++it)
760  addStatusText(it->first.first + " - " + it->first.second);
761  addStatusText(".");
762  }
763 
764  if (!getCurrentPlanningGroup().empty())
765  {
766  const moveit::core::JointModelGroup* jmg = state->getJointModelGroup(getCurrentPlanningGroup());
767  if (jmg)
768  {
769  const std::vector<const moveit::core::JointModel*>& jmodels = jmg->getActiveJointModels();
770  std::vector<std::string> outside_bounds;
771  for (const moveit::core::JointModel* jmodel : jmodels)
772  if (!state->satisfiesBounds(jmodel, jmodel->getMaximumExtent() * 1e-2))
773  {
774  outside_bounds.push_back(jmodel->getChildLinkModel()->getName());
775  status_links_goal_[outside_bounds.back()] = OUTSIDE_BOUNDS_LINK;
776  }
777 
778  if (!outside_bounds.empty())
779  {
781  addStatusText("Links descending from joints that are outside bounds in goal state:");
782  addStatusText(outside_bounds);
783  }
784  }
785  }
787 
788  // update metrics text
789  displayMetrics(false);
790  }
791  }
792  else
793  query_robot_goal_->setVisible(false);
794  context_->queueRender();
795 }
796 
797 void MotionPlanningDisplay::resetInteractiveMarkers()
798 {
799  query_start_state_->clearError();
800  query_goal_state_->clearError();
801  addBackgroundJob([this] { publishInteractiveMarkers(false); }, "publishInteractiveMarkers");
802 }
803 
805 {
806  if (robot_interaction_)
807  {
808  if (pose_update &&
809  robot_interaction_->showingMarkers(query_start_state_) == query_start_state_property_->getBool() &&
810  robot_interaction_->showingMarkers(query_goal_state_) == query_goal_state_property_->getBool())
811  {
812  if (query_start_state_property_->getBool())
813  robot_interaction_->updateInteractiveMarkers(query_start_state_);
814  if (query_goal_state_property_->getBool())
815  robot_interaction_->updateInteractiveMarkers(query_goal_state_);
816  }
817  else
818  {
819  robot_interaction_->clearInteractiveMarkers();
820  if (query_start_state_property_->getBool())
821  robot_interaction_->addInteractiveMarkers(query_start_state_, query_marker_scale_property_->getFloat());
822  if (query_goal_state_property_->getBool())
823  robot_interaction_->addInteractiveMarkers(query_goal_state_, query_marker_scale_property_->getFloat());
824  robot_interaction_->publishInteractiveMarkers();
825  }
826  if (frame_)
827  {
829  }
830  }
831 }
832 
833 void MotionPlanningDisplay::changedQueryStartColor()
834 {
835  std_msgs::msg::ColorRGBA color;
836  QColor qcolor = query_start_color_property_->getColor();
837  color.r = qcolor.redF();
838  color.g = qcolor.greenF();
839  color.b = qcolor.blueF();
840  color.a = 1.0f;
841  query_robot_start_->setDefaultAttachedObjectColor(color);
842  changedQueryStartState();
843 }
844 
845 void MotionPlanningDisplay::changedQueryStartAlpha()
846 {
847  query_robot_start_->setAlpha(query_start_alpha_property_->getFloat());
848  changedQueryStartState();
849 }
850 
851 void MotionPlanningDisplay::changedQueryMarkerScale()
852 {
854  return;
855 
856  if (isEnabled())
857  {
858  // Clear the interactive markers and re-add them:
860  }
861 }
862 
863 void MotionPlanningDisplay::changedQueryGoalColor()
864 {
865  std_msgs::msg::ColorRGBA color;
866  QColor qcolor = query_goal_color_property_->getColor();
867  color.r = qcolor.redF();
868  color.g = qcolor.greenF();
869  color.b = qcolor.blueF();
870  color.a = 1.0f;
871  query_robot_goal_->setDefaultAttachedObjectColor(color);
872  changedQueryGoalState();
873 }
874 
875 void MotionPlanningDisplay::changedQueryGoalAlpha()
876 {
877  query_robot_goal_->setAlpha(query_goal_alpha_property_->getFloat());
878  changedQueryGoalState();
879 }
880 
881 void MotionPlanningDisplay::changedQueryCollidingLinkColor()
882 {
883  changedQueryStartState();
884  changedQueryGoalState();
885 }
886 
887 void MotionPlanningDisplay::changedQueryJointViolationColor()
888 {
889  changedQueryStartState();
890  changedQueryGoalState();
891 }
892 
893 void MotionPlanningDisplay::changedAttachedBodyColor()
894 {
896  // forward color to TrajectoryVisualization
897  const QColor& color = attached_body_color_property_->getColor();
898  trajectory_visual_->setDefaultAttachedObjectColor(color);
899 }
900 
902  bool error_state_changed)
903 {
905  return;
906  addBackgroundJob([this, pose_update = !error_state_changed] { publishInteractiveMarkers(pose_update); },
907  "publishInteractiveMarkers");
909 }
910 
912  bool error_state_changed)
913 {
915  return;
916  addBackgroundJob([this, pose_update = !error_state_changed] { publishInteractiveMarkers(pose_update); },
917  "publishInteractiveMarkers");
919 }
920 
922 {
925  addMainLoopJob([this] { changedQueryStartState(); });
926  context_->queueRender();
927 }
928 
930 {
933  addMainLoopJob([this] { changedQueryGoalState(); });
934  context_->queueRender();
935 }
936 
938 {
939  *previous_state_ = *query_start_state_->getState();
940 }
941 
943 {
944  query_start_state_->setState(start);
946 }
947 
949 {
950  query_goal_state_->setState(goal);
952 }
953 
955 {
956  if (robot_interaction_)
957  {
960  robot_interaction_->getKinematicOptionsMap()->setOptions(
963  }
964 }
965 
968  const double* ik_solution) const
969 {
970  if (frame_->ui_->collision_aware_ik->isChecked() && planning_scene_monitor_)
971  {
972  state->setJointGroupPositions(group, ik_solution);
973  state->update();
974  bool res = !getPlanningSceneRO()->isStateColliding(*state, group->getName());
975  return res;
976  }
977  else
978  return true;
979 }
980 
982 {
983  unsetAllColors(&query_robot_start_->getRobot());
984  unsetAllColors(&query_robot_goal_->getRobot());
985  std::string group = planning_group_property_->getStdString();
986  if (!group.empty())
987  {
990 
991  for (std::map<std::string, LinkDisplayStatus>::const_iterator it = status_links_start_.begin();
992  it != status_links_start_.end(); ++it)
993  if (it->second == COLLISION_LINK)
994  setLinkColor(&query_robot_start_->getRobot(), it->first, query_colliding_link_color_property_->getColor());
995  else
996  setLinkColor(&query_robot_start_->getRobot(), it->first,
998 
999  for (std::map<std::string, LinkDisplayStatus>::const_iterator it = status_links_goal_.begin();
1000  it != status_links_goal_.end(); ++it)
1001  if (it->second == COLLISION_LINK)
1002  setLinkColor(&query_robot_goal_->getRobot(), it->first, query_colliding_link_color_property_->getColor());
1003  else
1004  setLinkColor(&query_robot_goal_->getRobot(), it->first,
1006  }
1007 }
1008 
1010 {
1011  if (!getRobotModel() || !robot_interaction_)
1012  return;
1013 
1014  if (getRobotModel()->hasJointModelGroup(group))
1015  {
1016  planning_group_property_->setStdString(group);
1017  }
1018  else
1019  RCLCPP_ERROR(LOGGER, "Group [%s] not found in the robot model.", group.c_str());
1020 }
1021 
1022 void MotionPlanningDisplay::changedPlanningGroup()
1023 {
1024  if (!getRobotModel() || !robot_interaction_)
1025  return;
1026 
1027  if (!planning_group_property_->getStdString().empty() &&
1028  !getRobotModel()->hasJointModelGroup(planning_group_property_->getStdString()))
1029  {
1030  planning_group_property_->setStdString("");
1031  return;
1032  }
1033  modified_groups_.insert(planning_group_property_->getStdString());
1034 
1035  robot_interaction_->decideActiveComponents(planning_group_property_->getStdString());
1036 
1039  updateLinkColors();
1040 
1041  if (frame_)
1043  addBackgroundJob([this] { publishInteractiveMarkers(false); }, "publishInteractiveMarkers");
1044 }
1045 
1046 void MotionPlanningDisplay::changedWorkspace()
1047 {
1049 }
1050 
1052 {
1053  return planning_group_property_->getStdString();
1054 }
1055 
1056 void MotionPlanningDisplay::setQueryStateHelper(bool use_start_state, const std::string& state_name)
1057 {
1058  moveit::core::RobotState state = use_start_state ? *getQueryStartState() : *getQueryGoalState();
1059 
1060  std::string v = "<" + state_name + ">";
1061 
1062  if (v == "<random>")
1063  {
1065  state.setToRandomPositions(jmg);
1066  }
1067  else if (v == "<current>")
1068  {
1070  if (ps)
1071  state = ps->getCurrentState();
1072  }
1073  else if (v == "<same as goal>")
1074  {
1075  state = *getQueryGoalState();
1076  }
1077  else if (v == "<same as start>")
1078  {
1079  state = *getQueryStartState();
1080  }
1081  else
1082  {
1083  // maybe it is a named state
1085  state.setToDefaultValues(jmg, state_name);
1086  }
1087 
1088  use_start_state ? setQueryStartState(state) : setQueryGoalState(state);
1089 }
1090 
1091 void MotionPlanningDisplay::populateMenuHandler(std::shared_ptr<interactive_markers::MenuHandler>& mh)
1092 {
1093  typedef interactive_markers::MenuHandler immh;
1094  std::vector<std::string> state_names;
1095  state_names.push_back("random");
1096  state_names.push_back("current");
1097  state_names.push_back("same as start");
1098  state_names.push_back("same as goal");
1099 
1100  // hacky way to distinguish between the start and goal handlers...
1101  bool is_start = (mh.get() == menu_handler_start_.get());
1102 
1103  // Commands for changing the state
1104  immh::EntryHandle menu_states =
1105  mh->insert(is_start ? "Set start state to" : "Set goal state to", immh::FeedbackCallback());
1106  for (const std::string& state_name : state_names)
1107  {
1108  // Don't add "same as start" to the start state handler, and vice versa.
1109  if ((state_name == "same as start" && is_start) || (state_name == "same as goal" && !is_start))
1110  continue;
1111  mh->insert(menu_states, state_name,
1112  [this, is_start, state_name](auto&&) { setQueryStateHelper(is_start, state_name); });
1113  }
1114 
1115  // // Group commands, which end up being the same for both interaction handlers
1116  // const std::vector<std::string>& group_names = getRobotModel()->getJointModelGroupNames();
1117  // immh::EntryHandle menu_groups = mh->insert("Planning Group", immh::FeedbackCallback());
1118  // for (int i = 0; i < group_names.size(); ++i)
1119  // mh->insert(menu_groups, group_names[i],
1120  // [this, &name = group_names[i]] { changePlanningGroup(name); });
1121 }
1122 
1124 {
1125  // Invalidate all references to the RobotModel ...
1126  if (frame_)
1128  if (trajectory_visual_)
1129  trajectory_visual_->clearRobotModel();
1130  previous_state_.reset();
1131  query_start_state_.reset();
1132  query_goal_state_.reset();
1133  kinematics_metrics_.reset();
1134  robot_interaction_.reset();
1135  dynamics_solver_.clear();
1136  // ... before calling the parent's method, which finally destroys the creating RobotModelLoader.
1138 }
1139 
1141 {
1143  trajectory_visual_->onRobotModelLoaded(getRobotModel());
1144 
1145  robot_interaction_ = std::make_shared<robot_interaction::RobotInteraction>(
1146  getRobotModel(), node_, rclcpp::names::append(getMoveGroupNS(), "rviz_moveit_motion_planning_display"));
1148  o.state_validity_callback_ = [this](moveit::core::RobotState* robot_state,
1149  const moveit::core::JointModelGroup* joint_group,
1150  const double* joint_group_variable_values) {
1151  return isIKSolutionCollisionFree(robot_state, joint_group, joint_group_variable_values);
1152  };
1153  robot_interaction_->getKinematicOptionsMap()->setOptions(
1155 
1156  int_marker_display_->subProp("Interactive Markers Namespace")
1157  ->setValue(QString::fromStdString(robot_interaction_->getServerTopic()));
1158  query_robot_start_->load(*getRobotModel()->getURDF());
1159  query_robot_goal_->load(*getRobotModel()->getURDF());
1160 
1161  // initialize previous state, start state, and goal state to current state
1162  previous_state_ = std::make_shared<moveit::core::RobotState>(getPlanningSceneRO()->getCurrentState());
1163  query_start_state_ = std::make_shared<robot_interaction::InteractionHandler>(
1164  robot_interaction_, "start", *previous_state_, planning_scene_monitor_->getTFClient());
1165  query_goal_state_ = std::make_shared<robot_interaction::InteractionHandler>(
1166  robot_interaction_, "goal", *previous_state_, planning_scene_monitor_->getTFClient());
1167  query_start_state_->setUpdateCallback(
1168  [this](robot_interaction::InteractionHandler* handler, bool error_state_changed) {
1169  scheduleDrawQueryStartState(handler, error_state_changed);
1170  });
1171  query_goal_state_->setUpdateCallback([this](robot_interaction::InteractionHandler* handler, bool error_state_changed) {
1172  scheduleDrawQueryGoalState(handler, error_state_changed);
1173  });
1174 
1175  // Interactive marker menus
1178  query_start_state_->setMenuHandler(menu_handler_start_);
1179  query_goal_state_->setMenuHandler(menu_handler_goal_);
1180 
1181  if (!planning_group_property_->getStdString().empty())
1182  if (!getRobotModel()->hasJointModelGroup(planning_group_property_->getStdString()))
1183  planning_group_property_->setStdString("");
1184 
1185  const std::vector<std::string>& groups = getRobotModel()->getJointModelGroupNames();
1186  planning_group_property_->clearOptions();
1187  for (const std::string& group : groups)
1188  planning_group_property_->addOptionStd(group);
1189  planning_group_property_->sortOptions();
1190  if (!groups.empty() && planning_group_property_->getStdString().empty())
1191  planning_group_property_->setStdString(groups[0]);
1192 
1193  modified_groups_.clear();
1194  kinematics_metrics_ = std::make_shared<kinematics_metrics::KinematicsMetrics>(getRobotModel());
1195 
1196  geometry_msgs::msg::Vector3 gravity_vector;
1197  gravity_vector.x = 0.0;
1198  gravity_vector.y = 0.0;
1199  gravity_vector.z = 9.81;
1200 
1201  dynamics_solver_.clear();
1202  for (const std::string& group : groups)
1203  if (getRobotModel()->getJointModelGroup(group)->isChain())
1205  std::make_shared<dynamics_solver::DynamicsSolver>(getRobotModel(), group, gravity_vector);
1206 
1207  if (frame_)
1208  frame_->fillPlanningGroupOptions();
1209  changedPlanningGroup();
1210 }
1212 {
1213  frame_->onNewPlanningSceneState();
1214 }
1215 
1217  const moveit::core::RobotState& src)
1218 {
1219  moveit::core::RobotState src_copy = src;
1220  for (const std::string& modified_group : modified_groups_)
1221  {
1222  const moveit::core::JointModelGroup* jmg = dest.getJointModelGroup(modified_group);
1223  if (jmg)
1224  {
1225  std::vector<double> values_to_keep;
1226  dest.copyJointGroupPositions(jmg, values_to_keep);
1227  src_copy.setJointGroupPositions(jmg, values_to_keep);
1228  }
1229  }
1230 
1231  // overwrite the destination state
1232  dest = src_copy;
1233 }
1234 
1236 {
1237  std::string group = planning_group_property_->getStdString();
1238 
1239  if (query_start_state_ && query_start_state_property_->getBool() && !group.empty())
1240  {
1242  updateStateExceptModified(start, current_state);
1243  setQueryStartState(start);
1244  }
1245 
1246  if (query_goal_state_ && query_goal_state_property_->getBool() && !group.empty())
1247  {
1249  updateStateExceptModified(goal, current_state);
1250  setQueryGoalState(goal);
1251  }
1252 }
1253 
1256 {
1258  updateQueryStates(getPlanningSceneRO()->getCurrentState());
1259  if (frame_)
1260  frame_->sceneUpdate(update_type);
1261 }
1262 
1263 // ******************************************************************************************
1264 // Enable
1265 // ******************************************************************************************
1267 {
1269 
1270  // Planned Path Display
1271  trajectory_visual_->onEnable();
1272 
1273  text_to_display_->setVisible(false);
1274 
1275  query_robot_start_->setVisible(query_start_state_property_->getBool());
1276  query_robot_goal_->setVisible(query_goal_state_property_->getBool());
1277 
1278  int_marker_display_->setEnabled(true);
1279  int_marker_display_->setFixedFrame(fixed_frame_);
1280 
1281  frame_->enable();
1282 }
1283 
1284 // ******************************************************************************************
1285 // Disable
1286 // ******************************************************************************************
1288 {
1289  if (robot_interaction_)
1290  robot_interaction_->clear();
1291  int_marker_display_->setEnabled(false);
1292 
1293  query_robot_start_->setVisible(false);
1294  query_robot_goal_->setVisible(false);
1295  text_to_display_->setVisible(false);
1296 
1298 
1299  // Planned Path Display
1300  trajectory_visual_->onDisable();
1301 
1302  frame_->disable();
1303 }
1304 
1305 // ******************************************************************************************
1306 // Update
1307 // ******************************************************************************************
1308 void MotionPlanningDisplay::update(float wall_dt, float ros_dt)
1309 {
1310  if (int_marker_display_)
1311  int_marker_display_->update(wall_dt, ros_dt);
1312  if (frame_)
1313  frame_->updateSceneMarkers(wall_dt, ros_dt);
1314 
1315  PlanningSceneDisplay::update(wall_dt, ros_dt);
1316 }
1317 
1318 void MotionPlanningDisplay::updateInternal(float wall_dt, float ros_dt)
1319 {
1320  PlanningSceneDisplay::updateInternal(wall_dt, ros_dt);
1321 
1322  // Planned Path Display
1323  trajectory_visual_->update(wall_dt, ros_dt);
1324 
1326 }
1327 
1328 void MotionPlanningDisplay::load(const rviz_common::Config& config)
1329 {
1331  if (frame_)
1332  {
1333  float d;
1334  if (config.mapGetFloat("MoveIt_Planning_Time", &d))
1335  frame_->ui_->planning_time->setValue(d);
1336  int attempts;
1337  if (config.mapGetInt("MoveIt_Planning_Attempts", &attempts))
1338  frame_->ui_->planning_attempts->setValue(attempts);
1339  if (config.mapGetFloat("Velocity_Scaling_Factor", &d))
1340  frame_->ui_->velocity_scaling_factor->setValue(d);
1341  if (config.mapGetFloat("Acceleration_Scaling_Factor", &d))
1342  frame_->ui_->acceleration_scaling_factor->setValue(d);
1343 
1344  bool b;
1345  if (config.mapGetBool("MoveIt_Allow_Replanning", &b))
1346  frame_->ui_->allow_replanning->setChecked(b);
1347  if (config.mapGetBool("MoveIt_Allow_Sensor_Positioning", &b))
1348  frame_->ui_->allow_looking->setChecked(b);
1349  if (config.mapGetBool("MoveIt_Allow_External_Program", &b))
1350  frame_->ui_->allow_external_program->setChecked(b);
1351  if (config.mapGetBool("MoveIt_Use_Cartesian_Path", &b))
1352  frame_->ui_->use_cartesian_path->setChecked(b);
1353  if (config.mapGetBool("MoveIt_Use_Constraint_Aware_IK", &b))
1354  frame_->ui_->collision_aware_ik->setChecked(b);
1355  if (config.mapGetBool("MoveIt_Allow_Approximate_IK", &b))
1356  frame_->ui_->approximate_ik->setChecked(b);
1357 
1358  rviz_common::Config workspace = config.mapGetChild("MoveIt_Workspace");
1359  rviz_common::Config ws_center = workspace.mapGetChild("Center");
1360  float val;
1361  if (ws_center.mapGetFloat("X", &val))
1362  frame_->ui_->wcenter_x->setValue(val);
1363  if (ws_center.mapGetFloat("Y", &val))
1364  frame_->ui_->wcenter_y->setValue(val);
1365  if (ws_center.mapGetFloat("Z", &val))
1366  frame_->ui_->wcenter_z->setValue(val);
1367 
1368  rviz_common::Config ws_size = workspace.mapGetChild("Size");
1369  if (ws_size.isValid())
1370  {
1371  if (ws_size.mapGetFloat("X", &val))
1372  frame_->ui_->wsize_x->setValue(val);
1373  if (ws_size.mapGetFloat("Y", &val))
1374  frame_->ui_->wsize_y->setValue(val);
1375  if (ws_size.mapGetFloat("Z", &val))
1376  frame_->ui_->wsize_z->setValue(val);
1377  }
1378  else
1379  {
1380  double val;
1381  if (node_->get_parameter("default_workspace_bounds", val))
1382  {
1383  frame_->ui_->wsize_x->setValue(val);
1384  frame_->ui_->wsize_y->setValue(val);
1385  frame_->ui_->wsize_z->setValue(val);
1386  }
1387  }
1388  }
1389 }
1390 
1391 void MotionPlanningDisplay::save(rviz_common::Config config) const
1392 {
1394  if (frame_)
1395  {
1396  // "Options" Section
1397  config.mapSetValue("MoveIt_Planning_Time", frame_->ui_->planning_time->value());
1398  config.mapSetValue("MoveIt_Planning_Attempts", frame_->ui_->planning_attempts->value());
1399  config.mapSetValue("Velocity_Scaling_Factor", frame_->ui_->velocity_scaling_factor->value());
1400  config.mapSetValue("Acceleration_Scaling_Factor", frame_->ui_->acceleration_scaling_factor->value());
1401 
1402  config.mapSetValue("MoveIt_Allow_Replanning", frame_->ui_->allow_replanning->isChecked());
1403  config.mapSetValue("MoveIt_Allow_Sensor_Positioning", frame_->ui_->allow_looking->isChecked());
1404  config.mapSetValue("MoveIt_Allow_External_Program", frame_->ui_->allow_external_program->isChecked());
1405  config.mapSetValue("MoveIt_Use_Cartesian_Path", frame_->ui_->use_cartesian_path->isChecked());
1406  config.mapSetValue("MoveIt_Use_Constraint_Aware_IK", frame_->ui_->collision_aware_ik->isChecked());
1407  config.mapSetValue("MoveIt_Allow_Approximate_IK", frame_->ui_->approximate_ik->isChecked());
1408 
1409  rviz_common::Config workspace = config.mapMakeChild("MoveIt_Workspace");
1410  rviz_common::Config ws_center = workspace.mapMakeChild("Center");
1411  ws_center.mapSetValue("X", frame_->ui_->wcenter_x->value());
1412  ws_center.mapSetValue("Y", frame_->ui_->wcenter_y->value());
1413  ws_center.mapSetValue("Z", frame_->ui_->wcenter_z->value());
1414  rviz_common::Config ws_size = workspace.mapMakeChild("Size");
1415  ws_size.mapSetValue("X", frame_->ui_->wsize_x->value());
1416  ws_size.mapSetValue("Y", frame_->ui_->wsize_y->value());
1417  ws_size.mapSetValue("Z", frame_->ui_->wsize_z->value());
1418  }
1419 }
1420 
1422 {
1424  if (int_marker_display_)
1425  int_marker_display_->setFixedFrame(fixed_frame_);
1426  // When the fixed frame changes we need to tell RViz to update the rendered interactive marker display
1427  if (frame_ && frame_->scene_marker_)
1428  frame_->scene_marker_->requestPoseUpdate(frame_->scene_marker_->getPosition(),
1429  frame_->scene_marker_->getOrientation());
1430  changedPlanningGroup();
1431 }
1432 
1433 // Pick and place
1435 {
1436  for (std::shared_ptr<rviz_rendering::Shape>& place_location_shape : place_locations_display_)
1437  place_location_shape.reset();
1438  place_locations_display_.clear();
1439 }
1440 
1441 void MotionPlanningDisplay::visualizePlaceLocations(const std::vector<geometry_msgs::msg::PoseStamped>& place_poses)
1442 {
1444  place_locations_display_.resize(place_poses.size());
1445  for (std::size_t i = 0; i < place_poses.size(); ++i)
1446  {
1448  std::make_shared<rviz_rendering::Shape>(rviz_rendering::Shape::Sphere, context_->getSceneManager());
1449  place_locations_display_[i]->setColor(1.0f, 0.0f, 0.0f, 0.3f);
1450  Ogre::Vector3 center(place_poses[i].pose.position.x, place_poses[i].pose.position.y, place_poses[i].pose.position.z);
1451  Ogre::Vector3 extents(0.02, 0.02, 0.02);
1452  place_locations_display_[i]->setScale(extents);
1453  place_locations_display_[i]->setPosition(center);
1454  }
1455 }
1456 
1457 } // namespace moveit_rviz_plugin
const std::vector< std::string > & getLinkModelNames() const
Get the names of the links that are part of this joint group.
const std::vector< const JointModel * > & getActiveJointModels() const
Get the active joints in this group (that have controllable DOF). This does not include mimic joints.
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
Definition: joint_model.h:117
A link from the robot. Contains the constant transform applied to the link and its geometry.
Definition: link_model.h:72
Representation of a robot's state. This includes position, velocity, acceleration and effort.
Definition: robot_state.h:90
void setJointGroupPositions(const std::string &joint_group_name, const double *gstate)
Given positions for the variables that make up a group, in the order found in the group (including va...
Definition: robot_state.h:605
void copyJointGroupPositions(const std::string &joint_group_name, std::vector< double > &gstate) const
For a given group, copy the position values of the variables that make up the group into another loca...
Definition: robot_state.h:691
const JointModelGroup * getJointModelGroup(const std::string &group) const
Get the model of a particular joint group.
Definition: robot_state.h:134
void setToRandomPositions()
Set all joints to random values. Values will be within default bounds.
void update(bool force=false)
Update all transforms.
void setToDefaultValues()
Set all joints to their default positions. The default position is 0, or if that is not within bounds...
void clearJobUpdateEvent()
Clear the callback to be triggered when events in JobEvent take place.
void setJobUpdateEvent(const JobUpdateCallback &event)
Set the callback to be triggered when events in JobEvent take place.
std::size_t getJobCount() const
Get the size of the queue of jobs (includes currently processed job).
void populateMenuHandler(std::shared_ptr< interactive_markers::MenuHandler > &mh)
RobotStateVisualizationPtr query_robot_start_
Handles drawing the robot at the start configuration.
void scheduleDrawQueryGoalState(robot_interaction::InteractionHandler *handler, bool error_state_changed)
kinematics_metrics::KinematicsMetricsPtr kinematics_metrics_
rviz_common::properties::FloatProperty * metrics_text_height_property_
void updateInternal(float wall_dt, float ros_dt) override
void onNewPlanningSceneState() override
This is called upon successful retrieval of the (initial) planning scene state.
void save(rviz_common::Config config) const override
moveit::core::RobotStatePtr previous_state_
remember previous start state (updated before starting execution)
void backgroundJobUpdate(moveit::tools::BackgroundProcessing::JobEvent event, const std::string &jobname)
rviz_common::properties::BoolProperty * show_joint_torques_property_
void displayTable(const std::map< std::string, double > &values, const Ogre::ColourValue &color, const Ogre::Vector3 &pos, const Ogre::Quaternion &orient)
rviz_common::properties::FloatProperty * query_marker_scale_property_
void updateStateExceptModified(moveit::core::RobotState &dest, const moveit::core::RobotState &src)
bool text_display_for_start_
indicates whether the text display is for the start state or not
robot_interaction::RobotInteractionPtr robot_interaction_
rviz_common::properties::BoolProperty * show_manipulability_property_
void setQueryGoalState(const moveit::core::RobotState &goal)
robot_interaction::InteractionHandlerPtr query_start_state_
std::map< std::string, LinkDisplayStatus > status_links_goal_
void setQueryStartState(const moveit::core::RobotState &start)
rviz_common::properties::ColorProperty * query_outside_joint_limits_link_color_property_
rviz_common::properties::FloatProperty * query_goal_alpha_property_
rviz_common::properties::ColorProperty * query_start_color_property_
void computeMetricsInternal(std::map< std::string, double > &metrics, const robot_interaction::EndEffectorInteraction &eef, const moveit::core::RobotState &state, double payload)
void computeMetrics(bool start, const std::string &group, double payload)
rviz_common::properties::Property * path_category_
rviz_common::properties::FloatProperty * metrics_set_payload_property_
void setQueryStateHelper(bool use_start_state, const std::string &v)
std::map< std::string, bool > position_only_ik_
Some groups use position only ik, calls to the metrics have to be modified appropriately.
rviz_common::properties::ColorProperty * query_goal_color_property_
rviz_common::properties::BoolProperty * compute_weight_limit_property_
std::unique_ptr< rviz_rendering::Shape > workspace_box_
std::map< std::pair< bool, std::string >, std::map< std::string, double > > computed_metrics_
std::map< std::string, LinkDisplayStatus > status_links_start_
Ogre::SceneNode * text_display_scene_node_
displays texts
void updateQueryStates(const moveit::core::RobotState &current_state)
rviz_common::properties::EditableEnumProperty * planning_group_property_
rviz_common::properties::BoolProperty * show_manipulability_index_property_
rviz_common::properties::Property * metrics_category_
std::shared_ptr< interactive_markers::MenuHandler > menu_handler_start_
void scheduleDrawQueryStartState(robot_interaction::InteractionHandler *handler, bool error_state_changed)
std::map< std::string, dynamics_solver::DynamicsSolverPtr > dynamics_solver_
moveit::core::RobotStateConstPtr getQueryStartState() const
rviz_common::properties::BoolProperty * show_workspace_property_
rviz_common::properties::BoolProperty * query_goal_state_property_
void load(const rviz_common::Config &config) override
bool isIKSolutionCollisionFree(moveit::core::RobotState *state, const moveit::core::JointModelGroup *group, const double *ik_solution) const
rviz_common::properties::FloatProperty * query_start_alpha_property_
std::vector< std::shared_ptr< rviz_rendering::Shape > > place_locations_display_
RobotStateVisualizationPtr query_robot_goal_
Handles drawing the robot at the goal configuration.
void onSceneMonitorReceivedUpdate(planning_scene_monitor::PlanningSceneMonitor::SceneUpdateType update_type) override
void update(float wall_dt, float ros_dt) override
rviz_common::properties::BoolProperty * query_start_state_property_
rviz_common::properties::Property * plan_category_
std::shared_ptr< interactive_markers::MenuHandler > menu_handler_goal_
rclcpp::Subscription< std_msgs::msg::String >::SharedPtr planning_group_sub_
void selectPlanningGroupCallback(const std_msgs::msg::String::ConstSharedPtr &msg)
void onRobotModelLoaded() override
This is an event called by loadRobotModel() in the MainLoop; do not call directly.
rviz_common::properties::ColorProperty * query_colliding_link_color_property_
void visualizePlaceLocations(const std::vector< geometry_msgs::msg::PoseStamped > &place_poses)
moveit::core::RobotStateConstPtr getQueryGoalState() const
robot_interaction::InteractionHandlerPtr query_goal_state_
std::shared_ptr< rviz_default_plugins::displays::InteractiveMarker > scene_marker_
void updateSceneMarkers(float wall_dt, float ros_dt)
void sceneUpdate(planning_scene_monitor::PlanningSceneMonitor::SceneUpdateType update_type)
planning_scene_monitor::LockedPlanningSceneRO getPlanningSceneRO() const
get read-only access to planning scene
rviz_common::properties::ColorProperty * attached_body_color_property_
void setLinkColor(const std::string &link_name, const QColor &color)
void save(rviz_common::Config config) const override
virtual void onRobotModelLoaded()
This is an event called by loadRobotModel() in the MainLoop; do not call directly.
void setGroupColor(rviz_default_plugins::robot::Robot *robot, const std::string &group_name, const QColor &color)
virtual void updateInternal(float wall_dt, float ros_dt)
virtual void onSceneMonitorReceivedUpdate(planning_scene_monitor::PlanningSceneMonitor::SceneUpdateType update_type)
void addMainLoopJob(const std::function< void()> &job)
queue the execution of this function for the next time the main update() loop gets called
planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_
const moveit::core::RobotModelConstPtr & getRobotModel() const
void addBackgroundJob(const std::function< void()> &job, const std::string &name)
void update(float wall_dt, float ros_dt) override
void unsetAllColors(rviz_default_plugins::robot::Robot *robot)
Ogre::SceneNode * planning_scene_node_
displays planning scene with everything in it
moveit::tools::BackgroundProcessing background_process_
void load(const rviz_common::Config &config) override
This is a convenience class for obtaining access to an instance of a locked PlanningScene.
static const std::string DEFAULT
When used as key this means the default value.
static const std::string ALL
When used as key this means set ALL keys (including default)
Vec3fX< details::Vec3Data< double > > Vector3d
Definition: fcl_compat.h:89
p
Definition: pick.py:62
std::string append(const std::string &left, const std::string &right)
d
Definition: setup.py:4
name
Definition: setup.py:7
const rclcpp::Logger LOGGER
Definition: async_test.h:31
std::map< std::pair< std::string, std::string >, std::vector< Contact > > ContactMap
A map returning the pairs of body ids in contact, plus their contact details.
std::string parent_group
The name of the group that sustains the end-effector (usually an arm)
Definition: interaction.h:142
kinematics::KinematicsQueryOptions options_
other options
moveit::core::GroupStateValidityCallbackFn state_validity_callback_
This is called to determine if the state is valid.