moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
trajectory_visualization.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: Dave Coleman */
36
37#include <boost/algorithm/string.hpp>
38#include <boost/algorithm/string/replace.hpp>
39
41
44#include <rviz_default_plugins/robot/robot.hpp>
47#include <rviz_common/display_context.hpp>
48#include <rviz_common/properties/bool_property.hpp>
49#include <rviz_common/properties/color_property.hpp>
50#include <rviz_common/properties/editable_enum_property.hpp>
51#include <rviz_common/properties/float_property.hpp>
52#include <rviz_common/properties/int_property.hpp>
53#include <rviz_common/properties/property.hpp>
54#include <rviz_common/properties/ros_topic_property.hpp>
55#include <rviz_common/properties/string_property.hpp>
56#include <rviz_default_plugins/robot/robot_link.hpp>
57#include <rviz_common/window_manager_interface.hpp>
58
59#include <rclcpp/qos.hpp>
60
61#include <cmath>
62#include <string>
63
64using namespace std::placeholders;
65
66namespace moveit_rviz_plugin
67{
68
69TrajectoryVisualization::TrajectoryVisualization(rviz_common::properties::Property* widget,
70 rviz_common::Display* display)
71 : animating_path_(false)
72 , drop_displaying_trajectory_(false)
73 , current_state_(-1)
74 , display_(display)
75 , widget_(widget)
76 , trajectory_slider_panel_(nullptr)
77 , trajectory_slider_dock_panel_(nullptr)
78 , logger_(moveit::getLogger("moveit.ros.trajectory_visualization"))
79{
80 trajectory_topic_property_ = new rviz_common::properties::RosTopicProperty(
81 "Trajectory Topic", "/display_planned_path",
82 rosidl_generator_traits::data_type<moveit_msgs::msg::DisplayTrajectory>(),
83 "The topic on which the moveit_msgs::msg::DisplayTrajectory messages are received", widget,
84 SLOT(changedTrajectoryTopic()), this);
85
87 new rviz_common::properties::BoolProperty("Show Robot Visual", true,
88 "Indicates whether the geometry of the robot as defined for "
89 "visualisation purposes should be displayed",
90 widget, SLOT(changedDisplayPathVisualEnabled()), this);
91
93 new rviz_common::properties::BoolProperty("Show Robot Collision", false,
94 "Indicates whether the geometry of the robot as defined "
95 "for collision detection purposes should be displayed",
96 widget, SLOT(changedDisplayPathCollisionEnabled()), this);
97
98 robot_path_alpha_property_ = new rviz_common::properties::FloatProperty(
99 "Robot Alpha", 0.5f, "Specifies the alpha for the robot links", widget, SLOT(changedRobotPathAlpha()), this);
100 robot_path_alpha_property_->setMin(0.0);
101 robot_path_alpha_property_->setMax(1.0);
102
104 new rviz_common::properties::EditableEnumProperty("State Display Time", "3x",
105 "Replay speed of trajectory. Either as factor of its time"
106 "parameterization or as constant time (s) per waypoint.",
107 widget, SLOT(changedStateDisplayTime()), this);
108 state_display_time_property_->addOptionStd("3x");
109 state_display_time_property_->addOptionStd("1x");
110 state_display_time_property_->addOptionStd("0.5x");
111 state_display_time_property_->addOptionStd("0.05s");
112 state_display_time_property_->addOptionStd("0.1s");
113 state_display_time_property_->addOptionStd("0.5s");
114
115 use_sim_time_property_ = new rviz_common::properties::BoolProperty(
116 "Use Sim Time", false, "Indicates whether simulation time or wall-time is used for state display timing.", widget,
117 nullptr, this);
118
119 loop_display_property_ = new rviz_common::properties::BoolProperty("Loop Animation", false,
120 "Indicates whether the last received path "
121 "is to be animated in a loop",
122 widget, SLOT(changedLoopDisplay()), this);
123
124 trail_display_property_ = new rviz_common::properties::BoolProperty("Show Trail", false, "Show a path trail", widget,
125 SLOT(changedShowTrail()), this);
126
127 trail_step_size_property_ = new rviz_common::properties::IntProperty("Trail Step Size", 1,
128 "Specifies the step size of the samples "
129 "shown in the trajectory trail.",
130 widget, SLOT(changedTrailStepSize()), this);
131 trail_step_size_property_->setMin(1);
132
133 interrupt_display_property_ = new rviz_common::properties::BoolProperty(
134 "Interrupt Display", false,
135 "Immediately show newly planned trajectory, interrupting the currently displayed one.", widget);
136
137 robot_color_property_ = new rviz_common::properties::ColorProperty(
138 "Robot Color", QColor(150, 50, 150), "The color of the animated robot", widget, SLOT(changedRobotColor()), this);
139
140 enable_robot_color_property_ = new rviz_common::properties::BoolProperty(
141 "Color Enabled", false, "Specifies whether robot coloring is enabled", widget, SLOT(enabledRobotColor()), this);
142}
143
154
155void TrajectoryVisualization::onInitialize(const rclcpp::Node::SharedPtr& node, Ogre::SceneNode* scene_node,
156 rviz_common::DisplayContext* context)
157{
158 // Save pointers for later use
159 scene_node_ = scene_node;
160 context_ = context;
161 node_ = node;
162
163 auto ros_node_abstraction = context_->getRosNodeAbstraction().lock();
164 if (!ros_node_abstraction)
165 {
166 RVIZ_COMMON_LOG_WARNING("Unable to lock weak_ptr from DisplayContext in TrajectoryVisualization constructor");
167 return;
168 }
169 trajectory_topic_property_->initialize(ros_node_abstraction);
170
171 // Load trajectory robot
172 display_path_robot_ = std::make_shared<RobotStateVisualization>(scene_node_, context_, "Planned Path", widget_);
174 display_path_robot_->setCollisionVisible(display_path_collision_enabled_property_->getBool());
175 display_path_robot_->setVisible(false);
176
177 rviz_common::WindowManagerInterface* window_context = context_->getWindowManager();
178 if (window_context)
179 {
180 trajectory_slider_panel_ = new TrajectoryPanel(window_context->getParentWindow());
182 window_context->addPane(display_->getName() + " - Trajectory Slider", trajectory_slider_panel_);
183 trajectory_slider_dock_panel_->setIcon(display_->getIcon());
184 connect(trajectory_slider_dock_panel_, SIGNAL(visibilityChanged(bool)), this,
185 SLOT(trajectorySliderPanelVisibilityChange(bool)));
187 }
188
189 trajectory_topic_sub_ = node_->create_subscription<moveit_msgs::msg::DisplayTrajectory>(
190 trajectory_topic_property_->getStdString(), rclcpp::ServicesQoS(),
191 [this](const moveit_msgs::msg::DisplayTrajectory::ConstSharedPtr& msg) { return incomingDisplayTrajectory(msg); });
192}
193
194void TrajectoryVisualization::setName(const QString& name)
195{
197 trajectory_slider_dock_panel_->setWindowTitle(name + " - Slider");
198}
199
200void TrajectoryVisualization::onRobotModelLoaded(const moveit::core::RobotModelConstPtr& robot_model)
201{
202 robot_model_ = robot_model;
203
204 // Error check
205 if (!robot_model_)
206 {
207 RCLCPP_ERROR_STREAM(logger_, "No robot model found");
208 return;
209 }
210
211 // Load robot state
212 robot_state_ = std::make_shared<moveit::core::RobotState>(robot_model_);
213 robot_state_->setToDefaultValues();
214
215 // Load rviz robot
216 display_path_robot_->load(*robot_model_->getURDF());
217 enabledRobotColor(); // force-refresh to account for saved display configuration
218 // perform post-poned subscription to trajectory topic
219 // Check if topic name is empty
220 if (trajectory_topic_sub_->get_topic_name())
221 changedTrajectoryTopic();
222}
223
235
240
241void TrajectoryVisualization::changedLoopDisplay()
242{
246}
247
248void TrajectoryVisualization::changedShowTrail()
249{
251
252 if (!trail_display_property_->getBool())
253 return;
254 robot_trajectory::RobotTrajectoryPtr t = trajectory_message_to_display_;
255 if (!t)
257 if (!t)
258 return;
259
260 int stepsize = trail_step_size_property_->getInt();
261 // always include last trajectory point
262 trajectory_trail_.resize(
263 static_cast<int>(std::ceil((t->getWayPointCount() + stepsize - 1) / static_cast<float>(stepsize))));
264 for (std::size_t i = 0; i < trajectory_trail_.size(); ++i)
265 {
266 int waypoint_i = std::min(i * stepsize, t->getWayPointCount() - 1); // limit to last trajectory point
267 auto r =
268 std::make_unique<RobotStateVisualization>(scene_node_, context_, "Trail Robot " + std::to_string(i), nullptr);
269 r->load(*robot_model_->getURDF());
270 r->setVisualVisible(display_path_visual_enabled_property_->getBool());
271 r->setCollisionVisible(display_path_collision_enabled_property_->getBool());
272 r->setAlpha(robot_path_alpha_property_->getFloat());
273 r->update(t->getWayPointPtr(waypoint_i), default_attached_object_color_);
274 if (enable_robot_color_property_->getBool())
275 setRobotColor(&(r->getRobot()), robot_color_property_->getColor());
276 r->setVisible(display_->isEnabled() && (!animating_path_ || waypoint_i <= current_state_));
277 r->updateAttachedObjectColors(default_attached_object_color_);
278 trajectory_trail_[i] = std::move(r);
279 }
280}
281
282void TrajectoryVisualization::changedTrailStepSize()
283{
284 if (trail_display_property_->getBool())
285 changedShowTrail();
286}
287
288void TrajectoryVisualization::changedRobotPathAlpha()
289{
290 display_path_robot_->setAlpha(robot_path_alpha_property_->getFloat());
291 for (const RobotStateVisualizationUniquePtr& r : trajectory_trail_)
292 r->setAlpha(robot_path_alpha_property_->getFloat());
293}
294
295void TrajectoryVisualization::changedTrajectoryTopic()
296{
297 // post-pone subscription if robot_state_ is not yet defined, i.e. onRobotModelLoaded() not yet called
298 if (!trajectory_topic_property_->getStdString().empty() && robot_state_)
299 {
300 trajectory_topic_sub_ = node_->create_subscription<moveit_msgs::msg::DisplayTrajectory>(
301 trajectory_topic_property_->getStdString(), rclcpp::ServicesQoS(),
302 [this](const moveit_msgs::msg::DisplayTrajectory::ConstSharedPtr& msg) {
303 return incomingDisplayTrajectory(msg);
304 });
305 }
306}
307
308void TrajectoryVisualization::changedDisplayPathVisualEnabled()
309{
310 if (display_->isEnabled())
311 {
314 for (const RobotStateVisualizationUniquePtr& r : trajectory_trail_)
315 r->setVisualVisible(display_path_visual_enabled_property_->getBool());
316 }
317}
318
319void TrajectoryVisualization::changedStateDisplayTime()
320{
321}
322
323void TrajectoryVisualization::changedDisplayPathCollisionEnabled()
324{
325 if (display_->isEnabled())
326 {
327 display_path_robot_->setCollisionVisible(display_path_collision_enabled_property_->getBool());
329 for (const RobotStateVisualizationUniquePtr& r : trajectory_trail_)
330 r->setCollisionVisible(display_path_collision_enabled_property_->getBool());
331 }
332}
333
335{
336 changedRobotPathAlpha(); // set alpha property
337
339 display_path_robot_->setCollisionVisible(display_path_collision_enabled_property_->getBool());
341 for (const RobotStateVisualizationUniquePtr& r : trajectory_trail_)
342 {
343 r->setVisualVisible(display_path_visual_enabled_property_->getBool());
344 r->setCollisionVisible(display_path_collision_enabled_property_->getBool());
345 r->setVisible(true);
346 }
347
348 changedTrajectoryTopic(); // load topic at startup if default used
349}
350
352{
353 display_path_robot_->setVisible(false);
354 for (const RobotStateVisualizationUniquePtr& r : trajectory_trail_)
355 r->setVisible(false);
357 animating_path_ = false;
360}
361
363{
364 // update() starts a new trajectory as soon as it is available
365 // interrupting may cause the newly received trajectory to interrupt
366 // hence, only interrupt when current_state_ already advanced past first
367 if (current_state_ > 0)
368 animating_path_ = false;
369}
370
372{
373 constexpr char default_time_string[] = "3x";
374 constexpr double default_time_value = -3.0;
375
376 std::string tm = state_display_time_property_->getStdString();
377 boost::trim(tm);
378
379 double type;
380
381 if (tm.back() == 'x')
382 {
383 type = -1.0f;
384 }
385 else if (tm.back() == 's')
386 {
387 type = 1.0f;
388 }
389 else
390 {
391 state_display_time_property_->setStdString(default_time_string);
392 return default_time_value;
393 }
394
395 tm.resize(tm.size() - 1);
396 boost::trim_right(tm);
397
398 double value;
399 try
400 {
401 value = std::stof(tm);
402 }
403 catch (const std::invalid_argument& ex)
404 {
405 state_display_time_property_->setStdString(default_time_string);
406 return default_time_value;
407 }
408
409 if (value <= 0)
410 {
411 state_display_time_property_->setStdString(default_time_string);
412 return default_time_value;
413 }
414
415 return type * value;
416}
417
422
423void TrajectoryVisualization::update(std::chrono::nanoseconds wall_dt, std::chrono::nanoseconds sim_dt)
424{
426 {
427 animating_path_ = false;
431 }
432 if (!animating_path_)
433 { // finished last animation?
434 std::scoped_lock lock(update_trajectory_message_);
435
436 // new trajectory available to display?
438 {
439 animating_path_ = true;
441 changedShowTrail();
444 }
446 {
447 if (loop_display_property_->getBool())
448 { // do loop? -> start over too
449 animating_path_ = true;
450 }
451 else if (trajectory_slider_panel_ && trajectory_slider_panel_->isVisible())
452 {
453 if (static_cast<unsigned int>(trajectory_slider_panel_->getSliderPosition()) >=
454 displaying_trajectory_message_->getWayPointCount() - 1)
455 {
456 return; // nothing more to do
457 }
458 else
459 {
460 animating_path_ = true;
461 }
462 }
463 }
465
466 if (animating_path_)
467 {
468 // restart animation
469 current_state_ = -1;
470 }
471 }
472
473 if (animating_path_)
474 {
475 int previous_state = current_state_;
476 int waypoint_count = displaying_trajectory_message_->getWayPointCount();
477 if (use_sim_time_property_->getBool())
478 {
479 current_state_time_ += std::chrono::duration_cast<std::chrono::duration<double>>(sim_dt).count();
480 }
481 else
482 {
483 current_state_time_ += std::chrono::duration_cast<std::chrono::duration<double>>(wall_dt).count();
484 }
485 double tm = getStateDisplayTime();
486
488 {
490 current_state_time_ = displaying_trajectory_message_->getWayPointDurationFromPrevious(current_state_);
491 }
492 else if (current_state_ < 0)
493 { // special case indicating restart of animation
494 current_state_ = 0;
496 }
497 else if (tm < 0.0)
498 {
499 // using realtime factors: skip to next waypoint based on elapsed display time
500 const double rt_factor = -tm; // negative tm is the intended realtime factor
501 while (current_state_ < waypoint_count &&
502 (tm = displaying_trajectory_message_->getWayPointDurationFromPrevious(current_state_ + 1) / rt_factor) <
504 {
506 // if we are stuck in the while loop we should move the robot along the path to keep up
507 if (tm < current_state_time_)
510 }
511 }
512 else if (current_state_time_ > tm)
513 { // fixed display time per state
516 }
517
518 if (current_state_ == previous_state)
519 return;
520
521 if (current_state_ < waypoint_count)
522 {
526 for (std::size_t i = 0; i < trajectory_trail_.size(); ++i)
527 {
528 trajectory_trail_[i]->setVisible(
529 std::min(waypoint_count - 1, static_cast<int>(i) * trail_step_size_property_->getInt()) <= current_state_);
530 }
531 }
532 else
533 {
534 animating_path_ = false; // animation finished
536 { // make sure we move the slider to the end
537 // so the user can re-play
539 }
540 display_path_robot_->update(displaying_trajectory_message_->getWayPointPtr(waypoint_count - 1));
541 display_path_robot_->setVisible(loop_display_property_->getBool());
544 }
545 }
546 // set visibility
547 display_path_robot_->setVisible(display_->isEnabled() && displaying_trajectory_message_ &&
550 display_path_robot_->updateAttachedObjectColors(default_attached_object_color_);
551}
552
553void TrajectoryVisualization::update(double wall_dt, double sim_dt)
554{
555 update(std::chrono::nanoseconds(std::lround(wall_dt)), std::chrono::nanoseconds(std::lround(sim_dt)));
556}
557
558void TrajectoryVisualization::incomingDisplayTrajectory(const moveit_msgs::msg::DisplayTrajectory::ConstSharedPtr& msg)
559{
560 // Error check
561 if (!robot_state_ || !robot_model_)
562 {
563 RCLCPP_ERROR_STREAM(logger_, "No robot state or robot model loaded");
564 return;
565 }
566
567 if (!msg->model_id.empty() && msg->model_id != robot_model_->getName())
568 {
569 RCLCPP_WARN(logger_, "Received a trajectory to display for model '%s' but model '%s' was expected",
570 msg->model_id.c_str(), robot_model_->getName().c_str());
571 }
572
574
575 auto t = std::make_shared<robot_trajectory::RobotTrajectory>(robot_model_, "");
576 try
577 {
578 for (std::size_t i = 0; i < msg->trajectory.size(); ++i)
579 {
580 if (t->empty())
581 {
582 t->setRobotTrajectoryMsg(*robot_state_, msg->trajectory_start, msg->trajectory[i]);
583 }
584 else
585 {
587 tmp.setRobotTrajectoryMsg(t->getLastWayPoint(), msg->trajectory[i]);
588 t->append(tmp, 0.0);
589 }
590 }
591 display_->setStatus(rviz_common::properties::StatusProperty::Ok, "Trajectory", "");
592 }
593 catch (const moveit::Exception& e)
594 {
595 display_->setStatus(rviz_common::properties::StatusProperty::Error, "Trajectory", e.what());
596 return;
597 }
598
599 if (!t->empty())
600 {
601 std::scoped_lock lock(update_trajectory_message_);
603 if (interrupt_display_property_->getBool())
605 }
606}
607
608void TrajectoryVisualization::changedRobotColor()
609{
610 if (enable_robot_color_property_->getBool())
611 setRobotColor(&(display_path_robot_->getRobot()), robot_color_property_->getColor());
612}
613
614void TrajectoryVisualization::enabledRobotColor()
615{
616 if (enable_robot_color_property_->getBool())
617 {
618 setRobotColor(&(display_path_robot_->getRobot()), robot_color_property_->getColor());
619 }
620 else
621 {
622 unsetRobotColor(&(display_path_robot_->getRobot()));
623 }
624}
625
626void TrajectoryVisualization::unsetRobotColor(rviz_default_plugins::robot::Robot* robot)
627{
628 for (auto& link : robot->getLinks())
629 link.second->unsetColor();
630}
631
633{
634 default_attached_object_color_.r = color.redF();
635 default_attached_object_color_.g = color.greenF();
636 default_attached_object_color_.b = color.blueF();
637 default_attached_object_color_.a = color.alphaF();
638
640 {
641 display_path_robot_->setDefaultAttachedObjectColor(default_attached_object_color_);
642 display_path_robot_->updateAttachedObjectColors(default_attached_object_color_);
643 }
644 for (const RobotStateVisualizationUniquePtr& r : trajectory_trail_)
645 r->updateAttachedObjectColors(default_attached_object_color_);
646}
647
648void TrajectoryVisualization::setRobotColor(rviz_default_plugins::robot::Robot* robot, const QColor& color)
649{
650 for (auto& link : robot->getLinks())
651 robot->getLink(link.first)->setColor(color.redF(), color.greenF(), color.blueF());
652}
653
654void TrajectoryVisualization::trajectorySliderPanelVisibilityChange(bool enable)
655{
657 return;
658
659 if (enable)
660 {
662 }
663 else
664 {
666 }
667}
668
670{
671 robot_model_.reset();
672 robot_state_.reset();
673}
674
675} // namespace moveit_rviz_plugin
This may be thrown if unrecoverable errors occur.
rviz_common::properties::BoolProperty * enable_robot_color_property_
void incomingDisplayTrajectory(const moveit_msgs::msg::DisplayTrajectory::ConstSharedPtr &msg)
ROS callback for an incoming path message.
rviz_common::properties::BoolProperty * display_path_visual_enabled_property_
rviz_common::properties::BoolProperty * interrupt_display_property_
robot_trajectory::RobotTrajectoryPtr trajectory_message_to_display_
robot_trajectory::RobotTrajectoryPtr displaying_trajectory_message_
rviz_common::PanelDockWidget * trajectory_slider_dock_panel_
void onInitialize(const rclcpp::Node::SharedPtr &node, Ogre::SceneNode *scene_node, rviz_common::DisplayContext *context)
rviz_common::properties::BoolProperty * trail_display_property_
virtual void update(std::chrono::nanoseconds wall_dt, std::chrono::nanoseconds sim_dt)
rviz_common::properties::BoolProperty * display_path_collision_enabled_property_
rviz_common::properties::RosTopicProperty * trajectory_topic_property_
rviz_common::properties::BoolProperty * use_sim_time_property_
TrajectoryVisualization(rviz_common::properties::Property *widget, rviz_common::Display *display)
Playback a trajectory from a planned path.
rviz_common::properties::BoolProperty * loop_display_property_
rviz_common::properties::ColorProperty * robot_color_property_
void setRobotColor(rviz_default_plugins::robot::Robot *robot, const QColor &color)
rviz_common::properties::EditableEnumProperty * state_display_time_property_
rviz_common::properties::IntProperty * trail_step_size_property_
std::vector< RobotStateVisualizationUniquePtr > trajectory_trail_
void unsetRobotColor(rviz_default_plugins::robot::Robot *robot)
void onRobotModelLoaded(const moveit::core::RobotModelConstPtr &robot_model)
rviz_common::properties::FloatProperty * robot_path_alpha_property_
rclcpp::Subscription< moveit_msgs::msg::DisplayTrajectory >::SharedPtr trajectory_topic_sub_
double getStateDisplayTime()
get time to show each single robot state
Maintain a sequence of waypoints and the time durations between these waypoints.
RobotTrajectory & setRobotTrajectoryMsg(const moveit::core::RobotState &reference_state, const trajectory_msgs::msg::JointTrajectory &trajectory)
Copy the content of the trajectory message into this class. The trajectory message itself is not requ...
RobotTrajectory & append(const RobotTrajectory &source, double dt, size_t start_index=0, size_t end_index=std::numeric_limits< std::size_t >::max())
Add a specified part of a trajectory to the end of the current trajectory. The default (when start_in...
Main namespace for MoveIt.