40#include <geometric_shapes/check_isometry.h>
42#include <tf2_eigen/tf2_eigen.hpp>
45#include <rclcpp/qos.hpp>
52static const auto DEFAULT_CONTROLLER_INFORMATION_VALIDITY_AGE = rclcpp::Duration::from_seconds(1);
53static const double DEFAULT_CONTROLLER_GOAL_DURATION_MARGIN = 0.5;
56static const double DEFAULT_CONTROLLER_GOAL_DURATION_SCALING =
58static const bool DEFAULT_CONTROL_MULTI_DOF_JOINT_VARIABLES =
false;
61 const moveit::core::RobotModelConstPtr& robot_model,
62 const planning_scene_monitor::CurrentStateMonitorPtr& csm)
64 , logger_(
moveit::getLogger(
"moveit.ros.trajectory_execution_manager"))
65 , robot_model_(robot_model)
68 if (!node_->get_parameter(
"moveit_manage_controllers", manage_controllers_))
69 manage_controllers_ =
false;
74 const moveit::core::RobotModelConstPtr& robot_model,
75 const planning_scene_monitor::CurrentStateMonitorPtr& csm,
76 bool manage_controllers)
78 , logger_(
moveit::getLogger(
"moveit.ros.trajectory_execution_manager"))
79 , robot_model_(robot_model)
81 , manage_controllers_(manage_controllers)
89 if (private_executor_)
90 private_executor_->cancel();
91 if (private_executor_thread_.joinable())
92 private_executor_thread_.join();
95void TrajectoryExecutionManager::initialize()
98 execution_complete_ =
true;
99 current_context_ = -1;
101 execution_duration_monitoring_ =
true;
102 execution_velocity_scaling_ = 1.0;
103 allowed_start_tolerance_ = 0.01;
104 allowed_start_tolerance_joints_.clear();
105 wait_for_trajectory_completion_ =
true;
106 control_multi_dof_joint_variables_ = DEFAULT_CONTROL_MULTI_DOF_JOINT_VARIABLES;
108 allowed_execution_duration_scaling_ = DEFAULT_CONTROLLER_GOAL_DURATION_SCALING;
109 allowed_goal_duration_margin_ = DEFAULT_CONTROLLER_GOAL_DURATION_MARGIN;
114 controller_manager_loader_ =
115 std::make_unique<pluginlib::ClassLoader<moveit_controller_manager::MoveItControllerManager>>(
116 "moveit_core",
"moveit_controller_manager::MoveItControllerManager");
118 catch (pluginlib::PluginlibException& ex)
120 RCLCPP_FATAL_STREAM(logger_,
"Exception while creating controller manager plugin loader: " << ex.what());
124 if (controller_manager_loader_)
126 std::string controller;
128 if (!node_->get_parameter(
"moveit_controller_manager", controller))
130 const std::vector<std::string>& classes = controller_manager_loader_->getDeclaredClasses();
131 if (classes.size() == 1)
133 controller = classes[0];
135 "Parameter '~moveit_controller_manager' is not specified but only one "
136 "matching plugin was found: '%s'. Using that one.",
141 RCLCPP_FATAL(logger_,
"Parameter '~moveit_controller_manager' not specified. This is needed to "
142 "identify the plugin to use for interacting with controllers. No paths can "
149 if (controller ==
"moveit_ros_control_interface/MoveItControllerManager")
151 RCLCPP_WARN(logger_,
"moveit_ros_control_interface/MoveItControllerManager is deprecated. Replace with "
152 "`moveit_ros_control_interface/Ros2ControlManager.`");
154 if (controller ==
"moveit_ros_control_interface/MoveItMultiControllerManager")
156 RCLCPP_WARN(logger_,
"moveit_ros_control_interface/MoveItMultiControllerManager is deprecated. Replace with "
157 "`moveit_ros_control_interface/Ros2ControlMultiManager.`");
160 if (!controller.empty())
167 rclcpp::NodeOptions opt;
168 opt.allow_undeclared_parameters(
true);
169 opt.automatically_declare_parameters_from_overrides(
true);
170 controller_mgr_node_ =
171 std::make_shared<rclcpp::Node>(
"moveit_simple_controller_manager", node_->get_namespace(), opt);
173 auto all_params = node_->get_node_parameters_interface()->get_parameter_overrides();
174 for (
const auto& param : all_params)
175 controller_mgr_node_->set_parameter(
rclcpp::Parameter(param.first, param.second));
177 controller_manager_ = controller_manager_loader_->createUniqueInstance(controller);
178 controller_manager_->initialize(controller_mgr_node_);
179 private_executor_ = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
180 private_executor_->add_node(controller_mgr_node_);
183 private_executor_thread_ = std::thread([
this]() { private_executor_->spin(); });
185 catch (pluginlib::PluginlibException& ex)
187 RCLCPP_FATAL_STREAM(logger_,
"Exception while loading controller manager '" << controller <<
"': " << ex.what());
193 reloadControllerInformation();
196 loadControllerParams();
201 auto callback_group = node_->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
202 auto options = rclcpp::SubscriptionOptions();
203 options.callback_group = callback_group;
204 event_topic_subscriber_ = node_->create_subscription<std_msgs::msg::String>(
206 [
this](
const std_msgs::msg::String::ConstSharedPtr& event) {
return receiveEvent(event); },
options);
208 controller_mgr_node_->get_parameter(
"trajectory_execution.execution_duration_monitoring",
209 execution_duration_monitoring_);
210 controller_mgr_node_->get_parameter(
"trajectory_execution.allowed_execution_duration_scaling",
211 allowed_execution_duration_scaling_);
212 controller_mgr_node_->get_parameter(
"trajectory_execution.allowed_goal_duration_margin",
213 allowed_goal_duration_margin_);
214 controller_mgr_node_->get_parameter(
"trajectory_execution.allowed_start_tolerance", allowed_start_tolerance_);
215 controller_mgr_node_->get_parameter(
"trajectory_execution.control_multi_dof_joint_variables",
216 control_multi_dof_joint_variables_);
218 initializeAllowedStartToleranceJoints();
220 if (manage_controllers_)
222 RCLCPP_INFO(logger_,
"Trajectory execution is managing controllers");
226 RCLCPP_INFO(logger_,
"Trajectory execution is not managing controllers");
229 auto controller_mgr_parameter_set_callback = [
this](
const std::vector<rclcpp::Parameter>& parameters) {
230 auto result = rcl_interfaces::msg::SetParametersResult();
231 result.successful =
true;
232 for (
const auto& parameter : parameters)
234 const std::string&
name = parameter.get_name();
235 if (name ==
"trajectory_execution.execution_duration_monitoring")
239 else if (name ==
"trajectory_execution.allowed_execution_duration_scaling")
243 else if (name ==
"trajectory_execution.allowed_goal_duration_margin")
247 else if (name ==
"trajectory_execution.execution_velocity_scaling")
251 else if (name ==
"trajectory_execution.allowed_start_tolerance")
255 else if (
name.find(
"trajectory_execution.allowed_start_tolerance_joints.") == 0)
257 setAllowedStartToleranceJoint(name, parameter.as_double());
259 else if (name ==
"trajectory_execution.wait_for_trajectory_completion")
265 result.successful =
false;
270 callback_handler_ = controller_mgr_node_->add_on_set_parameters_callback(controller_mgr_parameter_set_callback);
275 execution_duration_monitoring_ = flag;
280 return execution_duration_monitoring_;
285 allowed_execution_duration_scaling_ = scaling;
290 return allowed_execution_duration_scaling_;
295 allowed_goal_duration_margin_ = margin;
300 return allowed_goal_duration_margin_;
305 execution_velocity_scaling_ = scaling;
310 return execution_velocity_scaling_;
315 allowed_start_tolerance_ = tolerance;
320 return allowed_start_tolerance_;
325 wait_for_trajectory_completion_ = flag;
330 return wait_for_trajectory_completion_;
335 return manage_controllers_;
340 return controller_manager_;
351 RCLCPP_WARN_STREAM(logger_,
"Unknown event type: '" << event <<
'\'');
355void TrajectoryExecutionManager::receiveEvent(
const std_msgs::msg::String::ConstSharedPtr& event)
357 RCLCPP_INFO_STREAM(logger_,
"Received event '" << event->data <<
'\'');
363 if (controller.empty())
365 return push(trajectory, std::vector<std::string>());
369 return push(trajectory, std::vector<std::string>(1, controller));
374 const std::string& controller)
376 if (controller.empty())
378 return push(trajectory, std::vector<std::string>());
382 return push(trajectory, std::vector<std::string>(1, controller));
387 const std::vector<std::string>& controllers)
389 moveit_msgs::msg::RobotTrajectory traj;
390 traj.joint_trajectory = trajectory;
391 return push(traj, controllers);
395 const std::vector<std::string>& controllers)
397 if (!execution_complete_)
399 RCLCPP_ERROR(logger_,
"Cannot push a new trajectory while another is being executed");
404 std::optional<moveit_msgs::msg::RobotTrajectory> replaced_trajectory;
405 if (control_multi_dof_joint_variables_ && !trajectory.multi_dof_joint_trajectory.points.empty())
416 std::vector<std::string> all_trajectory_joints = trajectory.joint_trajectory.joint_names;
417 for (
const auto& mdof_joint : trajectory.multi_dof_joint_trajectory.joint_names)
419 all_trajectory_joints.push_back(mdof_joint);
423 const auto joint_trajectory =
428 if (!joint_trajectory.has_value())
430 RCLCPP_ERROR(logger_,
"Failed to convert multi-DOF trajectory to joint trajectory, aborting execution!");
435 RCLCPP_DEBUG(logger_,
"Successfully converted multi-DOF trajectory to joint trajectory for execution.");
436 replaced_trajectory = moveit_msgs::msg::RobotTrajectory();
437 replaced_trajectory->joint_trajectory = joint_trajectory.value();
441 if (configure(*context, replaced_trajectory.value_or(trajectory), controllers))
445 std::stringstream ss;
446 ss <<
"Pushed trajectory for execution using controllers [ ";
447 for (
const std::string& controller : context->
controllers_)
448 ss << controller <<
' ';
453 RCLCPP_INFO_STREAM(logger_, ss.str());
455 trajectories_.push_back(context);
467void TrajectoryExecutionManager::reloadControllerInformation()
469 known_controllers_.clear();
470 if (controller_manager_)
472 std::vector<std::string> names;
473 controller_manager_->getControllersList(names);
474 for (
const std::string& name : names)
476 std::vector<std::string> joints;
477 controller_manager_->getControllerJoints(name, joints);
478 ControllerInformation ci;
480 ci.joints_.insert(joints.begin(), joints.end());
481 known_controllers_[ci.name_] = ci;
485 controller_manager_->getActiveControllers(names);
486 for (
const auto& active_name : names)
488 auto found_it = std::find_if(known_controllers_.begin(), known_controllers_.end(),
489 [&](
const auto& known_controller) { return known_controller.first == active_name; });
490 if (found_it != known_controllers_.end())
492 found_it->second.state_.active_ =
true;
496 for (std::map<std::string, ControllerInformation>::iterator it = known_controllers_.begin();
497 it != known_controllers_.end(); ++it)
499 for (std::map<std::string, ControllerInformation>::iterator jt = known_controllers_.begin();
500 jt != known_controllers_.end(); ++jt)
504 std::vector<std::string> intersect;
505 std::set_intersection(it->second.joints_.begin(), it->second.joints_.end(), jt->second.joints_.begin(),
506 jt->second.joints_.end(), std::back_inserter(intersect));
507 if (!intersect.empty())
509 it->second.overlapping_controllers_.insert(jt->first);
510 jt->second.overlapping_controllers_.insert(it->first);
518 RCLCPP_ERROR(logger_,
"Failed to reload controllers: `controller_manager_` does not exist.");
522void TrajectoryExecutionManager::updateControllerState(
const std::string& controller,
const rclcpp::Duration& age)
524 std::map<std::string, ControllerInformation>::iterator it = known_controllers_.find(controller);
525 if (it != known_controllers_.end())
527 updateControllerState(it->second, age);
531 RCLCPP_ERROR(logger_,
"Controller '%s' is not known.", controller.c_str());
535void TrajectoryExecutionManager::updateControllerState(ControllerInformation& ci,
const rclcpp::Duration& age)
537 if (node_->now() - ci.last_update_ >= age)
539 if (controller_manager_)
542 RCLCPP_INFO(logger_,
"Updating information for controller '%s'.", ci.name_.c_str());
543 ci.state_ = controller_manager_->getControllerState(ci.name_);
544 ci.last_update_ = node_->now();
548 RCLCPP_INFO(logger_,
"Information for controller '%s' is assumed to be up to date.", ci.name_.c_str());
551void TrajectoryExecutionManager::updateControllersState(
const rclcpp::Duration& age)
553 for (std::pair<const std::string, ControllerInformation>& known_controller : known_controllers_)
554 updateControllerState(known_controller.second, age);
557bool TrajectoryExecutionManager::checkControllerCombination(std::vector<std::string>& selected,
558 const std::set<std::string>& actuated_joints)
560 std::set<std::string> combined_joints;
561 for (
const std::string& controller : selected)
563 const ControllerInformation& ci = known_controllers_[controller];
564 combined_joints.insert(ci.joints_.begin(), ci.joints_.end());
569 std::stringstream ss, saj, sac;
570 for (
const std::string& controller : selected)
571 ss << controller <<
' ';
572 for (
const std::string& actuated_joint : actuated_joints)
573 saj << actuated_joint <<
' ';
574 for (
const std::string& combined_joint : combined_joints)
575 sac << combined_joint <<
' ';
576 RCLCPP_INFO(logger_,
"Checking if controllers [ %s] operating on joints [ %s] cover joints [ %s]", ss.str().c_str(),
577 sac.str().c_str(), saj.str().c_str());
580 return std::includes(combined_joints.begin(), combined_joints.end(), actuated_joints.begin(), actuated_joints.end());
583void TrajectoryExecutionManager::generateControllerCombination(std::size_t start_index, std::size_t controller_count,
584 const std::vector<std::string>& available_controllers,
585 std::vector<std::string>& selected_controllers,
587 const std::set<std::string>& actuated_joints)
589 if (selected_controllers.size() == controller_count)
591 if (checkControllerCombination(selected_controllers, actuated_joints))
596 for (std::size_t i = start_index; i < available_controllers.size(); ++i)
598 bool overlap =
false;
599 const ControllerInformation& ci = known_controllers_[available_controllers[i]];
600 for (std::size_t j = 0; j < selected_controllers.size() && !overlap; ++j)
602 if (ci.overlapping_controllers_.find(selected_controllers[j]) != ci.overlapping_controllers_.end())
607 selected_controllers.push_back(available_controllers[i]);
608 generateControllerCombination(i + 1, controller_count, available_controllers, selected_controllers,
610 selected_controllers.pop_back();
616struct OrderPotentialControllerCombination
618 bool operator()(
const std::size_t a,
const std::size_t b)
const
621 if (nrdefault[a] > nrdefault[b])
623 if (nrdefault[a] < nrdefault[b])
627 if (nrjoints[a] < nrjoints[b])
629 if (nrjoints[a] > nrjoints[b])
633 if (nractive[a] > nractive[b])
635 if (nractive[a] < nractive[b])
648bool TrajectoryExecutionManager::findControllers(
const std::set<std::string>& actuated_joints,
649 std::size_t controller_count,
650 const std::vector<std::string>& available_controllers,
651 std::vector<std::string>& selected_controllers)
654 std::vector<std::string> work_area;
655 OrderPotentialControllerCombination order;
656 std::vector<std::vector<std::string>>&
selected_options = order.selected_options;
657 generateControllerCombination(0, controller_count, available_controllers, work_area,
selected_options,
662 std::stringstream saj;
663 std::stringstream sac;
664 for (
const std::string& available_controller : available_controllers)
665 sac << available_controller <<
' ';
666 for (
const std::string& actuated_joint : actuated_joints)
667 saj << actuated_joint <<
' ';
668 RCLCPP_INFO(logger_,
"Looking for %zu controllers among [ %s] that cover joints [ %s]. Found %zd options.",
669 controller_count, sac.str().c_str(), saj.str().c_str(),
selected_options.size());
695 updateControllerState(
selected_options[i][k], DEFAULT_CONTROLLER_INFORMATION_VALIDITY_AGE);
696 const ControllerInformation& ci = known_controllers_[
selected_options[i][k]];
698 if (ci.state_.default_)
699 order.nrdefault[i]++;
700 if (ci.state_.active_)
702 order.nrjoints[i] += ci.joints_.size();
712 std::sort(bijection.begin(), bijection.end(), order);
716 if (!manage_controllers_)
741 for (
const std::string& controller : controllers)
743 updateControllerState(controller, DEFAULT_CONTROLLER_INFORMATION_VALIDITY_AGE);
744 std::map<std::string, ControllerInformation>::iterator it = known_controllers_.find(controller);
745 if (it == known_controllers_.end() || !it->second.state_.active_)
751bool TrajectoryExecutionManager::selectControllers(
const std::set<std::string>& actuated_joints,
752 const std::vector<std::string>& available_controllers,
753 std::vector<std::string>& selected_controllers)
755 for (std::size_t i = 1; i <= available_controllers.size(); ++i)
757 if (findControllers(actuated_joints, i, available_controllers, selected_controllers))
762 std::vector<std::string> other_option;
763 for (std::size_t j = i + 1; j <= available_controllers.size(); ++j)
765 if (findControllers(actuated_joints, j, available_controllers, other_option))
769 selected_controllers = other_option;
781bool TrajectoryExecutionManager::distributeTrajectory(
const moveit_msgs::msg::RobotTrajectory& trajectory,
782 const std::vector<std::string>& controllers,
783 std::vector<moveit_msgs::msg::RobotTrajectory>& parts)
786 parts.resize(controllers.size());
788 std::set<std::string> actuated_joints_mdof;
789 actuated_joints_mdof.insert(trajectory.multi_dof_joint_trajectory.joint_names.begin(),
790 trajectory.multi_dof_joint_trajectory.joint_names.end());
791 std::set<std::string> actuated_joints_single;
792 for (
const std::string& joint_name : trajectory.joint_trajectory.joint_names)
799 actuated_joints_single.insert(joint_name);
803 for (std::size_t i = 0; i < controllers.size(); ++i)
805 std::map<std::string, ControllerInformation>::iterator it = known_controllers_.find(controllers[i]);
806 if (it == known_controllers_.end())
808 RCLCPP_ERROR_STREAM(logger_,
"Controller " << controllers[i] <<
" not found.");
811 std::vector<std::string> intersect_mdof;
812 std::set_intersection(it->second.joints_.begin(), it->second.joints_.end(), actuated_joints_mdof.begin(),
813 actuated_joints_mdof.end(), std::back_inserter(intersect_mdof));
814 std::vector<std::string> intersect_single;
815 std::set_intersection(it->second.joints_.begin(), it->second.joints_.end(), actuated_joints_single.begin(),
816 actuated_joints_single.end(), std::back_inserter(intersect_single));
817 if (intersect_mdof.empty() && intersect_single.empty())
818 RCLCPP_WARN_STREAM(logger_,
"No joints to be distributed for controller " << controllers[i]);
820 if (!intersect_mdof.empty())
822 std::vector<std::string>& jnames = parts[i].multi_dof_joint_trajectory.joint_names;
823 jnames.insert(jnames.end(), intersect_mdof.begin(), intersect_mdof.end());
824 std::map<std::string, std::size_t> index;
825 for (std::size_t j = 0; j < trajectory.multi_dof_joint_trajectory.joint_names.size(); ++j)
826 index[trajectory.multi_dof_joint_trajectory.joint_names[j]] = j;
827 std::vector<std::size_t> bijection(jnames.size());
828 for (std::size_t j = 0; j < jnames.size(); ++j)
829 bijection[j] = index[jnames[j]];
831 parts[i].multi_dof_joint_trajectory.header.frame_id = trajectory.multi_dof_joint_trajectory.header.frame_id;
832 parts[i].multi_dof_joint_trajectory.points.resize(trajectory.multi_dof_joint_trajectory.points.size());
833 for (std::size_t j = 0; j < trajectory.multi_dof_joint_trajectory.points.size(); ++j)
835 parts[i].multi_dof_joint_trajectory.points[j].time_from_start =
836 trajectory.multi_dof_joint_trajectory.points[j].time_from_start;
837 parts[i].multi_dof_joint_trajectory.points[j].transforms.resize(bijection.size());
838 for (std::size_t k = 0; k < bijection.size(); ++k)
840 parts[i].multi_dof_joint_trajectory.points[j].transforms[k] =
841 trajectory.multi_dof_joint_trajectory.points[j].transforms[bijection[k]];
843 if (!trajectory.multi_dof_joint_trajectory.points[j].velocities.empty())
845 parts[i].multi_dof_joint_trajectory.points[j].velocities.resize(bijection.size());
847 parts[i].multi_dof_joint_trajectory.points[j].velocities[0].linear.x =
848 trajectory.multi_dof_joint_trajectory.points[j].velocities[0].linear.x * execution_velocity_scaling_;
850 parts[i].multi_dof_joint_trajectory.points[j].velocities[0].linear.y =
851 trajectory.multi_dof_joint_trajectory.points[j].velocities[0].linear.y * execution_velocity_scaling_;
853 parts[i].multi_dof_joint_trajectory.points[j].velocities[0].linear.z =
854 trajectory.multi_dof_joint_trajectory.points[j].velocities[0].linear.z * execution_velocity_scaling_;
856 parts[i].multi_dof_joint_trajectory.points[j].velocities[0].angular.x =
857 trajectory.multi_dof_joint_trajectory.points[j].velocities[0].angular.x * execution_velocity_scaling_;
859 parts[i].multi_dof_joint_trajectory.points[j].velocities[0].angular.y =
860 trajectory.multi_dof_joint_trajectory.points[j].velocities[0].angular.y * execution_velocity_scaling_;
862 parts[i].multi_dof_joint_trajectory.points[j].velocities[0].angular.z =
863 trajectory.multi_dof_joint_trajectory.points[j].velocities[0].angular.z * execution_velocity_scaling_;
868 if (!intersect_single.empty())
870 std::vector<std::string>& jnames = parts[i].joint_trajectory.joint_names;
871 jnames.insert(jnames.end(), intersect_single.begin(), intersect_single.end());
872 parts[i].joint_trajectory.header = trajectory.joint_trajectory.header;
873 std::map<std::string, std::size_t> index;
874 for (std::size_t j = 0; j < trajectory.joint_trajectory.joint_names.size(); ++j)
875 index[trajectory.joint_trajectory.joint_names[j]] = j;
876 std::vector<std::size_t> bijection(jnames.size());
877 for (std::size_t j = 0; j < jnames.size(); ++j)
878 bijection[j] = index[jnames[j]];
879 parts[i].joint_trajectory.points.resize(trajectory.joint_trajectory.points.size());
880 for (std::size_t j = 0; j < trajectory.joint_trajectory.points.size(); ++j)
882 parts[i].joint_trajectory.points[j].time_from_start = trajectory.joint_trajectory.points[j].time_from_start;
883 if (!trajectory.joint_trajectory.points[j].positions.empty())
885 parts[i].joint_trajectory.points[j].positions.resize(bijection.size());
886 for (std::size_t k = 0; k < bijection.size(); ++k)
888 parts[i].joint_trajectory.points[j].positions[k] =
889 trajectory.joint_trajectory.points[j].positions[bijection[k]];
892 if (!trajectory.joint_trajectory.points[j].velocities.empty())
894 parts[i].joint_trajectory.points[j].velocities.resize(bijection.size());
895 for (std::size_t k = 0; k < bijection.size(); ++k)
897 parts[i].joint_trajectory.points[j].velocities[k] =
898 trajectory.joint_trajectory.points[j].velocities[bijection[k]] * execution_velocity_scaling_;
901 if (!trajectory.joint_trajectory.points[j].accelerations.empty())
903 parts[i].joint_trajectory.points[j].accelerations.resize(bijection.size());
904 for (std::size_t k = 0; k < bijection.size(); ++k)
906 parts[i].joint_trajectory.points[j].accelerations[k] =
907 trajectory.joint_trajectory.points[j].accelerations[bijection[k]];
910 if (!trajectory.joint_trajectory.points[j].effort.empty())
912 parts[i].joint_trajectory.points[j].effort.resize(bijection.size());
913 for (std::size_t k = 0; k < bijection.size(); ++k)
915 parts[i].joint_trajectory.points[j].effort[k] =
916 trajectory.joint_trajectory.points[j].effort[bijection[k]];
926bool TrajectoryExecutionManager::validate(
const TrajectoryExecutionContext& context)
const
928 if (allowed_start_tolerance_ == 0 && allowed_start_tolerance_joints_.empty())
931 if (allowed_start_tolerance_joints_.empty())
933 RCLCPP_INFO_STREAM(logger_,
"Validating trajectory with allowed_start_tolerance " << allowed_start_tolerance_);
937 std::ostringstream ss;
938 for (
const auto& [joint_name, joint_start_tolerance] : allowed_start_tolerance_joints_)
942 ss << joint_name <<
": " << joint_start_tolerance;
944 RCLCPP_INFO_STREAM(logger_,
"Validating trajectory with allowed_start_tolerance "
945 << allowed_start_tolerance_ <<
" and allowed_start_tolerance_joints {" << ss.str()
949 moveit::core::RobotStatePtr current_state;
950 if (!csm_->waitForCurrentState(node_->now()) || !(current_state = csm_->getCurrentState()))
952 RCLCPP_WARN(logger_,
"Failed to validate trajectory: couldn't receive full current joint state within 1s");
956 for (
const auto& trajectory : context.trajectory_parts_)
958 if (!trajectory.joint_trajectory.points.empty())
961 const std::vector<double>& positions = trajectory.joint_trajectory.points.front().positions;
962 const std::vector<std::string>& joint_names = trajectory.joint_trajectory.joint_names;
963 if (positions.size() != joint_names.size())
965 RCLCPP_ERROR(logger_,
"Wrong trajectory: #joints: %zu != #positions: %zu", joint_names.size(), positions.size());
969 std::set<const moveit::core::JointModel*> joints;
970 for (
const auto& joint_name : joint_names)
975 RCLCPP_ERROR_STREAM(logger_,
"Unknown joint in trajectory: " << joint_name);
986 reference_state.setVariablePositions(joint_names, positions);
988 for (
const auto joint : joints)
990 const double joint_start_tolerance = getAllowedStartToleranceJoint(joint->getName());
991 reference_state.enforcePositionBounds(joint);
992 current_state->enforcePositionBounds(joint);
993 if (joint_start_tolerance != 0 && reference_state.distance(*current_state, joint) > joint_start_tolerance)
995 RCLCPP_ERROR(logger_,
996 "Invalid Trajectory: start point deviates from current robot state more than %g at joint '%s'."
997 "\nEnable DEBUG for detailed state info.",
998 joint_start_tolerance, joint->getName().c_str());
999 RCLCPP_DEBUG(logger_,
"| Joint | Expected | Current |");
1000 for (
const auto& joint_name : joint_names)
1002 RCLCPP_DEBUG(logger_,
"| %s | %g | %g |", joint_name.c_str(),
1003 reference_state.getVariablePosition(joint_name),
1004 current_state->getVariablePosition(joint_name));
1011 if (!trajectory.multi_dof_joint_trajectory.points.empty())
1014 const std::vector<geometry_msgs::msg::Transform>& transforms =
1015 trajectory.multi_dof_joint_trajectory.points.front().transforms;
1016 const std::vector<std::string>& joint_names = trajectory.multi_dof_joint_trajectory.joint_names;
1017 if (transforms.size() != joint_names.size())
1019 RCLCPP_ERROR(logger_,
"Wrong trajectory: #joints: %zu != #transforms: %zu", joint_names.size(),
1024 for (std::size_t i = 0, end = joint_names.size(); i < end; ++i)
1029 RCLCPP_ERROR_STREAM(logger_,
"Unknown joint in trajectory: " << joint_names[i]);
1035 Eigen::Isometry3d cur_transform, start_transform;
1038 start_transform = tf2::transformToEigen(transforms[i]);
1039 ASSERT_ISOMETRY(start_transform)
1040 Eigen::Vector3d offset = cur_transform.translation() - start_transform.translation();
1041 Eigen::AngleAxisd rotation;
1042 rotation.fromRotationMatrix(cur_transform.linear().transpose() * start_transform.linear());
1043 const double joint_start_tolerance = getAllowedStartToleranceJoint(joint_names[i]);
1044 if (joint_start_tolerance != 0 &&
1045 ((offset.array() > joint_start_tolerance).any() || rotation.angle() > joint_start_tolerance))
1047 RCLCPP_ERROR_STREAM(logger_,
"\nInvalid Trajectory: start point deviates from current robot state more than "
1048 << joint_start_tolerance <<
"\nmulti-dof joint '" << joint_names[i]
1049 <<
"': pos delta: " << offset.transpose()
1050 <<
" rot delta: " << rotation.angle());
1059bool TrajectoryExecutionManager::configure(TrajectoryExecutionContext& context,
1060 const moveit_msgs::msg::RobotTrajectory& trajectory,
1061 const std::vector<std::string>& controllers)
1063 if (trajectory.multi_dof_joint_trajectory.points.empty() && trajectory.joint_trajectory.points.empty())
1069 reloadControllerInformation();
1070 std::set<std::string> actuated_joints;
1072 auto is_actuated = [
this](
const std::string& joint_name) ->
bool {
1076 for (
const std::string& joint_name : trajectory.multi_dof_joint_trajectory.joint_names)
1078 if (is_actuated(joint_name))
1079 actuated_joints.insert(joint_name);
1081 for (
const std::string& joint_name : trajectory.joint_trajectory.joint_names)
1083 if (is_actuated(joint_name))
1084 actuated_joints.insert(joint_name);
1087 if (actuated_joints.empty())
1089 RCLCPP_WARN(logger_,
"The trajectory to execute specifies no joints");
1093 if (controllers.empty())
1096 bool reloaded =
false;
1100 std::vector<std::string> all_controller_names;
1101 for (std::map<std::string, ControllerInformation>::const_iterator it = known_controllers_.begin();
1102 it != known_controllers_.end(); ++it)
1103 all_controller_names.push_back(it->first);
1104 if (selectControllers(actuated_joints, all_controller_names, context.controllers_))
1106 if (distributeTrajectory(trajectory, context.controllers_, context.trajectory_parts_))
1114 reloadControllerInformation();
1125 bool reloaded =
false;
1126 for (
const std::string& controller : controllers)
1128 if (known_controllers_.find(controller) == known_controllers_.end())
1130 reloadControllerInformation();
1137 for (
const std::string& controller : controllers)
1139 if (known_controllers_.find(controller) == known_controllers_.end())
1141 std::stringstream stream;
1142 for (
const auto& controller : known_controllers_)
1144 stream <<
" `" << controller.first <<
'`';
1146 RCLCPP_ERROR_STREAM(logger_,
1147 "Controller " << controller <<
" is not known. Known controllers: " << stream.str());
1152 if (selectControllers(actuated_joints, controllers, context.controllers_))
1154 if (distributeTrajectory(trajectory, context.controllers_, context.trajectory_parts_))
1158 std::stringstream ss;
1159 for (
const std::string& actuated_joint : actuated_joints)
1160 ss << actuated_joint <<
' ';
1161 RCLCPP_ERROR(logger_,
"Unable to identify any set of controllers that can actuate the specified joints: [ %s]",
1164 std::stringstream ss2;
1165 std::map<std::string, ControllerInformation>::const_iterator mi;
1166 for (mi = known_controllers_.begin(); mi != known_controllers_.end(); ++mi)
1168 ss2 <<
"controller '" << mi->second.name_ <<
"' controls joints:\n";
1170 std::set<std::string>::const_iterator ji;
1171 for (ji = mi->second.joints_.begin(); ji != mi->second.joints_.end(); ++ji)
1173 ss2 <<
" " << *ji <<
'\n';
1176 RCLCPP_ERROR(logger_,
"Known controllers and their joints:\n%s", ss2.str().c_str());
1178 if (!trajectory.multi_dof_joint_trajectory.joint_names.empty())
1180 RCLCPP_WARN(logger_,
"Hint: You can control multi-dof waypoints as joint trajectory by setting "
1181 "`trajectory_execution.control_multi_dof_joint_variables=True`");
1193void TrajectoryExecutionManager::stopExecutionInternal()
1196 for (moveit_controller_manager::MoveItControllerHandlePtr& active_handle : active_handles_)
1200 active_handle->cancelExecution();
1202 catch (std::exception& ex)
1204 RCLCPP_ERROR(logger_,
"Caught %s when canceling execution.", ex.what());
1211 if (!execution_complete_)
1213 execution_state_mutex_.lock();
1214 if (!execution_complete_)
1220 execution_complete_ =
true;
1221 stopExecutionInternal();
1225 execution_state_mutex_.unlock();
1226 RCLCPP_INFO(logger_,
"Stopped trajectory execution.");
1229 std::scoped_lock lock(execution_thread_mutex_);
1230 if (execution_thread_)
1232 execution_thread_->join();
1233 execution_thread_.reset();
1240 execution_state_mutex_.unlock();
1242 else if (execution_thread_)
1245 std::scoped_lock lock(execution_thread_mutex_);
1246 if (execution_thread_)
1248 execution_thread_->join();
1249 execution_thread_.reset();
1264 if (trajectories_.empty())
1270 if (!trajectories_.empty() && !validate(*trajectories_.front()))
1276 callback(last_execution_status_);
1281 execution_complete_ =
false;
1282 execution_thread_ = std::make_unique<std::thread>(&TrajectoryExecutionManager::executeThread,
this, callback,
1283 part_callback, auto_clear);
1289 std::unique_lock<std::mutex> ulock(execution_state_mutex_);
1290 while (!execution_complete_)
1291 execution_complete_condition_.wait(ulock);
1297 return last_execution_status_;
1300void TrajectoryExecutionManager::clear()
1302 if (execution_complete_)
1304 std::scoped_lock slock(execution_state_mutex_);
1305 for (TrajectoryExecutionContext* trajectory : trajectories_)
1307 trajectories_.clear();
1310 RCLCPP_FATAL(logger_,
"Expecting execution_complete_ to be true!");
1313void TrajectoryExecutionManager::executeThread(
const ExecutionCompleteCallback& callback,
1314 const PathSegmentCompleteCallback& part_callback,
bool auto_clear)
1317 if (execution_complete_)
1321 callback(last_execution_status_);
1325 RCLCPP_INFO(logger_,
"Starting trajectory execution ...");
1332 for (; i < trajectories_.size(); ++i)
1334 bool epart = executePart(i);
1335 if (epart && part_callback)
1337 if (!epart || execution_complete_)
1347 std::scoped_lock slock(execution_state_mutex_);
1348 if (!execution_complete_)
1350 waitForRobotToStop(*trajectories_[i - 1]);
1354 RCLCPP_INFO(logger_,
"Completed trajectory execution with status %s ...", last_execution_status_.
asString().c_str());
1357 execution_state_mutex_.lock();
1358 execution_complete_ =
true;
1359 execution_state_mutex_.unlock();
1360 execution_complete_condition_.notify_all();
1368 callback(last_execution_status_);
1371bool TrajectoryExecutionManager::executePart(std::size_t part_index)
1373 TrajectoryExecutionContext& context = *trajectories_[part_index];
1379 if (execution_complete_)
1382 std::vector<moveit_controller_manager::MoveItControllerHandlePtr> handles;
1384 std::scoped_lock slock(execution_state_mutex_);
1385 if (!execution_complete_)
1388 time_index_mutex_.lock();
1389 current_context_ = part_index;
1390 time_index_mutex_.unlock();
1391 active_handles_.resize(context.controllers_.size());
1392 for (std::size_t i = 0; i < context.controllers_.size(); ++i)
1394 moveit_controller_manager::MoveItControllerHandlePtr h;
1397 h = controller_manager_->getControllerHandle(context.controllers_[i]);
1399 catch (std::exception& ex)
1401 RCLCPP_ERROR(logger_,
"Caught %s when retrieving controller handle", ex.what());
1405 active_handles_.clear();
1406 current_context_ = -1;
1408 RCLCPP_ERROR(logger_,
"No controller handle for controller '%s'. Aborting.",
1409 context.controllers_[i].c_str());
1412 active_handles_[i] = h;
1414 handles = active_handles_;
1415 for (std::size_t i = 0; i < context.trajectory_parts_.size(); ++i)
1420 ok = active_handles_[i]->sendTrajectory(context.trajectory_parts_[i]);
1422 catch (std::exception& ex)
1424 RCLCPP_ERROR(logger_,
"Caught %s when sending trajectory to controller", ex.what());
1428 for (std::size_t j = 0; j < i; ++j)
1432 active_handles_[j]->cancelExecution();
1434 catch (std::exception& ex)
1436 RCLCPP_ERROR(logger_,
"Caught %s when canceling execution", ex.what());
1439 RCLCPP_ERROR(logger_,
"Failed to send trajectory part %zu of %zu to controller %s", i + 1,
1440 context.trajectory_parts_.size(), active_handles_[i]->getName().c_str());
1442 RCLCPP_ERROR(logger_,
"Cancelling previously sent trajectory parts");
1443 active_handles_.clear();
1444 current_context_ = -1;
1453 rclcpp::Time current_time = node_->now();
1454 auto expected_trajectory_duration = rclcpp::Duration::from_seconds(0);
1455 int longest_part = -1;
1456 for (std::size_t i = 0; i < context.trajectory_parts_.size(); ++i)
1458 auto d = rclcpp::Duration::from_seconds(0);
1459 if (!(context.trajectory_parts_[i].joint_trajectory.points.empty() &&
1460 context.trajectory_parts_[i].multi_dof_joint_trajectory.points.empty()))
1462 if (rclcpp::Time(context.trajectory_parts_[i].joint_trajectory.header.stamp) > current_time)
1463 d = rclcpp::Time(context.trajectory_parts_[i].joint_trajectory.header.stamp) - current_time;
1464 if (rclcpp::Time(context.trajectory_parts_[i].multi_dof_joint_trajectory.header.stamp) > current_time)
1466 d = std::max(d, rclcpp::Time(context.trajectory_parts_[i].multi_dof_joint_trajectory.header.stamp) -
1470 std::max(context.trajectory_parts_[i].joint_trajectory.points.empty() ?
1471 rclcpp::Duration::from_seconds(0) :
1472 rclcpp::Duration(context.trajectory_parts_[i].joint_trajectory.points.back().time_from_start),
1473 context.trajectory_parts_[i].multi_dof_joint_trajectory.points.empty() ?
1474 rclcpp::Duration::from_seconds(0) :
1476 context.trajectory_parts_[i].multi_dof_joint_trajectory.points.back().time_from_start));
1478 if (longest_part < 0 ||
1479 std::max(context.trajectory_parts_[i].joint_trajectory.points.size(),
1480 context.trajectory_parts_[i].multi_dof_joint_trajectory.points.size()) >
1481 std::max(context.trajectory_parts_[longest_part].joint_trajectory.points.size(),
1482 context.trajectory_parts_[longest_part].multi_dof_joint_trajectory.points.size()))
1489 std::map<std::string, double>::const_iterator scaling_it =
1490 controller_allowed_execution_duration_scaling_.find(context.controllers_[i]);
1491 const double current_scaling = scaling_it != controller_allowed_execution_duration_scaling_.end() ?
1492 scaling_it->second :
1493 allowed_execution_duration_scaling_;
1495 std::map<std::string, double>::const_iterator margin_it =
1496 controller_allowed_goal_duration_margin_.find(context.controllers_[i]);
1497 const double current_margin = margin_it != controller_allowed_goal_duration_margin_.end() ?
1499 allowed_goal_duration_margin_;
1502 expected_trajectory_duration =
1503 std::max(d * current_scaling + rclcpp::Duration::from_seconds(current_margin), expected_trajectory_duration);
1507 if (longest_part >= 0)
1509 std::scoped_lock slock(time_index_mutex_);
1511 if (context.trajectory_parts_[longest_part].joint_trajectory.points.size() >=
1512 context.trajectory_parts_[longest_part].multi_dof_joint_trajectory.points.size())
1514 auto d = rclcpp::Duration::from_seconds(0);
1515 if (rclcpp::Time(context.trajectory_parts_[longest_part].joint_trajectory.header.stamp) > current_time)
1516 d = rclcpp::Time(context.trajectory_parts_[longest_part].joint_trajectory.header.stamp) - current_time;
1517 for (trajectory_msgs::msg::JointTrajectoryPoint& point :
1518 context.trajectory_parts_[longest_part].joint_trajectory.points)
1519 time_index_.push_back(current_time + d +
rclcpp::Duration(point.time_from_start));
1523 auto d = rclcpp::Duration::from_seconds(0);
1524 if (rclcpp::Time(context.trajectory_parts_[longest_part].multi_dof_joint_trajectory.header.stamp) > current_time)
1526 d = rclcpp::Time(context.trajectory_parts_[longest_part].multi_dof_joint_trajectory.header.stamp) -
1529 for (trajectory_msgs::msg::MultiDOFJointTrajectoryPoint& point :
1530 context.trajectory_parts_[longest_part].multi_dof_joint_trajectory.points)
1531 time_index_.push_back(current_time + d +
rclcpp::Duration(point.time_from_start));
1536 for (moveit_controller_manager::MoveItControllerHandlePtr& handle : handles)
1538 if (execution_duration_monitoring_)
1540 if (!handle->waitForExecution(expected_trajectory_duration))
1542 if (!execution_complete_ && node_->now() - current_time > expected_trajectory_duration)
1544 RCLCPP_ERROR(logger_,
1545 "Controller is taking too long to execute trajectory (the expected upper "
1546 "bound for the trajectory execution was %lf seconds). Stopping trajectory.",
1547 expected_trajectory_duration.seconds());
1549 std::scoped_lock slock(execution_state_mutex_);
1550 stopExecutionInternal();
1560 handle->waitForExecution();
1563 if (execution_complete_)
1570 RCLCPP_WARN_STREAM(logger_,
"Controller handle " << handle->getName() <<
" reports status "
1571 << handle->getLastExecutionStatus().asString());
1572 last_execution_status_ = handle->getLastExecutionStatus();
1578 execution_state_mutex_.lock();
1579 active_handles_.clear();
1582 time_index_mutex_.lock();
1583 time_index_.clear();
1584 current_context_ = -1;
1585 time_index_mutex_.unlock();
1587 execution_state_mutex_.unlock();
1592 RCLCPP_ERROR(logger_,
"Active status of required controllers can not be assured.");
1598bool TrajectoryExecutionManager::waitForRobotToStop(
const TrajectoryExecutionContext& context,
double wait_time)
1601 if ((allowed_start_tolerance_ == 0 && allowed_start_tolerance_joints_.empty()) || !wait_for_trajectory_completion_)
1603 RCLCPP_INFO(logger_,
"Not waiting for trajectory completion");
1607 auto start = std::chrono::system_clock::now();
1608 double time_remaining = wait_time;
1610 moveit::core::RobotStatePtr prev_state, cur_state;
1611 prev_state = csm_->getCurrentState();
1612 prev_state->enforceBounds();
1615 unsigned int no_motion_count = 0;
1616 while (time_remaining > 0. && no_motion_count < 3)
1618 if (!csm_->waitForCurrentState(node_->now(), time_remaining) || !(cur_state = csm_->getCurrentState()))
1620 RCLCPP_WARN(logger_,
"Failed to receive current joint state");
1623 cur_state->enforceBounds();
1624 std::chrono::duration<double> elapsed_seconds = std::chrono::system_clock::now() - start;
1625 time_remaining = wait_time - elapsed_seconds.count();
1629 for (
const auto& trajectory : context.trajectory_parts_)
1631 const std::vector<std::string>& joint_names = trajectory.joint_trajectory.joint_names;
1632 const std::size_t n = joint_names.size();
1634 for (std::size_t i = 0; i < n && !moved; ++i)
1640 const double joint_start_tolerance = getAllowedStartToleranceJoint(joint_names[i]);
1641 if (fabs(jm->
distance(cur_state->getJointPositions(jm), prev_state->getJointPositions(jm))) >
1642 joint_start_tolerance)
1645 no_motion_count = 0;
1654 std::swap(prev_state, cur_state);
1657 return time_remaining > 0;
1662 std::scoped_lock slock(time_index_mutex_);
1663 if (current_context_ < 0)
1664 return std::make_pair(-1, -1);
1665 if (time_index_.empty())
1666 return std::make_pair(
static_cast<int>(current_context_), -1);
1667 std::vector<rclcpp::Time>::const_iterator time_index_it =
1668 std::lower_bound(time_index_.begin(), time_index_.end(), node_->now());
1669 int pos = time_index_it - time_index_.begin();
1670 return std::make_pair(
static_cast<int>(current_context_), pos);
1673const std::vector<TrajectoryExecutionManager::TrajectoryExecutionContext*>&
1676 return trajectories_;
1681 return last_execution_status_;
1687 if (joint_model_group)
1699 std::vector<std::string> all_controller_names;
1700 for (std::map<std::string, ControllerInformation>::const_iterator it = known_controllers_.begin();
1701 it != known_controllers_.end(); ++it)
1702 all_controller_names.push_back(it->first);
1703 std::vector<std::string> selected_controllers;
1704 std::set<std::string> jset;
1705 for (
const std::string& joint : joints)
1716 if (selectControllers(jset, all_controller_names, selected_controllers))
1733 reloadControllerInformation();
1735 updateControllersState(DEFAULT_CONTROLLER_INFORMATION_VALIDITY_AGE);
1737 if (manage_controllers_)
1739 std::vector<std::string> controllers_to_activate;
1740 std::vector<std::string> controllers_to_deactivate;
1741 std::set<std::string> joints_to_be_activated;
1742 std::set<std::string> joints_to_be_deactivated;
1743 for (
const std::string& controller : controllers)
1745 std::map<std::string, ControllerInformation>::const_iterator it = known_controllers_.find(controller);
1746 if (it == known_controllers_.end())
1748 std::stringstream stream;
1749 for (
const auto& controller : known_controllers_)
1751 stream <<
" `" << controller.first <<
'`';
1753 RCLCPP_WARN_STREAM(logger_,
"Controller " << controller <<
" is not known. Known controllers: " << stream.str());
1756 if (!it->second.state_.active_)
1758 RCLCPP_DEBUG_STREAM(logger_,
"Need to activate " << controller);
1759 controllers_to_activate.push_back(controller);
1760 joints_to_be_activated.insert(it->second.joints_.begin(), it->second.joints_.end());
1761 for (
const std::string& overlapping_controller : it->second.overlapping_controllers_)
1763 const ControllerInformation& ci = known_controllers_[overlapping_controller];
1764 if (ci.state_.active_)
1766 controllers_to_deactivate.push_back(overlapping_controller);
1767 joints_to_be_deactivated.insert(ci.joints_.begin(), ci.joints_.end());
1772 RCLCPP_DEBUG_STREAM(logger_,
"Controller " << controller <<
" is already active");
1774 std::set<std::string> diff;
1775 std::set_difference(joints_to_be_deactivated.begin(), joints_to_be_deactivated.end(),
1776 joints_to_be_activated.begin(), joints_to_be_activated.end(), std::inserter(diff, diff.end()));
1780 std::vector<std::string> possible_additional_controllers;
1781 for (std::map<std::string, ControllerInformation>::const_iterator it = known_controllers_.begin();
1782 it != known_controllers_.end(); ++it)
1785 for (
const std::string& controller_to_activate : controllers_to_activate)
1787 if (it->second.overlapping_controllers_.find(controller_to_activate) !=
1788 it->second.overlapping_controllers_.end())
1795 possible_additional_controllers.push_back(it->first);
1799 std::vector<std::string> additional_controllers;
1800 if (selectControllers(diff, possible_additional_controllers, additional_controllers))
1802 controllers_to_activate.insert(controllers_to_activate.end(), additional_controllers.begin(),
1803 additional_controllers.end());
1810 if (!controllers_to_activate.empty() || !controllers_to_deactivate.empty())
1812 if (controller_manager_)
1815 for (
const std::string& controller_to_activate : controllers_to_activate)
1817 ControllerInformation& ci = known_controllers_[controller_to_activate];
1818 ci.last_update_ = rclcpp::Time(0, 0, RCL_ROS_TIME);
1821 for (
const std::string& controller_to_deactivate : controllers_to_deactivate)
1822 known_controllers_[controller_to_deactivate].last_update_ = rclcpp::Time(0, 0, RCL_ROS_TIME);
1823 return controller_manager_->switchControllers(controllers_to_activate, controllers_to_deactivate);
1833 std::set<std::string> originally_active;
1834 for (std::map<std::string, ControllerInformation>::const_iterator it = known_controllers_.begin();
1835 it != known_controllers_.end(); ++it)
1837 if (it->second.state_.active_)
1839 originally_active.insert(it->first);
1842 return std::includes(originally_active.begin(), originally_active.end(), controllers.begin(), controllers.end());
1846void TrajectoryExecutionManager::loadControllerParams()
1848 for (
const auto& controller : known_controllers_)
1850 const std::string& controller_name = controller.first;
1851 for (
const auto& controller_manager_name : controller_manager_loader_->getDeclaredClasses())
1853 const std::string parameter_prefix =
1854 controller_manager_loader_->getClassPackage(controller_manager_name) +
"." + controller_name;
1856 double allowed_execution_duration_scaling;
1857 if (node_->get_parameter(parameter_prefix +
".allowed_execution_duration_scaling",
1858 allowed_execution_duration_scaling))
1859 controller_allowed_execution_duration_scaling_.insert({ controller_name, allowed_execution_duration_scaling });
1861 double allowed_goal_duration_margin;
1862 if (node_->get_parameter(parameter_prefix +
".allowed_goal_duration_margin", allowed_goal_duration_margin))
1863 controller_allowed_goal_duration_margin_.insert({ controller_name, allowed_goal_duration_margin });
1868double TrajectoryExecutionManager::getAllowedStartToleranceJoint(
const std::string& joint_name)
const
1870 auto start_tolerance_it = allowed_start_tolerance_joints_.find(joint_name);
1871 return start_tolerance_it != allowed_start_tolerance_joints_.end() ? start_tolerance_it->second :
1872 allowed_start_tolerance_;
1875void TrajectoryExecutionManager::setAllowedStartToleranceJoint(
const std::string& parameter_name,
1876 double joint_start_tolerance)
1878 if (joint_start_tolerance < 0)
1880 RCLCPP_WARN(logger_,
"%s has a negative value. The start tolerance value for that joint was not updated.",
1881 parameter_name.c_str());
1886 std::string joint_name = parameter_name;
1887 const std::string parameter_prefix =
"trajectory_execution.allowed_start_tolerance_joints.";
1888 if (parameter_name.find(parameter_prefix) == 0)
1889 joint_name = joint_name.substr(parameter_prefix.length());
1891 if (!robot_model_->hasJointModel(joint_name))
1893 RCLCPP_WARN(logger_,
1894 "Joint '%s' was not found in the robot model. "
1895 "The start tolerance value for that joint was not updated.",
1896 joint_name.c_str());
1900 allowed_start_tolerance_joints_.insert_or_assign(joint_name, joint_start_tolerance);
1903void TrajectoryExecutionManager::initializeAllowedStartToleranceJoints()
1905 allowed_start_tolerance_joints_.clear();
1909 for (
const auto& joint_name : robot_model_->getJointModelNames())
1911 double joint_start_tolerance;
1912 const std::string parameter_name =
"trajectory_execution.allowed_start_tolerance_joints." + joint_name;
1913 if (node_->get_parameter(parameter_name, joint_start_tolerance))
1915 if (joint_start_tolerance < 0)
1917 RCLCPP_WARN(logger_,
1918 "%s has a negative value. The start tolerance value for that joint "
1919 "will default to allowed_start_tolerance.",
1920 parameter_name.c_str());
1923 allowed_start_tolerance_joints_.insert({ joint_name, joint_start_tolerance });
const std::vector< std::string > & getJointModelNames() const
Get the names of the joints in this group. These are the names of the joints returned by getJointMode...
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
const JointModel * getMimic() const
Get the joint this one is mimicking.
virtual double distance(const double *value1, const double *value2) const =0
Compute the distance between two joint states of the same model (represented by the variable values)
bool isPassive() const
Check if this joint is passive.
virtual void computeTransform(const double *joint_values, Eigen::Isometry3d &transf) const =0
Given the joint values for a joint, compute the corresponding transform. The computed transform is gu...
JointType getType() const
Get the type of joint.
Representation of a robot's state. This includes position, velocity, acceleration and effort.
void setToDefaultValues()
Set all joints to their default positions. The default position is 0, or if that is not within bounds...
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...
TrajectoryExecutionManager(const rclcpp::Node::SharedPtr &node, const moveit::core::RobotModelConstPtr &robot_model, const planning_scene_monitor::CurrentStateMonitorPtr &csm)
Load the controller manager plugin, start listening for events on a topic.
~TrajectoryExecutionManager()
Destructor. Cancels all running trajectories (if any)
void execute(const ExecutionCompleteCallback &callback=ExecutionCompleteCallback(), bool auto_clear=true)
Start the execution of pushed trajectories; this does not wait for completion, but calls a callback w...
void stopExecution(bool auto_clear=true)
Stop whatever executions are active, if any.
void setWaitForTrajectoryCompletion(bool flag)
Enable or disable waiting for trajectory completion.
double allowedStartTolerance() const
Get the current joint-value for validating trajectory's start point against current robot state.
bool ensureActiveControllersForGroup(const std::string &group)
Make sure the active controllers are such that trajectories that actuate joints in the specified grou...
void setAllowedGoalDurationMargin(double margin)
const std::vector< TrajectoryExecutionContext * > & getTrajectories() const
Get the trajectories to be executed.
std::function< void(const moveit_controller_manager::ExecutionStatus &)> ExecutionCompleteCallback
bool ensureActiveController(const std::string &controller)
Make sure a particular controller is active.
void setAllowedExecutionDurationScaling(double scaling)
moveit_controller_manager::ExecutionStatus getLastExecutionStatus() const
Return the controller status for the last attempted execution.
std::pair< int, int > getCurrentExpectedTrajectoryIndex() const
double allowedExecutionDurationScaling() const
Get the current scaling of the duration of a trajectory to get the allowed duration of execution.
static const std::string EXECUTION_EVENT_TOPIC
void enableExecutionDurationMonitoring(bool flag)
bool push(const moveit_msgs::msg::RobotTrajectory &trajectory, const std::string &controller="")
void setExecutionVelocityScaling(double scaling)
bool isManagingControllers() const
If this function returns true, then this instance of the manager is allowed to load/unload/switch con...
bool isControllerActive(const std::string &controller)
Check if a controller is active.
bool executionDurationMonitoring() const
Get the current status of the monitoring of trajectory execution duration.
double allowedGoalDurationMargin() const
Get the current margin of the duration of a trajectory to get the allowed duration of execution.
bool waitForTrajectoryCompletion() const
Get the current state of waiting for the trajectory being completed.
moveit_controller_manager::ExecutionStatus executeAndWait(bool auto_clear=true)
moveit_controller_manager::ExecutionStatus waitForExecution()
void setAllowedStartTolerance(double tolerance)
Set joint-value tolerance for validating trajectory's start point against current robot state.
void processEvent(const std::string &event)
Execute a named event (e.g., 'stop')
double executionVelocityScaling() const
Get the current scaling of the execution velocities.
bool areControllersActive(const std::vector< std::string > &controllers)
Check if a set of controllers is active.
std::function< void(std::size_t)> PathSegmentCompleteCallback
bool ensureActiveControllersForJoints(const std::vector< std::string > &joints)
Make sure the active controllers are such that trajectories that actuate joints in the specified set ...
bool ensureActiveControllers(const std::vector< std::string > &controllers)
Make sure a particular set of controllers are active.
const moveit_controller_manager::MoveItControllerManagerPtr & getControllerManager() const
Get the instance of the controller manager used (this is the plugin instance loaded)
std::vector< std::size_t > nrjoints
std::vector< std::size_t > nrdefault
std::vector< std::size_t > nractive
std::vector< std::vector< std::string > > selected_options
Main namespace for MoveIt.
std::optional< trajectory_msgs::msg::JointTrajectory > toJointTrajectory(const RobotTrajectory &trajectory, bool include_mdof_joints=false, const std::vector< std::string > &joint_filter={})
Converts a RobotTrajectory to a JointTrajectory message.
The reported execution status.
std::string asString() const
Convert the execution status to a string.
Data structure that represents information necessary to execute a trajectory.
std::vector< std::string > controllers_
The controllers to use for executing the different trajectory parts;.