moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
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 <QShortcut>
69
70#include "ui_motion_planning_rviz_plugin_frame.h"
73
74#include <rclcpp/qos.hpp>
75
76namespace moveit_rviz_plugin
77{
78
79// ******************************************************************************************
80// Base class constructor
81// ******************************************************************************************
84 , text_to_display_(nullptr)
85 , frame_(nullptr)
86 , frame_dock_(nullptr)
87 , menu_handler_start_(std::make_shared<interactive_markers::MenuHandler>())
88 , menu_handler_goal_(std::make_shared<interactive_markers::MenuHandler>())
89 , int_marker_display_(nullptr)
90{
91 // Category Groups
92 plan_category_ = new rviz_common::properties::Property("Planning Request", QVariant(), "", this);
93 metrics_category_ = new rviz_common::properties::Property("Planning Metrics", QVariant(), "", this);
94 path_category_ = new rviz_common::properties::Property("Planned Path", QVariant(), "", this);
95
96 // Metrics category -----------------------------------------------------------------------------------------
98 new rviz_common::properties::BoolProperty("Show Weight Limit", false,
99 "Shows the weight limit at a particular pose for an end-effector",
100 metrics_category_, SLOT(changedShowWeightLimit()), this);
101
103 new rviz_common::properties::BoolProperty("Show Manipulability Index", false,
104 "Shows the manipulability index for an end-effector", metrics_category_,
105 SLOT(changedShowManipulabilityIndex()), this);
106
108 new rviz_common::properties::BoolProperty("Show Manipulability", false,
109 "Shows the manipulability for an end-effector", metrics_category_,
110 SLOT(changedShowManipulability()), this);
111
113 new rviz_common::properties::BoolProperty("Show Joint Torques", false,
114 "Shows the joint torques for a given configuration and payload",
115 metrics_category_, SLOT(changedShowJointTorques()), this);
116
118 new rviz_common::properties::FloatProperty("Payload", 1.0f, "Specify the payload at the end effector (kg)",
119 metrics_category_, SLOT(changedMetricsSetPayload()), this);
121
122 metrics_text_height_property_ = new rviz_common::properties::FloatProperty(
123 "TextHeight", 0.08f, "Text height", metrics_category_, SLOT(changedMetricsTextHeight()), this);
124 metrics_text_height_property_->setMin(0.001);
125
126 // Planning request category -----------------------------------------------------------------------------------------
127
128 planning_group_property_ = new rviz_common::properties::EditableEnumProperty(
129 "Planning Group", "", "The name of the group of links to plan for (from the ones defined in the SRDF)",
130 plan_category_, SLOT(changedPlanningGroup()), this);
131 show_workspace_property_ = new rviz_common::properties::BoolProperty("Show Workspace", false,
132 "Shows the axis-aligned bounding box for "
133 "the workspace allowed for planning",
134 plan_category_, SLOT(changedWorkspace()), this);
136 new rviz_common::properties::BoolProperty("Query Start State", false,
137 "Set a custom start state for the motion planning query",
138 plan_category_, SLOT(changedQueryStartState()), this);
140 new rviz_common::properties::BoolProperty("Query Goal State", true,
141 "Shows the goal state for the motion planning query", plan_category_,
142 SLOT(changedQueryGoalState()), this);
143 query_marker_scale_property_ = new rviz_common::properties::FloatProperty(
144 "Interactive Marker Size", 0.0f,
145 "Specifies scale of the interactive marker overlaid on the robot. 0 is auto scale.", plan_category_,
146 SLOT(changedQueryMarkerScale()), this);
147 query_marker_scale_property_->setMin(0.0f);
148
150 new rviz_common::properties::ColorProperty("Start State Color", QColor(0, 255, 0),
151 "The highlight color for the start state", plan_category_,
152 SLOT(changedQueryStartColor()), this);
154 new rviz_common::properties::FloatProperty("Start State Alpha", 1.0f, "Specifies the alpha for the robot links",
155 plan_category_, SLOT(changedQueryStartAlpha()), this);
156 query_start_alpha_property_->setMin(0.0);
157 query_start_alpha_property_->setMax(1.0);
158
160 new rviz_common::properties::ColorProperty("Goal State Color", QColor(250, 128, 0),
161 "The highlight color for the goal state", plan_category_,
162 SLOT(changedQueryGoalColor()), this);
163
165 new rviz_common::properties::FloatProperty("Goal State Alpha", 1.0f, "Specifies the alpha for the robot links",
166 plan_category_, SLOT(changedQueryGoalAlpha()), this);
167 query_goal_alpha_property_->setMin(0.0);
168 query_goal_alpha_property_->setMax(1.0);
169
171 new rviz_common::properties::ColorProperty("Colliding Link Color", QColor(255, 0, 0),
172 "The highlight color for colliding links", plan_category_,
173 SLOT(changedQueryCollidingLinkColor()), this);
174
175 query_outside_joint_limits_link_color_property_ = new rviz_common::properties::ColorProperty(
176 "Joint Violation Color", QColor(255, 0, 255),
177 "The highlight color for child links of joints that are outside bounds", plan_category_,
178 SLOT(changedQueryJointViolationColor()), this);
179
180 // Trajectory playback / planned path category ---------------------------------------------
181 trajectory_visual_ = std::make_shared<TrajectoryVisualization>(path_category_, this);
182
183 // Start background jobs
185 const std::string& name) { backgroundJobUpdate(event, name); });
186}
187
188// ******************************************************************************************
189// Deconstructor
190// ******************************************************************************************
192{
193 background_process_.clearJobUpdateEvent();
194 clearJobs();
195
196 query_robot_start_.reset();
197 query_robot_goal_.reset();
198
199 delete text_to_display_;
200 delete int_marker_display_;
201 delete frame_dock_;
202}
203
205{
207
208 // Planned Path Display
209 trajectory_visual_->onInitialize(node_, planning_scene_node_, context_);
210 QColor qcolor = attached_body_color_property_->getColor();
211 trajectory_visual_->setDefaultAttachedObjectColor(qcolor);
212
214 std::make_shared<RobotStateVisualization>(planning_scene_node_, context_, "Planning Request Start", nullptr);
215 query_robot_start_->setCollisionVisible(false);
216 query_robot_start_->setVisualVisible(true);
217 query_robot_start_->setVisible(query_start_state_property_->getBool());
218 std_msgs::msg::ColorRGBA color;
219 qcolor = query_start_color_property_->getColor();
220 color.r = qcolor.redF();
221 color.g = qcolor.greenF();
222 color.b = qcolor.blueF();
223 color.a = 1.0f;
224 query_robot_start_->setDefaultAttachedObjectColor(color);
225
227 std::make_shared<RobotStateVisualization>(planning_scene_node_, context_, "Planning Request Goal", nullptr);
228 query_robot_goal_->setCollisionVisible(false);
229 query_robot_goal_->setVisualVisible(true);
230 query_robot_goal_->setVisible(query_goal_state_property_->getBool());
231 qcolor = query_goal_color_property_->getColor();
232 color.r = qcolor.redF();
233 color.g = qcolor.greenF();
234 color.b = qcolor.blueF();
235 query_robot_goal_->setDefaultAttachedObjectColor(color);
236
237 rviz_common::WindowManagerInterface* window_context = context_->getWindowManager();
238 frame_ = new MotionPlanningFrame(this, context_, window_context ? window_context->getParentWindow() : nullptr);
239
240 connect(frame_, SIGNAL(configChanged()), getModel(), SIGNAL(configChanged()));
242 addStatusText("Initialized.");
243
244 // immediately switch to next trajectory display after planning
245 connect(frame_, SIGNAL(planningFinished()), trajectory_visual_.get(), SLOT(interruptCurrentDisplay()));
246
247 if (window_context)
248 {
249 frame_dock_ = window_context->addPane(getName(), frame_);
250 connect(frame_dock_, SIGNAL(visibilityChanged(bool)), this, SLOT(motionPanelVisibilityChange(bool)));
251 frame_dock_->setIcon(getIcon());
252 }
253
255 int_marker_display_->initialize(context_);
256
257 text_display_scene_node_ = planning_scene_node_->createChildSceneNode();
258 text_to_display_ = new rviz_rendering::MovableText("EMPTY");
259 text_to_display_->setTextAlignment(rviz_rendering::MovableText::H_CENTER, rviz_rendering::MovableText::V_CENTER);
260 text_to_display_->setCharacterHeight(metrics_text_height_property_->getFloat());
261 text_to_display_->showOnTop();
262 text_to_display_->setVisible(false);
265
266 if (context_ && context_->getWindowManager() && context_->getWindowManager()->getParentWindow())
267 {
268 QShortcut* im_reset_shortcut =
269 new QShortcut(QKeySequence("Ctrl+I"), context_->getWindowManager()->getParentWindow());
270 connect(im_reset_shortcut, SIGNAL(activated()), this, SLOT(resetInteractiveMarkers()));
271 }
272}
273
274void MotionPlanningDisplay::motionPanelVisibilityChange(bool enable)
275{
276 if (enable)
277 setEnabled(true);
278}
279
281{
282 if (enable)
283 {
284 planning_group_sub_ = node_->create_subscription<std_msgs::msg::String>(
285 "/rviz/moveit/select_planning_group", rclcpp::ServicesQoS(),
286 [this](const std_msgs::msg::String::ConstSharedPtr& msg) { return selectPlanningGroupCallback(msg); });
287 }
288 else
289 {
290 planning_group_sub_.reset();
291 }
292}
293
294void MotionPlanningDisplay::selectPlanningGroupCallback(const std_msgs::msg::String::ConstSharedPtr& msg)
295{
296 // synchronize ROS callback with main loop
297 addMainLoopJob([this, group = msg->data] { changePlanningGroup(group); });
298}
299
301{
302 text_to_display_->setVisible(false);
303
304 query_robot_start_->clear();
305 query_robot_goal_->clear();
306
308
309 // Planned Path Display
310 trajectory_visual_->reset();
311
312 bool enabled = isEnabled();
313 frame_->disable();
314 if (enabled)
315 {
316 frame_->enable();
317 query_robot_start_->setVisible(query_start_state_property_->getBool());
318 query_robot_goal_->setVisible(query_goal_state_property_->getBool());
319 }
320}
321
327
329{
330 if (!frame_)
331 return;
332 QProgressBar* p = frame_->ui_->background_job_progress;
333 int n = background_process_.getJobCount();
334
335 if (n == 0)
336 {
337 p->hide();
338 p->setMaximum(0);
339 p->setValue(0);
340 }
341 else
342 {
343 if (p->maximum() < n) // increase max
344 {
345 p->setMaximum(n);
346 if (n > 1) // only show bar if there will be a progress to show
347 {
348 p->show();
349 }
350 }
351 else // progress
352 {
353 p->setValue(p->maximum() - n);
354 }
355 p->update();
356 }
357}
358
359void 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
373void 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
387void 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
401void 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
415void 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
429void MotionPlanningDisplay::changedMetricsTextHeight()
430{
431 text_to_display_->setCharacterHeight(metrics_text_height_property_->getFloat());
432}
433
434void MotionPlanningDisplay::displayTable(const std::map<std::string, double>& values, const Ogre::ColourValue& color,
435 const Ogre::Vector3& pos, const Ogre::Quaternion& orient)
436{
437 if (values.empty())
438 {
439 text_to_display_->setVisible(false);
440 return;
441 }
442
443 // the line we want to render
444 std::stringstream ss;
445 ss.setf(std::ios_base::fixed);
446 ss.precision(2);
447
448 for (const auto& [label, value] : values)
449 ss << label << ':' << value << '\n';
450
451 text_to_display_->setCaption(ss.str());
452 text_to_display_->setColor(color);
453 text_display_scene_node_->setPosition(pos);
454 text_display_scene_node_->setOrientation(orient);
455
456 // make sure the node is visible
457 text_to_display_->setVisible(true);
458}
459
461{
462 if (!frame_ || !show_workspace_property_->getBool())
463 {
464 if (workspace_box_)
465 workspace_box_.reset();
466 return;
467 }
468
469 if (!workspace_box_)
470 {
471 workspace_box_ = std::make_unique<rviz_rendering::Shape>(rviz_rendering::Shape::Cube, context_->getSceneManager(),
473 workspace_box_->setColor(0.0f, 0.0f, 0.6f, 0.3f);
474 }
475
476 Ogre::Vector3 center(frame_->ui_->wcenter_x->value(), frame_->ui_->wcenter_y->value(),
477 frame_->ui_->wcenter_z->value());
478 Ogre::Vector3 extents(frame_->ui_->wsize_x->value(), frame_->ui_->wsize_y->value(), frame_->ui_->wsize_z->value());
479 workspace_box_->setScale(extents);
480 workspace_box_->setPosition(center);
481}
482
483void MotionPlanningDisplay::computeMetrics(bool start, const std::string& group, double payload)
484{
486 return;
487 const std::vector<robot_interaction::EndEffectorInteraction>& eef = robot_interaction_->getActiveEndEffectors();
488 if (eef.empty())
489 return;
490 std::scoped_lock slock(update_metrics_lock_);
491
492 moveit::core::RobotStateConstPtr state = start ? getQueryStartState() : getQueryGoalState();
494 {
495 if (ee.parent_group == group)
496 computeMetricsInternal(computed_metrics_[std::make_pair(start, group)], ee, *state, payload);
497 }
498}
499
500void MotionPlanningDisplay::computeMetricsInternal(std::map<std::string, double>& metrics,
502 const moveit::core::RobotState& state, double payload)
503{
504 metrics.clear();
505 dynamics_solver::DynamicsSolverPtr ds;
506 std::map<std::string, dynamics_solver::DynamicsSolverPtr>::const_iterator it = dynamics_solver_.find(ee.parent_group);
507 if (it != dynamics_solver_.end())
508 ds = it->second;
509
510 // Max payload
511 if (ds)
512 {
513 double max_payload;
514 unsigned int saturated_joint;
515 std::vector<double> joint_values;
516 state.copyJointGroupPositions(ee.parent_group, joint_values);
517 if (ds->getMaxPayload(joint_values, max_payload, saturated_joint))
518 {
519 metrics["max_payload"] = max_payload;
520 metrics["saturated_joint"] = saturated_joint;
521 }
522 std::vector<double> joint_torques;
523 joint_torques.resize(joint_values.size());
524 if (ds->getPayloadTorques(joint_values, payload, joint_torques))
525 {
526 for (std::size_t i = 0; i < joint_torques.size(); ++i)
527 {
528 std::stringstream stream;
529 stream << "torque[" << i << ']';
530 metrics[stream.str()] = joint_torques[i];
531 }
532 }
533 }
534
536 {
538 node_->get_parameter_or(ee.parent_group + ".position_only_ik", position_only_ik_[ee.parent_group], false);
539
540 double manipulability_index, manipulability;
541 bool position_ik = position_only_ik_[ee.parent_group];
542 if (kinematics_metrics_->getManipulabilityIndex(state, ee.parent_group, manipulability_index, position_ik))
543 metrics["manipulability_index"] = manipulability_index;
544 if (kinematics_metrics_->getManipulability(state, ee.parent_group, manipulability))
545 metrics["manipulability"] = manipulability;
546 }
547}
548
549namespace
550{
551inline void copyItemIfExists(const std::map<std::string, double>& source, std::map<std::string, double>& dest,
552 const std::string& key)
553{
554 std::map<std::string, double>::const_iterator it = source.find(key);
555 if (it != source.end())
556 dest[key] = it->second;
557}
558} // namespace
559
561{
563 return;
564
565 static const Ogre::Quaternion ORIENTATION(1.0, 0.0, 0.0, 0.0);
566 const std::vector<robot_interaction::EndEffectorInteraction>& eef = robot_interaction_->getActiveEndEffectors();
567 if (eef.empty())
568 return;
569
570 moveit::core::RobotStateConstPtr state = start ? getQueryStartState() : getQueryGoalState();
571
573 {
574 Ogre::Vector3 position(0.0, 0.0, 0.0);
575 std::map<std::string, double> text_table;
576 const std::map<std::string, double>& metrics_table = computed_metrics_[std::make_pair(start, ee.parent_group)];
577 if (compute_weight_limit_property_->getBool())
578 {
579 copyItemIfExists(metrics_table, text_table, "max_payload");
580 copyItemIfExists(metrics_table, text_table, "saturated_joint");
581 }
583 copyItemIfExists(metrics_table, text_table, "manipulability_index");
584 if (show_manipulability_property_->getBool())
585 copyItemIfExists(metrics_table, text_table, "manipulability");
586 if (show_joint_torques_property_->getBool())
587 {
588 std::size_t nj = getRobotModel()->getJointModelGroup(ee.parent_group)->getJointModelNames().size();
589 for (size_t j = 0; j < nj; ++j)
590 {
591 std::stringstream stream;
592 stream << "torque[" << j << ']';
593 copyItemIfExists(metrics_table, text_table, stream.str());
594 }
595 }
596
597 const moveit::core::LinkModel* lm = nullptr;
598 const moveit::core::JointModelGroup* jmg = getRobotModel()->getJointModelGroup(ee.parent_group);
599 if (jmg)
600 {
601 if (!jmg->getLinkModelNames().empty())
602 lm = state->getLinkModel(jmg->getLinkModelNames().back());
603 }
604 if (lm)
605 {
606 const Eigen::Vector3d& t = state->getGlobalLinkTransform(lm).translation();
607 position[0] = t.x();
608 position[1] = t.y();
609 position[2] = t.z() + 0.2; // \todo this should be a param
610 }
611 if (start)
612 {
613 displayTable(text_table, query_start_color_property_->getOgreColor(), position, ORIENTATION);
614 }
615 else
616 {
617 displayTable(text_table, query_goal_color_property_->getOgreColor(), position, ORIENTATION);
618 }
620 }
621}
622
624{
626 return;
627
628 if (query_start_state_property_->getBool())
629 {
630 if (isEnabled())
631 {
632 moveit::core::RobotStateConstPtr state = getQueryStartState();
633
634 // update link poses
635 query_robot_start_->update(state);
636 query_robot_start_->setVisible(true);
637
638 // update link colors
639 std::vector<std::string> collision_links;
640 getPlanningSceneRO()->getCollidingLinks(collision_links, *state);
641 status_links_start_.clear();
642 for (const std::string& collision_link : collision_links)
643 status_links_start_[collision_link] = COLLISION_LINK;
644 if (!collision_links.empty())
645 {
647 getPlanningSceneRO()->getCollidingPairs(pairs, *state);
649 addStatusText("Start state colliding links:");
650 for (collision_detection::CollisionResult::ContactMap::const_iterator it = pairs.begin(); it != pairs.end();
651 ++it)
652 addStatusText(it->first.first + " - " + it->first.second);
653 addStatusText(".");
654 }
655 if (!getCurrentPlanningGroup().empty())
656 {
657 const moveit::core::JointModelGroup* jmg = state->getJointModelGroup(getCurrentPlanningGroup());
658 if (jmg)
659 {
660 std::vector<std::string> outside_bounds;
661 const std::vector<const moveit::core::JointModel*>& jmodels = jmg->getActiveJointModels();
662 for (const moveit::core::JointModel* jmodel : jmodels)
663 {
664 if (!state->satisfiesBounds(jmodel, jmodel->getMaximumExtent() * 1e-2))
665 {
666 outside_bounds.push_back(jmodel->getChildLinkModel()->getName());
667 status_links_start_[outside_bounds.back()] = OUTSIDE_BOUNDS_LINK;
668 }
669 }
670 if (!outside_bounds.empty())
671 {
673 addStatusText("Links descending from joints that are outside bounds in start state:");
674 addStatusText(outside_bounds);
675 }
676 }
677 }
679 // update metrics text
680 displayMetrics(true);
681 }
682 }
683 else
684 {
685 query_robot_start_->setVisible(false);
686 }
687 context_->queueRender();
688}
689
694
696{
697 if (frame_)
698 frame_->ui_->status_text->setTextColor(color);
699}
700
701void MotionPlanningDisplay::addStatusText(const std::string& text)
702{
703 if (frame_)
704 frame_->ui_->status_text->append(QString::fromStdString(text));
705}
706
707void MotionPlanningDisplay::addStatusText(const std::vector<std::string>& text)
708{
709 for (const std::string& it : text)
710 addStatusText(it);
711}
712
714{
715 std::string group = planning_group_property_->getStdString();
716 if (!group.empty())
717 computeMetrics(true, group, metrics_set_payload_property_->getFloat());
718}
719
721{
722 std::string group = planning_group_property_->getStdString();
723 if (!group.empty())
724 computeMetrics(false, group, metrics_set_payload_property_->getFloat());
725}
726
727void MotionPlanningDisplay::changedQueryStartState()
728{
730 return;
732 addStatusText("Changed start state");
734 addBackgroundJob([this] { publishInteractiveMarkers(true); }, "publishInteractiveMarkers");
735}
736
737void MotionPlanningDisplay::changedQueryGoalState()
738{
740 return;
742 addStatusText("Changed goal state");
744 addBackgroundJob([this] { publishInteractiveMarkers(true); }, "publishInteractiveMarkers");
745}
746
748{
750 return;
751 if (query_goal_state_property_->getBool())
752 {
753 if (isEnabled())
754 {
755 moveit::core::RobotStateConstPtr state = getQueryGoalState();
756
757 // update link poses
758 query_robot_goal_->update(state);
759 query_robot_goal_->setVisible(true);
760
761 // update link colors
762 std::vector<std::string> collision_links;
763 getPlanningSceneRO()->getCollidingLinks(collision_links, *state);
764 status_links_goal_.clear();
765 for (const std::string& collision_link : collision_links)
766 status_links_goal_[collision_link] = COLLISION_LINK;
767 if (!collision_links.empty())
768 {
770 getPlanningSceneRO()->getCollidingPairs(pairs, *state);
772 addStatusText("Goal state colliding links:");
773 for (collision_detection::CollisionResult::ContactMap::const_iterator it = pairs.begin(); it != pairs.end();
774 ++it)
775 addStatusText(it->first.first + " - " + it->first.second);
776 addStatusText(".");
777 }
778
779 if (!getCurrentPlanningGroup().empty())
780 {
781 const moveit::core::JointModelGroup* jmg = state->getJointModelGroup(getCurrentPlanningGroup());
782 if (jmg)
783 {
784 const std::vector<const moveit::core::JointModel*>& jmodels = jmg->getActiveJointModels();
785 std::vector<std::string> outside_bounds;
786 for (const moveit::core::JointModel* jmodel : jmodels)
787 {
788 if (!state->satisfiesBounds(jmodel, jmodel->getMaximumExtent() * 1e-2))
789 {
790 outside_bounds.push_back(jmodel->getChildLinkModel()->getName());
791 status_links_goal_[outside_bounds.back()] = OUTSIDE_BOUNDS_LINK;
792 }
793 }
794
795 if (!outside_bounds.empty())
796 {
798 addStatusText("Links descending from joints that are outside bounds in goal state:");
799 addStatusText(outside_bounds);
800 }
801 }
802 }
804
805 // update metrics text
806 displayMetrics(false);
807 }
808 }
809 else
810 {
811 query_robot_goal_->setVisible(false);
812 }
813 context_->queueRender();
814}
815
816void MotionPlanningDisplay::resetInteractiveMarkers()
817{
818 query_start_state_->clearError();
819 query_goal_state_->clearError();
820 addBackgroundJob([this] { publishInteractiveMarkers(false); }, "publishInteractiveMarkers");
821}
822
824{
826 {
827 if (pose_update &&
830 {
831 if (query_start_state_property_->getBool())
832 robot_interaction_->updateInteractiveMarkers(query_start_state_);
833 if (query_goal_state_property_->getBool())
834 robot_interaction_->updateInteractiveMarkers(query_goal_state_);
835 }
836 else
837 {
838 robot_interaction_->clearInteractiveMarkers();
839 if (query_start_state_property_->getBool())
840 robot_interaction_->addInteractiveMarkers(query_start_state_, query_marker_scale_property_->getFloat());
841 if (query_goal_state_property_->getBool())
842 robot_interaction_->addInteractiveMarkers(query_goal_state_, query_marker_scale_property_->getFloat());
843 robot_interaction_->publishInteractiveMarkers();
844 }
845 if (frame_)
846 {
847 frame_->updateExternalCommunication();
848 }
849 }
850}
851
852void MotionPlanningDisplay::changedQueryStartColor()
853{
854 std_msgs::msg::ColorRGBA color;
855 QColor qcolor = query_start_color_property_->getColor();
856 color.r = qcolor.redF();
857 color.g = qcolor.greenF();
858 color.b = qcolor.blueF();
859 color.a = 1.0f;
860 query_robot_start_->setDefaultAttachedObjectColor(color);
861 changedQueryStartState();
862}
863
864void MotionPlanningDisplay::changedQueryStartAlpha()
865{
866 query_robot_start_->setAlpha(query_start_alpha_property_->getFloat());
867 changedQueryStartState();
868}
869
870void MotionPlanningDisplay::changedQueryMarkerScale()
871{
873 return;
874
875 if (isEnabled())
876 {
877 // Clear the interactive markers and re-add them:
879 }
880}
881
882void MotionPlanningDisplay::changedQueryGoalColor()
883{
884 std_msgs::msg::ColorRGBA color;
885 QColor qcolor = query_goal_color_property_->getColor();
886 color.r = qcolor.redF();
887 color.g = qcolor.greenF();
888 color.b = qcolor.blueF();
889 color.a = 1.0f;
890 query_robot_goal_->setDefaultAttachedObjectColor(color);
891 changedQueryGoalState();
892}
893
894void MotionPlanningDisplay::changedQueryGoalAlpha()
895{
896 query_robot_goal_->setAlpha(query_goal_alpha_property_->getFloat());
897 changedQueryGoalState();
898}
899
900void MotionPlanningDisplay::changedQueryCollidingLinkColor()
901{
902 changedQueryStartState();
903 changedQueryGoalState();
904}
905
906void MotionPlanningDisplay::changedQueryJointViolationColor()
907{
908 changedQueryStartState();
909 changedQueryGoalState();
910}
911
913{
915 // forward color to TrajectoryVisualization
916 const QColor& color = attached_body_color_property_->getColor();
917 trajectory_visual_->setDefaultAttachedObjectColor(color);
918}
919
921 bool error_state_changed)
922{
924 return;
925 addBackgroundJob([this, pose_update = !error_state_changed] { publishInteractiveMarkers(pose_update); },
926 "publishInteractiveMarkers");
928}
929
931 bool error_state_changed)
932{
934 return;
935 addBackgroundJob([this, pose_update = !error_state_changed] { publishInteractiveMarkers(pose_update); },
936 "publishInteractiveMarkers");
938}
939
941{
944 addMainLoopJob([this] { changedQueryStartState(); });
945 context_->queueRender();
946}
947
949{
952 addMainLoopJob([this] { changedQueryGoalState(); });
953 context_->queueRender();
954}
955
960
966
972
984
987 const double* ik_solution) const
988{
989 if (frame_->ui_->collision_aware_ik->isChecked() && planning_scene_monitor_)
990 {
991 state->setJointGroupPositions(group, ik_solution);
992 state->update();
993 bool res = !getPlanningSceneRO()->isStateColliding(*state, group->getName());
994 return res;
995 }
996 else
997 {
998 return true;
999 }
1000}
1001
1003{
1004 unsetAllColors(&query_robot_start_->getRobot());
1005 unsetAllColors(&query_robot_goal_->getRobot());
1006 std::string group = planning_group_property_->getStdString();
1007 if (!group.empty())
1008 {
1009 setGroupColor(&query_robot_start_->getRobot(), group, query_start_color_property_->getColor());
1010 setGroupColor(&query_robot_goal_->getRobot(), group, query_goal_color_property_->getColor());
1011
1012 for (std::map<std::string, LinkDisplayStatus>::const_iterator it = status_links_start_.begin();
1013 it != status_links_start_.end(); ++it)
1014 {
1015 if (it->second == COLLISION_LINK)
1016 {
1017 setLinkColor(&query_robot_start_->getRobot(), it->first, query_colliding_link_color_property_->getColor());
1018 }
1019 else
1020 {
1021 setLinkColor(&query_robot_start_->getRobot(), it->first,
1023 }
1024 }
1025
1026 for (std::map<std::string, LinkDisplayStatus>::const_iterator it = status_links_goal_.begin();
1027 it != status_links_goal_.end(); ++it)
1028 {
1029 if (it->second == COLLISION_LINK)
1030 {
1031 setLinkColor(&query_robot_goal_->getRobot(), it->first, query_colliding_link_color_property_->getColor());
1032 }
1033 else
1034 {
1035 setLinkColor(&query_robot_goal_->getRobot(), it->first,
1037 }
1038 }
1039 }
1040}
1041
1043{
1045 return;
1046
1047 if (getRobotModel()->hasJointModelGroup(group))
1048 {
1049 planning_group_property_->setStdString(group);
1050 }
1051 else
1052 {
1053 RCLCPP_ERROR(moveit::getLogger("moveit.ros.motion_planning_display"), "Group [%s] not found in the robot model.",
1054 group.c_str());
1055 }
1056}
1057
1058void MotionPlanningDisplay::changedPlanningGroup()
1059{
1061 return;
1062
1063 if (!planning_group_property_->getStdString().empty() &&
1064 !getRobotModel()->hasJointModelGroup(planning_group_property_->getStdString()))
1065 {
1066 planning_group_property_->setStdString("");
1067 return;
1068 }
1069 modified_groups_.insert(planning_group_property_->getStdString());
1070
1071 robot_interaction_->decideActiveComponents(planning_group_property_->getStdString());
1072
1076
1077 if (frame_)
1079 addBackgroundJob([this] { publishInteractiveMarkers(false); }, "publishInteractiveMarkers");
1080}
1081
1082void MotionPlanningDisplay::changedWorkspace()
1083{
1085}
1086
1088{
1089 return planning_group_property_->getStdString();
1090}
1091
1092void MotionPlanningDisplay::setQueryStateHelper(bool use_start_state, const std::string& state_name)
1093{
1094 moveit::core::RobotState state = use_start_state ? *getQueryStartState() : *getQueryGoalState();
1095
1096 std::string v = "<" + state_name + ">";
1097
1098 if (v == "<random>")
1099 {
1101 state.setToRandomPositions(jmg);
1102 }
1103 else if (v == "<current>")
1104 {
1106 if (ps)
1107 state = ps->getCurrentState();
1108 }
1109 else if (v == "<same as goal>")
1110 {
1111 state = *getQueryGoalState();
1112 }
1113 else if (v == "<same as start>")
1114 {
1115 state = *getQueryStartState();
1116 }
1117 else
1118 {
1119 // maybe it is a named state
1121 state.setToDefaultValues(jmg, state_name);
1122 }
1123
1124 use_start_state ? setQueryStartState(state) : setQueryGoalState(state);
1125}
1126
1127void MotionPlanningDisplay::populateMenuHandler(std::shared_ptr<interactive_markers::MenuHandler>& mh)
1128{
1129 typedef interactive_markers::MenuHandler immh;
1130 std::vector<std::string> state_names;
1131 state_names.push_back("random");
1132 state_names.push_back("current");
1133 state_names.push_back("same as start");
1134 state_names.push_back("same as goal");
1135
1136 // hacky way to distinguish between the start and goal handlers...
1137 bool is_start = (mh.get() == menu_handler_start_.get());
1138
1139 // Commands for changing the state
1140 immh::EntryHandle menu_states =
1141 mh->insert(is_start ? "Set start state to" : "Set goal state to", immh::FeedbackCallback());
1142 for (const std::string& state_name : state_names)
1143 {
1144 // Don't add "same as start" to the start state handler, and vice versa.
1145 if ((state_name == "same as start" && is_start) || (state_name == "same as goal" && !is_start))
1146 continue;
1147 mh->insert(menu_states, state_name,
1148 [this, is_start, state_name](auto&&) { setQueryStateHelper(is_start, state_name); });
1149 }
1150
1151 // // Group commands, which end up being the same for both interaction handlers
1152 // const std::vector<std::string>& group_names = getRobotModel()->getJointModelGroupNames();
1153 // immh::EntryHandle menu_groups = mh->insert("Planning Group", immh::FeedbackCallback());
1154 // for (int i = 0; i < group_names.size(); ++i)
1155 // mh->insert(menu_groups, group_names[i],
1156 // [this, &name = group_names[i]] { changePlanningGroup(name); });
1157}
1158
1160{
1161 // Invalidate all references to the RobotModel ...
1162 if (frame_)
1163 frame_->clearRobotModel();
1165 trajectory_visual_->clearRobotModel();
1166 previous_state_.reset();
1167 query_start_state_.reset();
1168 query_goal_state_.reset();
1169 kinematics_metrics_.reset();
1170 robot_interaction_.reset();
1171 dynamics_solver_.clear();
1172 // ... before calling the parent's method, which finally destroys the creating RobotModelLoader.
1174}
1175
1177{
1179 trajectory_visual_->onRobotModelLoaded(getRobotModel());
1180
1181 robot_interaction_ = std::make_shared<robot_interaction::RobotInteraction>(
1182 getRobotModel(), node_, rclcpp::names::append(getMoveGroupNS(), "rviz_moveit_motion_planning_display"));
1184 o.state_validity_callback_ = [this](moveit::core::RobotState* robot_state,
1185 const moveit::core::JointModelGroup* joint_group,
1186 const double* joint_group_variable_values) {
1187 return isIKSolutionCollisionFree(robot_state, joint_group, joint_group_variable_values);
1188 };
1189 robot_interaction_->getKinematicOptionsMap()->setOptions(
1191
1192 int_marker_display_->subProp("Interactive Markers Namespace")
1193 ->setValue(QString::fromStdString(robot_interaction_->getServerTopic()));
1194 query_robot_start_->load(*getRobotModel()->getURDF());
1195 query_robot_goal_->load(*getRobotModel()->getURDF());
1196
1197 // initialize previous state, start state, and goal state to current state
1198 previous_state_ = std::make_shared<moveit::core::RobotState>(getPlanningSceneRO()->getCurrentState());
1199 query_start_state_ = std::make_shared<robot_interaction::InteractionHandler>(
1201 query_goal_state_ = std::make_shared<robot_interaction::InteractionHandler>(
1203 query_start_state_->setUpdateCallback(
1204 [this](robot_interaction::InteractionHandler* handler, bool error_state_changed) {
1205 scheduleDrawQueryStartState(handler, error_state_changed);
1206 });
1207 query_goal_state_->setUpdateCallback([this](robot_interaction::InteractionHandler* handler, bool error_state_changed) {
1208 scheduleDrawQueryGoalState(handler, error_state_changed);
1209 });
1210
1211 // Interactive marker menus
1214 query_start_state_->setMenuHandler(menu_handler_start_);
1215 query_goal_state_->setMenuHandler(menu_handler_goal_);
1216
1217 if (!planning_group_property_->getStdString().empty())
1218 {
1219 if (!getRobotModel()->hasJointModelGroup(planning_group_property_->getStdString()))
1220 planning_group_property_->setStdString("");
1221 }
1222
1223 const std::vector<std::string>& groups = getRobotModel()->getJointModelGroupNames();
1224 planning_group_property_->clearOptions();
1225 for (const std::string& group : groups)
1226 planning_group_property_->addOptionStd(group);
1227 planning_group_property_->sortOptions();
1228 if (!groups.empty() && planning_group_property_->getStdString().empty())
1229 planning_group_property_->setStdString(groups[0]);
1230
1231 modified_groups_.clear();
1232 kinematics_metrics_ = std::make_shared<kinematics_metrics::KinematicsMetrics>(getRobotModel());
1233
1234 geometry_msgs::msg::Vector3 gravity_vector;
1235 gravity_vector.x = 0.0;
1236 gravity_vector.y = 0.0;
1237 gravity_vector.z = 9.81;
1238
1239 dynamics_solver_.clear();
1240 for (const std::string& group : groups)
1241 {
1242 if (getRobotModel()->getJointModelGroup(group)->isChain())
1243 {
1244 dynamics_solver_[group] =
1245 std::make_shared<dynamics_solver::DynamicsSolver>(getRobotModel(), group, gravity_vector);
1246 }
1247 }
1248
1249 if (frame_)
1250 frame_->fillPlanningGroupOptions();
1251 changedPlanningGroup();
1252}
1254{
1255 frame_->onNewPlanningSceneState();
1256}
1257
1259 const moveit::core::RobotState& src)
1260{
1261 moveit::core::RobotState src_copy = src;
1262 for (const std::string& modified_group : modified_groups_)
1263 {
1264 const moveit::core::JointModelGroup* jmg = dest.getJointModelGroup(modified_group);
1265 if (jmg)
1266 {
1267 std::vector<double> values_to_keep;
1268 dest.copyJointGroupPositions(jmg, values_to_keep);
1269 src_copy.setJointGroupPositions(jmg, values_to_keep);
1270 }
1271 }
1272
1273 // overwrite the destination state
1274 dest = src_copy;
1275}
1276
1278{
1279 std::string group = planning_group_property_->getStdString();
1280
1281 if (query_start_state_ && query_start_state_property_->getBool() && !group.empty())
1282 {
1284 updateStateExceptModified(start, current_state);
1285 setQueryStartState(start);
1286 }
1287
1288 if (query_goal_state_ && query_goal_state_property_->getBool() && !group.empty())
1289 {
1291 updateStateExceptModified(goal, current_state);
1292 setQueryGoalState(goal);
1293 }
1294}
1295
1304
1305// ******************************************************************************************
1306// Enable
1307// ******************************************************************************************
1309{
1311
1312 // Planned Path Display
1313 trajectory_visual_->onEnable();
1314
1315 text_to_display_->setVisible(false);
1316
1317 query_robot_start_->setVisible(query_start_state_property_->getBool());
1318 query_robot_goal_->setVisible(query_goal_state_property_->getBool());
1319
1320 int_marker_display_->setEnabled(true);
1321 int_marker_display_->setFixedFrame(fixed_frame_);
1322
1323 frame_->enable();
1324}
1325
1326// ******************************************************************************************
1327// Disable
1328// ******************************************************************************************
1330{
1332 robot_interaction_->clear();
1333 int_marker_display_->setEnabled(false);
1334
1335 query_robot_start_->setVisible(false);
1336 query_robot_goal_->setVisible(false);
1337 text_to_display_->setVisible(false);
1338
1340
1341 // Planned Path Display
1342 trajectory_visual_->onDisable();
1343
1344 frame_->disable();
1345}
1346
1347// ******************************************************************************************
1348// Update
1349// ******************************************************************************************
1350// For Rolling, L-turtle, and newer
1351#if RCLCPP_VERSION_GTE(30, 0, 0)
1352void MotionPlanningDisplay::update(std::chrono::nanoseconds wall_dt, std::chrono::nanoseconds ros_dt)
1353{
1355 int_marker_display_->update(wall_dt, ros_dt);
1356 if (frame_)
1357 frame_->updateSceneMarkers(wall_dt, ros_dt);
1358
1359 PlanningSceneDisplay::update(wall_dt, ros_dt);
1360}
1361// For Kilted and older
1362#else
1363void MotionPlanningDisplay::update(float wall_dt, float ros_dt)
1364{
1366 int_marker_display_->update(wall_dt, ros_dt);
1367 if (frame_)
1368 frame_->updateSceneMarkers(wall_dt, ros_dt);
1369
1370 PlanningSceneDisplay::update(wall_dt, ros_dt);
1371}
1372#endif
1373
1374void MotionPlanningDisplay::updateInternal(std::chrono::nanoseconds wall_dt, std::chrono::nanoseconds ros_dt)
1375{
1376 PlanningSceneDisplay::updateInternal(wall_dt, ros_dt);
1377
1378 // Planned Path Display
1379 trajectory_visual_->update(wall_dt, ros_dt);
1380
1382}
1383
1384void MotionPlanningDisplay::updateInternal(double wall_dt, double ros_dt)
1385{
1386 updateInternal(std::chrono::nanoseconds(std::lround(wall_dt)), std::chrono::nanoseconds(std::lround(ros_dt)));
1387}
1388
1389void MotionPlanningDisplay::load(const rviz_common::Config& config)
1390{
1392 if (frame_)
1393 {
1394 float d;
1395 if (config.mapGetFloat("MoveIt_Planning_Time", &d))
1396 frame_->ui_->planning_time->setValue(d);
1397 int attempts;
1398 if (config.mapGetInt("MoveIt_Planning_Attempts", &attempts))
1399 frame_->ui_->planning_attempts->setValue(attempts);
1400 if (config.mapGetFloat("Velocity_Scaling_Factor", &d))
1401 frame_->ui_->velocity_scaling_factor->setValue(d);
1402 if (config.mapGetFloat("Acceleration_Scaling_Factor", &d))
1403 frame_->ui_->acceleration_scaling_factor->setValue(d);
1404
1405 bool b;
1406 if (config.mapGetBool("MoveIt_Allow_Replanning", &b))
1407 frame_->ui_->allow_replanning->setChecked(b);
1408 if (config.mapGetBool("MoveIt_Allow_Sensor_Positioning", &b))
1409 frame_->ui_->allow_looking->setChecked(b);
1410 if (config.mapGetBool("MoveIt_Allow_External_Program", &b))
1411 frame_->ui_->allow_external_program->setChecked(b);
1412 if (config.mapGetBool("MoveIt_Use_Cartesian_Path", &b))
1413 frame_->ui_->use_cartesian_path->setChecked(b);
1414 if (config.mapGetBool("MoveIt_Use_Constraint_Aware_IK", &b))
1415 frame_->ui_->collision_aware_ik->setChecked(b);
1416 if (config.mapGetBool("MoveIt_Allow_Approximate_IK", &b))
1417 frame_->ui_->approximate_ik->setChecked(b);
1418
1419 rviz_common::Config workspace = config.mapGetChild("MoveIt_Workspace");
1420 rviz_common::Config ws_center = workspace.mapGetChild("Center");
1421 float val;
1422 if (ws_center.mapGetFloat("X", &val))
1423 frame_->ui_->wcenter_x->setValue(val);
1424 if (ws_center.mapGetFloat("Y", &val))
1425 frame_->ui_->wcenter_y->setValue(val);
1426 if (ws_center.mapGetFloat("Z", &val))
1427 frame_->ui_->wcenter_z->setValue(val);
1428
1429 rviz_common::Config ws_size = workspace.mapGetChild("Size");
1430 if (ws_size.isValid())
1431 {
1432 if (ws_size.mapGetFloat("X", &val))
1433 frame_->ui_->wsize_x->setValue(val);
1434 if (ws_size.mapGetFloat("Y", &val))
1435 frame_->ui_->wsize_y->setValue(val);
1436 if (ws_size.mapGetFloat("Z", &val))
1437 frame_->ui_->wsize_z->setValue(val);
1438 }
1439 else
1440 {
1441 double val;
1442 if (node_->get_parameter("default_workspace_bounds", val))
1443 {
1444 frame_->ui_->wsize_x->setValue(val);
1445 frame_->ui_->wsize_y->setValue(val);
1446 frame_->ui_->wsize_z->setValue(val);
1447 }
1448 }
1449 }
1450}
1451
1452void MotionPlanningDisplay::save(rviz_common::Config config) const
1453{
1455 if (frame_)
1456 {
1457 // "Options" Section
1458 config.mapSetValue("MoveIt_Planning_Time", frame_->ui_->planning_time->value());
1459 config.mapSetValue("MoveIt_Planning_Attempts", frame_->ui_->planning_attempts->value());
1460 config.mapSetValue("Velocity_Scaling_Factor", frame_->ui_->velocity_scaling_factor->value());
1461 config.mapSetValue("Acceleration_Scaling_Factor", frame_->ui_->acceleration_scaling_factor->value());
1462
1463 config.mapSetValue("MoveIt_Allow_Replanning", frame_->ui_->allow_replanning->isChecked());
1464 config.mapSetValue("MoveIt_Allow_Sensor_Positioning", frame_->ui_->allow_looking->isChecked());
1465 config.mapSetValue("MoveIt_Allow_External_Program", frame_->ui_->allow_external_program->isChecked());
1466 config.mapSetValue("MoveIt_Use_Cartesian_Path", frame_->ui_->use_cartesian_path->isChecked());
1467 config.mapSetValue("MoveIt_Use_Constraint_Aware_IK", frame_->ui_->collision_aware_ik->isChecked());
1468 config.mapSetValue("MoveIt_Allow_Approximate_IK", frame_->ui_->approximate_ik->isChecked());
1469
1470 rviz_common::Config workspace = config.mapMakeChild("MoveIt_Workspace");
1471 rviz_common::Config ws_center = workspace.mapMakeChild("Center");
1472 ws_center.mapSetValue("X", frame_->ui_->wcenter_x->value());
1473 ws_center.mapSetValue("Y", frame_->ui_->wcenter_y->value());
1474 ws_center.mapSetValue("Z", frame_->ui_->wcenter_z->value());
1475 rviz_common::Config ws_size = workspace.mapMakeChild("Size");
1476 ws_size.mapSetValue("X", frame_->ui_->wsize_x->value());
1477 ws_size.mapSetValue("Y", frame_->ui_->wsize_y->value());
1478 ws_size.mapSetValue("Z", frame_->ui_->wsize_z->value());
1479 }
1480}
1481
1483{
1486 int_marker_display_->setFixedFrame(fixed_frame_);
1487 // When the fixed frame changes we need to tell RViz to update the rendered interactive marker display
1488 if (frame_ && frame_->scene_marker_)
1489 {
1490 frame_->scene_marker_->requestPoseUpdate(frame_->scene_marker_->getPosition(),
1491 frame_->scene_marker_->getOrientation());
1492 }
1493 changedPlanningGroup();
1494}
1495
1496// Pick and place
1498{
1499 for (std::shared_ptr<rviz_rendering::Shape>& place_location_shape : place_locations_display_)
1500 place_location_shape.reset();
1502}
1503
1504void MotionPlanningDisplay::visualizePlaceLocations(const std::vector<geometry_msgs::msg::PoseStamped>& place_poses)
1505{
1507 place_locations_display_.resize(place_poses.size());
1508 for (std::size_t i = 0; i < place_poses.size(); ++i)
1509 {
1511 std::make_shared<rviz_rendering::Shape>(rviz_rendering::Shape::Sphere, context_->getSceneManager());
1512 place_locations_display_[i]->setColor(1.0f, 0.0f, 0.0f, 0.3f);
1513 Ogre::Vector3 center(place_poses[i].pose.position.x, place_poses[i].pose.position.y, place_poses[i].pose.position.z);
1514 Ogre::Vector3 extents(0.02, 0.02, 0.02);
1515 place_locations_display_[i]->setScale(extents);
1516 place_locations_display_[i]->setPosition(center);
1517 }
1518}
1519
1520} // namespace moveit_rviz_plugin
const std::string & getName() const
Get the name of the 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.
const std::vector< std::string > & getLinkModelNames() const
Get the names of the links that are part of this joint group.
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
A link from the robot. Contains the constant transform applied to the link and its geometry.
Representation of a robot's state. This includes position, velocity, acceleration and effort.
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...
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...
const JointModelGroup * getJointModelGroup(const std::string &group) const
Get the model of a particular joint group.
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 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 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)
void updateInternal(std::chrono::nanoseconds wall_dt, std::chrono::nanoseconds ros_dt) override
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_
void updateSceneMarkers(std::chrono::nanoseconds wall_dt, std::chrono::nanoseconds ros_dt)
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 updateInternal(std::chrono::nanoseconds wall_dt, std::chrono::nanoseconds ros_dt)
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 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
PlanningSceneDisplay(bool listen_to_planning_scene=true, bool show_scene_robot=true)
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).
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
Definition logger.cpp:106
std::string append(const std::string &left, const std::string &right)
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).
kinematics::KinematicsQueryOptions options_
other options
moveit::core::GroupStateValidityCallbackFn state_validity_callback_
This is called to determine if the state is valid.