moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
move_group_interface.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2014, SRI International
5 * Copyright (c) 2013, Ioan A. Sucan
6 * Copyright (c) 2012, Willow Garage, Inc.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * * Neither the name of Willow Garage nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 *********************************************************************/
36
37/* Author: Ioan Sucan, Sachin Chitta */
38
39#include <cstdint>
40#include <stdexcept>
41#include <sstream>
42#include <memory>
43
44#include <rclcpp/rclcpp.hpp>
45#include <rclcpp/version.h>
46
47#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
58#include <moveit_msgs/action/execute_trajectory.hpp>
59#include <moveit_msgs/srv/query_planner_interfaces.hpp>
60#include <moveit_msgs/srv/get_cartesian_path.hpp>
61#include <moveit_msgs/srv/grasp_planning.hpp>
62#include <moveit_msgs/srv/get_planner_params.hpp>
63#include <moveit_msgs/srv/set_planner_params.hpp>
66
67#include <std_msgs/msg/string.hpp>
68#include <geometry_msgs/msg/transform_stamped.hpp>
69// TODO: Remove conditional include when released to all active distros.
70#if __has_include(<tf2/utils.hpp>)
71#include <tf2/utils.hpp>
72#else
73#include <tf2/utils.h>
74#endif
75#include <tf2_eigen/tf2_eigen.hpp>
76// For Rolling, Kilted, and newer
77#if RCLCPP_VERSION_GTE(29, 6, 0)
78#include <tf2_ros/transform_listener.hpp>
79// For Jazzy and older
80#else
81#include <tf2_ros/transform_listener.h>
82#endif
83
84namespace moveit
85{
86namespace planning_interface
87{
89 "robot_description"; // name of the robot description (a param name, so it can be changed externally)
90
91namespace
92{
93enum ActiveTargetType
94{
95 JOINT,
96 POSE,
99};
100
101// Function to support both Rolling and Humble on the main branch
102// Rolling has deprecated the version of the create_client method that takes
103// rmw_qos_profile_services_default for the QoS argument
104#if RCLCPP_VERSION_GTE(17, 0, 0) // Rolling
105auto qosDefault()
106{
107 return rclcpp::SystemDefaultsQoS();
108}
109#else // Humble
110auto qosDefault()
111{
112 return rmw_qos_profile_services_default;
113}
114#endif
115
116} // namespace
117
119{
120 friend MoveGroupInterface;
121
122public:
123 MoveGroupInterfaceImpl(const rclcpp::Node::SharedPtr& node, const Options& opt,
124 const std::shared_ptr<tf2_ros::Buffer>& tf_buffer, const rclcpp::Duration& wait_for_servers)
125 : opt_(opt), node_(node), logger_(moveit::getLogger("moveit.ros.move_group_interface")), tf_buffer_(tf_buffer)
126 {
127 // We have no control on how the passed node is getting executed. To make sure MGI is functional, we're creating
128 // our own callback group which is managed in a separate callback thread
129 callback_group_ = node_->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive,
130 false /* don't spin with node executor */);
131 callback_executor_.add_callback_group(callback_group_, node->get_node_base_interface());
132 callback_thread_ = std::thread([this]() { callback_executor_.spin(); });
133
134 robot_model_ = opt.robot_model ? opt.robot_model : getSharedRobotModel(node_, opt.robot_description);
135 if (!getRobotModel())
136 {
137 std::string error = "Unable to construct robot model. Please make sure all needed information is on the "
138 "parameter server.";
139 RCLCPP_FATAL_STREAM(logger_, error);
140 throw std::runtime_error(error);
141 }
142
143 if (!getRobotModel()->hasJointModelGroup(opt.group_name))
144 {
145 std::string error = "Group '" + opt.group_name + "' was not found.";
146 RCLCPP_FATAL_STREAM(logger_, error);
147 throw std::runtime_error(error);
148 }
149
151 joint_model_group_ = getRobotModel()->getJointModelGroup(opt.group_name);
152
153 joint_state_target_ = std::make_shared<moveit::core::RobotState>(getRobotModel());
154 joint_state_target_->setToDefaultValues();
155 active_target_ = JOINT;
156 can_look_ = false;
157 look_around_attempts_ = 0;
158 can_replan_ = false;
159 replan_delay_ = 2.0;
160 replan_attempts_ = 1;
161 goal_joint_tolerance_ = 1e-4;
162 goal_position_tolerance_ = 1e-4; // 0.1 mm
163 goal_orientation_tolerance_ = 1e-3; // ~0.1 deg
164 allowed_planning_time_ = 5.0;
165 num_planning_attempts_ = 1;
166 node_->get_parameter_or<double>("robot_description_planning.default_velocity_scaling_factor",
167 max_velocity_scaling_factor_, 0.1);
168 node_->get_parameter_or<double>("robot_description_planning.default_acceleration_scaling_factor",
169 max_acceleration_scaling_factor_, 0.1);
170 initializing_constraints_ = false;
171
172 if (joint_model_group_->isChain())
173 end_effector_link_ = joint_model_group_->getLinkModelNames().back();
174 pose_reference_frame_ = getRobotModel()->getModelFrame();
175 // Append the slash between two topic components
176 trajectory_event_publisher_ = node_->create_publisher<std_msgs::msg::String>(
177 rclcpp::names::append(opt_.move_group_namespace,
179 1);
180 attached_object_publisher_ = node_->create_publisher<moveit_msgs::msg::AttachedCollisionObject>(
181 rclcpp::names::append(opt_.move_group_namespace,
183 1);
184
185 current_state_monitor_ = getSharedStateMonitor(node_, robot_model_, tf_buffer_);
186
187 move_action_client_ = rclcpp_action::create_client<moveit_msgs::action::MoveGroup>(
188 node_, rclcpp::names::append(opt_.move_group_namespace, move_group::MOVE_ACTION), callback_group_);
189 move_action_client_->wait_for_action_server(wait_for_servers.to_chrono<std::chrono::duration<double>>());
190 execute_action_client_ = rclcpp_action::create_client<moveit_msgs::action::ExecuteTrajectory>(
191 node_, rclcpp::names::append(opt_.move_group_namespace, move_group::EXECUTE_ACTION_NAME), callback_group_);
192 execute_action_client_->wait_for_action_server(wait_for_servers.to_chrono<std::chrono::duration<double>>());
193
194 query_service_ = node_->create_client<moveit_msgs::srv::QueryPlannerInterfaces>(
195 rclcpp::names::append(opt_.move_group_namespace, move_group::QUERY_PLANNERS_SERVICE_NAME), qosDefault(),
196 callback_group_);
197 get_params_service_ = node_->create_client<moveit_msgs::srv::GetPlannerParams>(
198 rclcpp::names::append(opt_.move_group_namespace, move_group::GET_PLANNER_PARAMS_SERVICE_NAME), qosDefault(),
199 callback_group_);
200 set_params_service_ = node_->create_client<moveit_msgs::srv::SetPlannerParams>(
201 rclcpp::names::append(opt_.move_group_namespace, move_group::SET_PLANNER_PARAMS_SERVICE_NAME), qosDefault(),
202 callback_group_);
203 cartesian_path_service_ = node_->create_client<moveit_msgs::srv::GetCartesianPath>(
204 rclcpp::names::append(opt_.move_group_namespace, move_group::CARTESIAN_PATH_SERVICE_NAME), qosDefault(),
205 callback_group_);
206
207 RCLCPP_INFO_STREAM(logger_, "Ready to take commands for planning group " << opt.group_name << '.');
208 }
209
211 {
212 if (constraints_init_thread_)
213 constraints_init_thread_->join();
214
215 callback_executor_.cancel();
216
217 if (callback_thread_.joinable())
218 callback_thread_.join();
219 }
220
221 const std::shared_ptr<tf2_ros::Buffer>& getTF() const
222 {
223 return tf_buffer_;
224 }
225
226 const Options& getOptions() const
227 {
228 return opt_;
229 }
230
231 const moveit::core::RobotModelConstPtr& getRobotModel() const
232 {
233 return robot_model_;
234 }
235
237 {
238 return joint_model_group_;
239 }
240
241 rclcpp_action::Client<moveit_msgs::action::MoveGroup>& getMoveGroupClient() const
242 {
243 return *move_action_client_;
244 }
245
246 bool getInterfaceDescription(moveit_msgs::msg::PlannerInterfaceDescription& desc)
247 {
248 auto req = std::make_shared<moveit_msgs::srv::QueryPlannerInterfaces::Request>();
249 auto future_response = query_service_->async_send_request(req);
250
251 if (future_response.valid())
252 {
253 const auto& response = future_response.get();
254 if (!response->planner_interfaces.empty())
255 {
256 desc = response->planner_interfaces.front();
257 return true;
258 }
259 }
260 return false;
261 }
262
263 bool getInterfaceDescriptions(std::vector<moveit_msgs::msg::PlannerInterfaceDescription>& desc)
264 {
265 auto req = std::make_shared<moveit_msgs::srv::QueryPlannerInterfaces::Request>();
266 auto future_response = query_service_->async_send_request(req);
267 if (future_response.valid())
268 {
269 const auto& response = future_response.get();
270 if (!response->planner_interfaces.empty())
271 {
272 desc = response->planner_interfaces;
273 return true;
274 }
275 }
276 return false;
277 }
278
279 std::map<std::string, std::string> getPlannerParams(const std::string& planner_id, const std::string& group = "")
280 {
281 auto req = std::make_shared<moveit_msgs::srv::GetPlannerParams::Request>();
282 moveit_msgs::srv::GetPlannerParams::Response::SharedPtr response;
283 req->planner_config = planner_id;
284 req->group = group;
285 std::map<std::string, std::string> result;
286
287 auto future_response = get_params_service_->async_send_request(req);
288 if (future_response.valid())
289 {
290 response = future_response.get();
291 for (unsigned int i = 0, end = response->params.keys.size(); i < end; ++i)
292 result[response->params.keys[i]] = response->params.values[i];
293 }
294 return result;
295 }
296
297 void setPlannerParams(const std::string& planner_id, const std::string& group,
298 const std::map<std::string, std::string>& params, bool replace = false)
299 {
300 auto req = std::make_shared<moveit_msgs::srv::SetPlannerParams::Request>();
301 req->planner_config = planner_id;
302 req->group = group;
303 req->replace = replace;
304 for (const std::pair<const std::string, std::string>& param : params)
305 {
306 req->params.keys.push_back(param.first);
307 req->params.values.push_back(param.second);
308 }
309 set_params_service_->async_send_request(req);
310 }
311
313 {
314 std::string default_planning_pipeline;
315 node_->get_parameter("move_group.default_planning_pipeline", default_planning_pipeline);
316 return default_planning_pipeline;
317 }
318
319 void setPlanningPipelineId(const std::string& pipeline_id)
320 {
321 if (pipeline_id != planning_pipeline_id_)
322 {
323 planning_pipeline_id_ = pipeline_id;
324
325 // Reset planner_id if planning pipeline changed
326 planner_id_ = "";
327 }
328 }
329
330 const std::string& getPlanningPipelineId() const
331 {
332 return planning_pipeline_id_;
333 }
334
335 std::string getDefaultPlannerId(const std::string& group) const
336 {
337 // Check what planning pipeline config should be used
338 std::string pipeline_id = getDefaultPlanningPipelineId();
339 if (!planning_pipeline_id_.empty())
340 pipeline_id = planning_pipeline_id_;
341
342 std::stringstream param_name;
343 param_name << "move_group";
344 if (!pipeline_id.empty())
345 param_name << "/planning_pipelines/" << pipeline_id;
346 if (!group.empty())
347 param_name << '.' << group;
348 param_name << ".default_planner_config";
349
350 std::string default_planner_config;
351 node_->get_parameter(param_name.str(), default_planner_config);
352 return default_planner_config;
353 }
354
355 void setPlannerId(const std::string& planner_id)
356 {
357 planner_id_ = planner_id;
358 }
359
360 const std::string& getPlannerId() const
361 {
362 return planner_id_;
363 }
364
365 void setNumPlanningAttempts(unsigned int num_planning_attempts)
366 {
367 num_planning_attempts_ = num_planning_attempts;
368 }
369
371 {
372 setMaxScalingFactor(max_velocity_scaling_factor_, value, "velocity_scaling_factor", 0.1);
373 }
374
376 {
377 return max_velocity_scaling_factor_;
378 }
379
381 {
382 setMaxScalingFactor(max_acceleration_scaling_factor_, value, "acceleration_scaling_factor", 0.1);
383 }
384
386 {
387 return max_acceleration_scaling_factor_;
388 }
389
390 void setMaxScalingFactor(double& variable, const double target_value, const char* factor_name, double fallback_value)
391 {
392 if (target_value > 1.0)
393 {
394 RCLCPP_WARN(logger_, "Limiting max_%s (%.2f) to 1.0.", factor_name, target_value);
395 variable = 1.0;
396 }
397 else if (target_value <= 0.0)
398 {
399 node_->get_parameter_or<double>(std::string("robot_description_planning.default_") + factor_name, variable,
400 fallback_value);
401 if (target_value < 0.0)
402 {
403 RCLCPP_WARN(logger_, "max_%s < 0.0! Setting to default: %.2f.", factor_name, variable);
404 }
405 }
406 else
407 {
408 variable = target_value;
409 }
410 }
411
413 {
414 return *joint_state_target_;
415 }
416
418 {
419 return *joint_state_target_;
420 }
421
422 void setStartState(const moveit_msgs::msg::RobotState& start_state)
423 {
424 considered_start_state_ = start_state;
425 }
426
428 {
429 considered_start_state_ = moveit_msgs::msg::RobotState();
430 moveit::core::robotStateToRobotStateMsg(start_state, considered_start_state_, true);
431 }
432
434 {
435 // set message to empty diff
436 considered_start_state_ = moveit_msgs::msg::RobotState();
437 considered_start_state_.is_diff = true;
438 }
439
440 moveit::core::RobotStatePtr getStartState()
441 {
442 moveit::core::RobotStatePtr s;
444 moveit::core::robotStateMsgToRobotState(considered_start_state_, *s, true);
445 return s;
446 }
447
448 bool setJointValueTarget(const geometry_msgs::msg::Pose& eef_pose, const std::string& end_effector_link,
449 const std::string& frame, bool approx)
450 {
451 const std::string& eef = end_effector_link.empty() ? getEndEffectorLink() : end_effector_link;
452 // this only works if we have an end-effector
453 if (!eef.empty())
454 {
455 // first we set the goal to be the same as the start state
456 moveit::core::RobotStatePtr c = getStartState();
457 if (c)
458 {
459 setTargetType(JOINT);
460 c->enforceBounds();
461 getTargetRobotState() = *c;
462 if (!getTargetRobotState().satisfiesBounds(getGoalJointTolerance()))
463 {
464 return false;
465 }
466 }
467 else
468 {
469 return false;
470 }
471
472 // we may need to do approximate IK
475
476 // if no frame transforms are needed, call IK directly
477 if (frame.empty() || moveit::core::Transforms::sameFrame(frame, getRobotModel()->getModelFrame()))
478 {
479 return getTargetRobotState().setFromIK(getJointModelGroup(), eef_pose, eef, 0.0,
481 }
482 else
483 {
484 // transform the pose into the model frame, then do IK
485 bool frame_found;
486 const Eigen::Isometry3d& t = getTargetRobotState().getFrameTransform(frame, &frame_found);
487 if (frame_found)
488 {
489 Eigen::Isometry3d p;
490 tf2::fromMsg(eef_pose, p);
491 return getTargetRobotState().setFromIK(getJointModelGroup(), t * p, eef, 0.0,
493 }
494 else
495 {
496 RCLCPP_ERROR(logger_, "Unable to transform from frame '%s' to frame '%s'", frame.c_str(),
497 getRobotModel()->getModelFrame().c_str());
498 return false;
499 }
500 }
501 }
502 else
503 {
504 return false;
505 }
506 }
507
508 void setEndEffectorLink(const std::string& end_effector)
509 {
510 end_effector_link_ = end_effector;
511 }
512
513 void clearPoseTarget(const std::string& end_effector_link)
514 {
515 pose_targets_.erase(end_effector_link);
516 }
517
519 {
520 pose_targets_.clear();
521 }
522
523 const std::string& getEndEffectorLink() const
524 {
525 return end_effector_link_;
526 }
527
528 const std::string& getEndEffector() const
529 {
530 if (!end_effector_link_.empty())
531 {
532 const std::vector<std::string>& possible_eefs =
533 getRobotModel()->getJointModelGroup(opt_.group_name)->getAttachedEndEffectorNames();
534 for (const std::string& possible_eef : possible_eefs)
535 {
536 if (getRobotModel()->getEndEffector(possible_eef)->hasLinkModel(end_effector_link_))
537 return possible_eef;
538 }
539 }
540 static std::string empty;
541 return empty;
542 }
543
544 bool setPoseTargets(const std::vector<geometry_msgs::msg::PoseStamped>& poses, const std::string& end_effector_link)
545 {
546 const std::string& eef = end_effector_link.empty() ? end_effector_link_ : end_effector_link;
547 if (eef.empty())
548 {
549 RCLCPP_ERROR(logger_, "No end-effector to set the pose for");
550 return false;
551 }
552 else
553 {
554 pose_targets_[eef] = poses;
555 // make sure we don't store an actual stamp, since that will become stale can potentially cause tf errors
556 std::vector<geometry_msgs::msg::PoseStamped>& stored_poses = pose_targets_[eef];
557 for (geometry_msgs::msg::PoseStamped& stored_pose : stored_poses)
558 stored_pose.header.stamp = rclcpp::Time(0);
559 }
560 return true;
561 }
562
563 bool hasPoseTarget(const std::string& end_effector_link) const
564 {
565 const std::string& eef = end_effector_link.empty() ? end_effector_link_ : end_effector_link;
566 return pose_targets_.find(eef) != pose_targets_.end();
567 }
568
569 const geometry_msgs::msg::PoseStamped& getPoseTarget(const std::string& end_effector_link) const
570 {
571 const std::string& eef = end_effector_link.empty() ? end_effector_link_ : end_effector_link;
572
573 // if multiple pose targets are set, return the first one
574 std::map<std::string, std::vector<geometry_msgs::msg::PoseStamped>>::const_iterator jt = pose_targets_.find(eef);
575 if (jt != pose_targets_.end())
576 {
577 if (!jt->second.empty())
578 return jt->second.at(0);
579 }
580
581 // or return an error
582 static const geometry_msgs::msg::PoseStamped UNKNOWN;
583 RCLCPP_ERROR(logger_, "Pose for end-effector '%s' not known.", eef.c_str());
584 return UNKNOWN;
585 }
586
587 const std::vector<geometry_msgs::msg::PoseStamped>& getPoseTargets(const std::string& end_effector_link) const
588 {
589 const std::string& eef = end_effector_link.empty() ? end_effector_link_ : end_effector_link;
590
591 std::map<std::string, std::vector<geometry_msgs::msg::PoseStamped>>::const_iterator jt = pose_targets_.find(eef);
592 if (jt != pose_targets_.end())
593 {
594 if (!jt->second.empty())
595 return jt->second;
596 }
597
598 // or return an error
599 static const std::vector<geometry_msgs::msg::PoseStamped> EMPTY;
600 RCLCPP_ERROR(logger_, "Poses for end-effector '%s' are not known.", eef.c_str());
601 return EMPTY;
602 }
603
604 void setPoseReferenceFrame(const std::string& pose_reference_frame)
605 {
606 pose_reference_frame_ = pose_reference_frame;
607 }
608
609 const std::string& getPoseReferenceFrame() const
610 {
611 return pose_reference_frame_;
612 }
613
614 void setTargetType(ActiveTargetType type)
615 {
616 active_target_ = type;
617 }
618
619 ActiveTargetType getTargetType() const
620 {
621 return active_target_;
622 }
623
624 bool startStateMonitor(double wait)
625 {
626 if (!current_state_monitor_)
627 {
628 RCLCPP_ERROR(logger_, "Unable to monitor current robot state");
629 return false;
630 }
631
632 // if needed, start the monitor and wait up to 1 second for a full robot state
633 if (!current_state_monitor_->isActive())
634 current_state_monitor_->startStateMonitor();
635
636 current_state_monitor_->waitForCompleteState(opt_.group_name, wait);
637 return true;
638 }
639
640 bool getCurrentState(moveit::core::RobotStatePtr& current_state, double wait_seconds = 1.0)
641 {
642 if (!current_state_monitor_)
643 {
644 RCLCPP_ERROR(logger_, "Unable to get current robot state");
645 return false;
646 }
647
648 // if needed, start the monitor and wait up to 1 second for a full robot state
649 if (!current_state_monitor_->isActive())
650 current_state_monitor_->startStateMonitor();
651
652 if (!current_state_monitor_->waitForCurrentState(node_->now(), wait_seconds))
653 {
654 RCLCPP_ERROR(logger_, "Failed to fetch current robot state");
655 return false;
656 }
657
658 current_state = current_state_monitor_->getCurrentState();
659 return true;
660 }
661
663 {
664 if (!move_action_client_ || !move_action_client_->action_server_is_ready())
665 {
666 RCLCPP_INFO_STREAM(logger_, "MoveGroup action client/server not ready");
667 return moveit::core::MoveItErrorCode::FAILURE;
668 }
669 RCLCPP_INFO_STREAM(logger_, "MoveGroup action client/server ready");
670
671 moveit_msgs::action::MoveGroup::Goal goal;
672 constructGoal(goal);
673 goal.planning_options.plan_only = true;
674 goal.planning_options.look_around = false;
675 goal.planning_options.replan = false;
676 goal.planning_options.planning_scene_diff.is_diff = true;
677 goal.planning_options.planning_scene_diff.robot_state.is_diff = true;
678
679 bool done = false;
680 rclcpp_action::ResultCode code = rclcpp_action::ResultCode::UNKNOWN;
681 std::shared_ptr<moveit_msgs::action::MoveGroup::Result> res;
682 auto send_goal_opts = rclcpp_action::Client<moveit_msgs::action::MoveGroup>::SendGoalOptions();
683
684 send_goal_opts.goal_response_callback =
685 [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::MoveGroup>::SharedPtr& goal_handle) {
686 if (!goal_handle)
687 {
688 done = true;
689 RCLCPP_INFO(logger_, "Planning request rejected");
690 }
691 else
692 {
693 RCLCPP_INFO(logger_, "Planning request accepted");
694 }
695 };
696 send_goal_opts.result_callback =
697 [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::MoveGroup>::WrappedResult& result) {
698 res = result.result;
699 code = result.code;
700 done = true;
701
702 switch (result.code)
703 {
704 case rclcpp_action::ResultCode::SUCCEEDED:
705 RCLCPP_INFO(logger_, "Planning request complete!");
706 break;
707 case rclcpp_action::ResultCode::ABORTED:
708 RCLCPP_INFO(logger_, "Planning request aborted");
709 return;
710 case rclcpp_action::ResultCode::CANCELED:
711 RCLCPP_INFO(logger_, "Planning request canceled");
712 return;
713 default:
714 RCLCPP_INFO(logger_, "Planning request unknown result code");
715 return;
716 }
717 };
718
719 auto goal_handle_future = move_action_client_->async_send_goal(goal, send_goal_opts);
720
721 // wait until send_goal_opts.result_callback is called
722 while (!done)
723 {
724 std::this_thread::sleep_for(std::chrono::milliseconds(1));
725 }
726
727 if (code != rclcpp_action::ResultCode::SUCCEEDED)
728 {
729 RCLCPP_ERROR_STREAM(logger_, "MoveGroupInterface::plan() failed or timeout reached");
730 return res->error_code;
731 }
732
733 plan.trajectory = res->planned_trajectory;
734 plan.start_state = res->trajectory_start;
735 plan.planning_time = res->planning_time;
736 RCLCPP_INFO(logger_, "time taken to generate plan: %g seconds", plan.planning_time);
737
738 return res->error_code;
739 }
740
742 {
743 if (!move_action_client_ || !move_action_client_->action_server_is_ready())
744 {
745 RCLCPP_INFO_STREAM(logger_, "MoveGroup action client/server not ready");
746 return moveit::core::MoveItErrorCode::FAILURE;
747 }
748
749 moveit_msgs::action::MoveGroup::Goal goal;
750 constructGoal(goal);
751 goal.planning_options.plan_only = false;
752 goal.planning_options.look_around = can_look_;
753 goal.planning_options.replan = can_replan_;
754 goal.planning_options.replan_delay = replan_delay_;
755 goal.planning_options.planning_scene_diff.is_diff = true;
756 goal.planning_options.planning_scene_diff.robot_state.is_diff = true;
757
758 bool done = false;
759 rclcpp_action::ResultCode code = rclcpp_action::ResultCode::UNKNOWN;
760 std::shared_ptr<moveit_msgs::action::MoveGroup_Result> res;
761 auto send_goal_opts = rclcpp_action::Client<moveit_msgs::action::MoveGroup>::SendGoalOptions();
762
763 send_goal_opts.goal_response_callback =
764 [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::MoveGroup>::SharedPtr& goal_handle) {
765 if (!goal_handle)
766 {
767 done = true;
768 RCLCPP_INFO(logger_, "Plan and Execute request rejected");
769 }
770 else
771 {
772 RCLCPP_INFO(logger_, "Plan and Execute request accepted");
773 }
774 };
775 send_goal_opts.result_callback =
776 [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::MoveGroup>::WrappedResult& result) {
777 res = result.result;
778 code = result.code;
779 done = true;
780
781 switch (result.code)
782 {
783 case rclcpp_action::ResultCode::SUCCEEDED:
784 RCLCPP_INFO(logger_, "Plan and Execute request complete!");
785 break;
786 case rclcpp_action::ResultCode::ABORTED:
787 RCLCPP_INFO(logger_, "Plan and Execute request aborted");
788 return;
789 case rclcpp_action::ResultCode::CANCELED:
790 RCLCPP_INFO(logger_, "Plan and Execute request canceled");
791 return;
792 default:
793 RCLCPP_INFO(logger_, "Plan and Execute request unknown result code");
794 return;
795 }
796 };
797 auto goal_handle_future = move_action_client_->async_send_goal(goal, send_goal_opts);
798 if (!wait)
799 return moveit::core::MoveItErrorCode::SUCCESS;
800
801 // wait until send_goal_opts.result_callback is called
802 while (!done)
803 {
804 std::this_thread::sleep_for(std::chrono::milliseconds(1));
805 }
806
807 if (code != rclcpp_action::ResultCode::SUCCEEDED)
808 {
809 RCLCPP_ERROR_STREAM(logger_, "MoveGroupInterface::move() failed or timeout reached");
810 }
811 return res->error_code;
812 }
813
814 moveit::core::MoveItErrorCode execute(const moveit_msgs::msg::RobotTrajectory& trajectory, bool wait,
815 const std::vector<std::string>& controllers = std::vector<std::string>())
816 {
817 if (!execute_action_client_ || !execute_action_client_->action_server_is_ready())
818 {
819 RCLCPP_INFO_STREAM(logger_, "execute_action_client_ client/server not ready");
820 return moveit::core::MoveItErrorCode::FAILURE;
821 }
822
823 bool done = false;
824 rclcpp_action::ResultCode code = rclcpp_action::ResultCode::UNKNOWN;
825 std::shared_ptr<moveit_msgs::action::ExecuteTrajectory_Result> res;
826 auto send_goal_opts = rclcpp_action::Client<moveit_msgs::action::ExecuteTrajectory>::SendGoalOptions();
827
828 send_goal_opts.goal_response_callback =
829 [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::ExecuteTrajectory>::SharedPtr& goal_handle) {
830 if (!goal_handle)
831 {
832 done = true;
833 RCLCPP_INFO(logger_, "Execute request rejected");
834 }
835 else
836 {
837 RCLCPP_INFO(logger_, "Execute request accepted");
838 }
839 };
840 send_goal_opts.result_callback =
841 [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::ExecuteTrajectory>::WrappedResult& result) {
842 res = result.result;
843 code = result.code;
844 done = true;
845
846 switch (result.code)
847 {
848 case rclcpp_action::ResultCode::SUCCEEDED:
849 RCLCPP_INFO(logger_, "Execute request success!");
850 break;
851 case rclcpp_action::ResultCode::ABORTED:
852 RCLCPP_INFO(logger_, "Execute request aborted");
853 return;
854 case rclcpp_action::ResultCode::CANCELED:
855 RCLCPP_INFO(logger_, "Execute request canceled");
856 return;
857 default:
858 RCLCPP_INFO(logger_, "Execute request unknown result code");
859 return;
860 }
861 };
862
863 moveit_msgs::action::ExecuteTrajectory::Goal goal;
864 goal.trajectory = trajectory;
865 goal.controller_names = controllers;
866
867 auto goal_handle_future = execute_action_client_->async_send_goal(goal, send_goal_opts);
868 if (!wait)
869 return moveit::core::MoveItErrorCode::SUCCESS;
870
871 // wait until send_goal_opts.result_callback is called
872 while (!done)
873 {
874 std::this_thread::sleep_for(std::chrono::milliseconds(1));
875 }
876
877 if (code != rclcpp_action::ResultCode::SUCCEEDED)
878 {
879 RCLCPP_ERROR_STREAM(logger_, "MoveGroupInterface::execute() failed or timeout reached");
880 }
881 return res->error_code;
882 }
883
884 double computeCartesianPath(const std::vector<geometry_msgs::msg::Pose>& waypoints, double step,
885 moveit_msgs::msg::RobotTrajectory& msg,
886 const moveit_msgs::msg::Constraints& path_constraints, bool avoid_collisions,
887 moveit_msgs::msg::MoveItErrorCodes& error_code)
888 {
889 auto req = std::make_shared<moveit_msgs::srv::GetCartesianPath::Request>();
890 moveit_msgs::srv::GetCartesianPath::Response::SharedPtr response;
891
892 req->start_state = considered_start_state_;
893 req->group_name = opt_.group_name;
894 req->header.frame_id = getPoseReferenceFrame();
895 req->header.stamp = getClock()->now();
896 req->waypoints = waypoints;
897 req->max_step = step;
898 req->path_constraints = path_constraints;
899 req->avoid_collisions = avoid_collisions;
900 req->link_name = getEndEffectorLink();
901 req->max_velocity_scaling_factor = max_velocity_scaling_factor_;
902 req->max_acceleration_scaling_factor = max_acceleration_scaling_factor_;
903
904 auto future_response = cartesian_path_service_->async_send_request(req);
905 if (future_response.valid())
906 {
907 response = future_response.get();
908 error_code = response->error_code;
909 if (response->error_code.val == moveit_msgs::msg::MoveItErrorCodes::SUCCESS)
910 {
911 msg = response->solution;
912 return response->fraction;
913 }
914 else
915 {
916 return -1.0;
917 }
918 }
919 else
920 {
921 error_code.val = error_code.FAILURE;
922 return -1.0;
923 }
924 }
925
926 void stop()
927 {
928 if (trajectory_event_publisher_)
929 {
930 std_msgs::msg::String event;
931 event.data = "stop";
932 trajectory_event_publisher_->publish(event);
933 }
934 }
935
936 bool attachObject(const std::string& object, const std::string& link, const std::vector<std::string>& touch_links)
937 {
938 std::string l = link.empty() ? getEndEffectorLink() : link;
939 if (l.empty())
940 {
941 const std::vector<std::string>& links = joint_model_group_->getLinkModelNames();
942 if (!links.empty())
943 l = links[0];
944 }
945 if (l.empty())
946 {
947 RCLCPP_ERROR(logger_, "No known link to attach object '%s' to", object.c_str());
948 return false;
949 }
950 moveit_msgs::msg::AttachedCollisionObject aco;
951 aco.object.id = object;
952 aco.link_name.swap(l);
953 if (touch_links.empty())
954 {
955 aco.touch_links.push_back(aco.link_name);
956 }
957 else
958 {
959 aco.touch_links = touch_links;
960 }
961 aco.object.operation = moveit_msgs::msg::CollisionObject::ADD;
962 attached_object_publisher_->publish(aco);
963 return true;
964 }
965
966 bool detachObject(const std::string& name)
967 {
968 moveit_msgs::msg::AttachedCollisionObject aco;
969 // if name is a link
970 if (!name.empty() && joint_model_group_->hasLinkModel(name))
971 {
972 aco.link_name = name;
973 }
974 else
975 {
976 aco.object.id = name;
977 }
978 aco.object.operation = moveit_msgs::msg::CollisionObject::REMOVE;
979 if (aco.link_name.empty() && aco.object.id.empty())
980 {
981 // we only want to detach objects for this group
982 const std::vector<std::string>& lnames = joint_model_group_->getLinkModelNames();
983 for (const std::string& lname : lnames)
984 {
985 aco.link_name = lname;
986 attached_object_publisher_->publish(aco);
987 }
988 }
989 else
990 {
991 attached_object_publisher_->publish(aco);
992 }
993 return true;
994 }
995
997 {
998 return goal_position_tolerance_;
999 }
1000
1002 {
1003 return goal_orientation_tolerance_;
1004 }
1005
1007 {
1008 return goal_joint_tolerance_;
1009 }
1010
1011 void setGoalJointTolerance(double tolerance)
1012 {
1013 goal_joint_tolerance_ = tolerance;
1014 }
1015
1016 void setGoalPositionTolerance(double tolerance)
1017 {
1018 goal_position_tolerance_ = tolerance;
1019 }
1020
1021 void setGoalOrientationTolerance(double tolerance)
1022 {
1023 goal_orientation_tolerance_ = tolerance;
1024 }
1025
1026 void setPlanningTime(double seconds)
1027 {
1028 if (seconds > 0.0)
1029 allowed_planning_time_ = seconds;
1030 }
1031
1032 double getPlanningTime() const
1033 {
1034 return allowed_planning_time_;
1035 }
1036
1037 void constructRobotState(moveit_msgs::msg::RobotState& state) const
1038 {
1039 state = considered_start_state_;
1040 }
1041
1042 void constructMotionPlanRequest(moveit_msgs::msg::MotionPlanRequest& request) const
1043 {
1044 request.group_name = opt_.group_name;
1045 request.num_planning_attempts = num_planning_attempts_;
1046 request.max_velocity_scaling_factor = max_velocity_scaling_factor_;
1047 request.max_acceleration_scaling_factor = max_acceleration_scaling_factor_;
1048 request.allowed_planning_time = allowed_planning_time_;
1049 request.pipeline_id = planning_pipeline_id_;
1050 request.planner_id = planner_id_;
1051 request.workspace_parameters = workspace_parameters_;
1052 request.start_state = considered_start_state_;
1053
1054 if (active_target_ == JOINT)
1055 {
1056 request.goal_constraints.resize(1);
1057 request.goal_constraints[0] = kinematic_constraints::constructGoalConstraints(
1058 getTargetRobotState(), joint_model_group_, goal_joint_tolerance_);
1059 }
1060 else if (active_target_ == POSE || active_target_ == POSITION || active_target_ == ORIENTATION)
1061 {
1062 // find out how many goals are specified
1063 std::size_t goal_count = 0;
1064 for (const auto& pose_target : pose_targets_)
1065 goal_count = std::max(goal_count, pose_target.second.size());
1066
1067 // start filling the goals;
1068 // each end effector has a number of possible poses (K) as valid goals
1069 // but there could be multiple end effectors specified, so we want each end effector
1070 // to reach the goal that corresponds to the goals of the other end effectors
1071 request.goal_constraints.resize(goal_count);
1072
1073 for (const auto& pose_target : pose_targets_)
1074 {
1075 for (std::size_t i = 0; i < pose_target.second.size(); ++i)
1076 {
1077 moveit_msgs::msg::Constraints c = kinematic_constraints::constructGoalConstraints(
1078 pose_target.first, pose_target.second[i], goal_position_tolerance_, goal_orientation_tolerance_);
1079 if (active_target_ == ORIENTATION)
1080 c.position_constraints.clear();
1081 if (active_target_ == POSITION)
1082 c.orientation_constraints.clear();
1083 request.goal_constraints[i] = kinematic_constraints::mergeConstraints(request.goal_constraints[i], c);
1084 }
1085 }
1086 }
1087 else
1088 {
1089 RCLCPP_ERROR(logger_, "Unable to construct MotionPlanRequest representation");
1090 }
1091
1092 if (path_constraints_)
1093 {
1094 request.path_constraints = *path_constraints_;
1095 }
1096 if (trajectory_constraints_)
1097 request.trajectory_constraints = *trajectory_constraints_;
1098 }
1099
1100 void constructGoal(moveit_msgs::action::MoveGroup::Goal& goal) const
1101 {
1102 constructMotionPlanRequest(goal.request);
1103 }
1104
1105 void setPathConstraints(const moveit_msgs::msg::Constraints& constraint)
1106 {
1107 path_constraints_ = std::make_unique<moveit_msgs::msg::Constraints>(constraint);
1108 }
1109
1110 bool setPathConstraints(const std::string& constraint)
1111 {
1112 if (constraints_storage_)
1113 {
1115 if (constraints_storage_->getConstraints(msg_m, constraint, robot_model_->getName(), opt_.group_name))
1116 {
1117 path_constraints_ =
1118 std::make_unique<moveit_msgs::msg::Constraints>(static_cast<moveit_msgs::msg::Constraints>(*msg_m));
1119 return true;
1120 }
1121 else
1122 {
1123 return false;
1124 }
1125 }
1126 else
1127 {
1128 return false;
1129 }
1130 }
1131
1133 {
1134 path_constraints_.reset();
1135 }
1136
1137 void setTrajectoryConstraints(const moveit_msgs::msg::TrajectoryConstraints& constraint)
1138 {
1139 trajectory_constraints_ = std::make_unique<moveit_msgs::msg::TrajectoryConstraints>(constraint);
1140 }
1141
1143 {
1144 trajectory_constraints_.reset();
1145 }
1146
1147 std::vector<std::string> getKnownConstraints() const
1148 {
1149 while (initializing_constraints_)
1150 {
1151 std::chrono::duration<double> d(0.01);
1152 rclcpp::sleep_for(std::chrono::duration_cast<std::chrono::nanoseconds>(d), rclcpp::Context::SharedPtr(nullptr));
1153 }
1154
1155 std::vector<std::string> c;
1156 if (constraints_storage_)
1157 constraints_storage_->getKnownConstraints(c, robot_model_->getName(), opt_.group_name);
1158
1159 return c;
1160 }
1161
1162 moveit_msgs::msg::Constraints getPathConstraints() const
1163 {
1164 if (path_constraints_)
1165 {
1166 return *path_constraints_;
1167 }
1168 else
1169 {
1170 return moveit_msgs::msg::Constraints();
1171 }
1172 }
1173
1174 moveit_msgs::msg::TrajectoryConstraints getTrajectoryConstraints() const
1175 {
1176 if (trajectory_constraints_)
1177 {
1178 return *trajectory_constraints_;
1179 }
1180 else
1181 {
1182 return moveit_msgs::msg::TrajectoryConstraints();
1183 }
1184 }
1185
1186 void initializeConstraintsStorage(const std::string& host, unsigned int port)
1187 {
1188 initializing_constraints_ = true;
1189 if (constraints_init_thread_)
1190 constraints_init_thread_->join();
1191 constraints_init_thread_ =
1192 std::make_unique<std::thread>([this, host, port] { initializeConstraintsStorageThread(host, port); });
1193 }
1194
1195 void setWorkspace(double minx, double miny, double minz, double maxx, double maxy, double maxz)
1196 {
1197 workspace_parameters_.header.frame_id = getRobotModel()->getModelFrame();
1198 workspace_parameters_.header.stamp = getClock()->now();
1199 workspace_parameters_.min_corner.x = minx;
1200 workspace_parameters_.min_corner.y = miny;
1201 workspace_parameters_.min_corner.z = minz;
1202 workspace_parameters_.max_corner.x = maxx;
1203 workspace_parameters_.max_corner.y = maxy;
1204 workspace_parameters_.max_corner.z = maxz;
1205 }
1206
1207 rclcpp::Clock::SharedPtr getClock()
1208 {
1209 return node_->get_clock();
1210 }
1211
1212private:
1213 void initializeConstraintsStorageThread(const std::string& host, unsigned int port)
1214 {
1215 // Set up db
1216 try
1217 {
1218 warehouse_ros::DatabaseConnection::Ptr conn = moveit_warehouse::loadDatabase(node_);
1219 conn->setParams(host, port);
1220 if (conn->connect())
1221 {
1222 constraints_storage_ = std::make_unique<moveit_warehouse::ConstraintsStorage>(conn);
1223 }
1224 }
1225 catch (std::exception& ex)
1226 {
1227 RCLCPP_ERROR(logger_, "%s", ex.what());
1228 }
1229 initializing_constraints_ = false;
1230 }
1231
1232 Options opt_;
1233 rclcpp::Node::SharedPtr node_;
1234 rclcpp::Logger logger_;
1235 rclcpp::CallbackGroup::SharedPtr callback_group_;
1236 rclcpp::executors::SingleThreadedExecutor callback_executor_;
1237 std::thread callback_thread_;
1238 std::shared_ptr<tf2_ros::Buffer> tf_buffer_;
1239 moveit::core::RobotModelConstPtr robot_model_;
1240 planning_scene_monitor::CurrentStateMonitorPtr current_state_monitor_;
1241
1242 std::shared_ptr<rclcpp_action::Client<moveit_msgs::action::MoveGroup>> move_action_client_;
1243 // std::shared_ptr<rclcpp_action::Client<moveit_msgs::action::Pickup>> pick_action_client_;
1244 // std::shared_ptr<rclcpp_action::Client<moveit_msgs::action::Place>> place_action_client_;
1245 std::shared_ptr<rclcpp_action::Client<moveit_msgs::action::ExecuteTrajectory>> execute_action_client_;
1246
1247 // general planning params
1248 moveit_msgs::msg::RobotState considered_start_state_;
1249 moveit_msgs::msg::WorkspaceParameters workspace_parameters_;
1250 double allowed_planning_time_;
1251 std::string planning_pipeline_id_;
1252 std::string planner_id_;
1253 unsigned int num_planning_attempts_;
1254 double max_velocity_scaling_factor_;
1255 double max_acceleration_scaling_factor_;
1256 double goal_joint_tolerance_;
1257 double goal_position_tolerance_;
1258 double goal_orientation_tolerance_;
1259 bool can_look_;
1260 int32_t look_around_attempts_;
1261 bool can_replan_;
1262 int32_t replan_attempts_;
1263 double replan_delay_;
1264
1265 // joint state goal
1266 moveit::core::RobotStatePtr joint_state_target_;
1267 const moveit::core::JointModelGroup* joint_model_group_;
1268
1269 // pose goal;
1270 // for each link we have a set of possible goal locations;
1271 std::map<std::string, std::vector<geometry_msgs::msg::PoseStamped>> pose_targets_;
1272
1273 // common properties for goals
1274 ActiveTargetType active_target_;
1275 std::unique_ptr<moveit_msgs::msg::Constraints> path_constraints_;
1276 std::unique_ptr<moveit_msgs::msg::TrajectoryConstraints> trajectory_constraints_;
1277 std::string end_effector_link_;
1278 std::string pose_reference_frame_;
1279
1280 // ROS communication
1281 rclcpp::Publisher<std_msgs::msg::String>::SharedPtr trajectory_event_publisher_;
1282 rclcpp::Publisher<moveit_msgs::msg::AttachedCollisionObject>::SharedPtr attached_object_publisher_;
1283 rclcpp::Client<moveit_msgs::srv::QueryPlannerInterfaces>::SharedPtr query_service_;
1284 rclcpp::Client<moveit_msgs::srv::GetPlannerParams>::SharedPtr get_params_service_;
1285 rclcpp::Client<moveit_msgs::srv::SetPlannerParams>::SharedPtr set_params_service_;
1286 rclcpp::Client<moveit_msgs::srv::GetCartesianPath>::SharedPtr cartesian_path_service_;
1287 // rclcpp::Client<moveit_msgs::srv::GraspPlanning>::SharedPtr plan_grasps_service_;
1288 std::unique_ptr<moveit_warehouse::ConstraintsStorage> constraints_storage_;
1289 std::unique_ptr<std::thread> constraints_init_thread_;
1290 bool initializing_constraints_;
1291};
1292
1293MoveGroupInterface::MoveGroupInterface(const rclcpp::Node::SharedPtr& node, const std::string& group_name,
1294 const std::shared_ptr<tf2_ros::Buffer>& tf_buffer,
1295 const rclcpp::Duration& wait_for_servers)
1296 : logger_(moveit::getLogger("moveit.ros.move_group_interface"))
1297{
1298 if (!rclcpp::ok())
1299 throw std::runtime_error("ROS does not seem to be running");
1300 impl_ =
1301 new MoveGroupInterfaceImpl(node, Options(group_name), tf_buffer ? tf_buffer : getSharedTF(), wait_for_servers);
1302}
1303
1304MoveGroupInterface::MoveGroupInterface(const rclcpp::Node::SharedPtr& node, const Options& opt,
1305 const std::shared_ptr<tf2_ros::Buffer>& tf_buffer,
1306 const rclcpp::Duration& wait_for_servers)
1307 : logger_(moveit::getLogger("moveit.ros.move_group_interface"))
1308{
1309 impl_ = new MoveGroupInterfaceImpl(node, opt, tf_buffer ? tf_buffer : getSharedTF(), wait_for_servers);
1310}
1311
1313{
1314 delete impl_;
1315}
1316
1318 : remembered_joint_values_(std::move(other.remembered_joint_values_))
1319 , impl_(other.impl_)
1320 , logger_(std::move(other.logger_))
1321{
1322 other.impl_ = nullptr;
1323}
1324
1326{
1327 if (this != &other)
1328 {
1329 delete impl_;
1330 impl_ = other.impl_;
1331 logger_ = other.logger_;
1332 remembered_joint_values_ = std::move(other.remembered_joint_values_);
1333 other.impl_ = nullptr;
1334 }
1335
1336 return *this;
1337}
1338
1339const std::string& MoveGroupInterface::getName() const
1340{
1341 return impl_->getOptions().group_name;
1342}
1343
1344const std::vector<std::string>& MoveGroupInterface::getNamedTargets() const
1345{
1346 // The pointer returned by getJointModelGroup is guaranteed by the class
1347 // constructor to always be non-null
1348 return impl_->getJointModelGroup()->getDefaultStateNames();
1349}
1350
1351const std::shared_ptr<tf2_ros::Buffer>& MoveGroupInterface::getTF() const
1352{
1353 return impl_->getTF();
1354}
1355
1356moveit::core::RobotModelConstPtr MoveGroupInterface::getRobotModel() const
1357{
1358 return impl_->getRobotModel();
1359}
1360
1361bool MoveGroupInterface::getInterfaceDescription(moveit_msgs::msg::PlannerInterfaceDescription& desc) const
1362{
1363 return impl_->getInterfaceDescription(desc);
1364}
1365
1366bool MoveGroupInterface::getInterfaceDescriptions(std::vector<moveit_msgs::msg::PlannerInterfaceDescription>& desc) const
1367{
1368 return impl_->getInterfaceDescriptions(desc);
1369}
1370
1371std::map<std::string, std::string> MoveGroupInterface::getPlannerParams(const std::string& planner_id,
1372 const std::string& group) const
1373{
1374 return impl_->getPlannerParams(planner_id, group);
1375}
1376
1377void MoveGroupInterface::setPlannerParams(const std::string& planner_id, const std::string& group,
1378 const std::map<std::string, std::string>& params, bool replace)
1379{
1380 impl_->setPlannerParams(planner_id, group, params, replace);
1381}
1382
1384{
1385 return impl_->getDefaultPlanningPipelineId();
1386}
1387
1388void MoveGroupInterface::setPlanningPipelineId(const std::string& pipeline_id)
1389{
1390 impl_->setPlanningPipelineId(pipeline_id);
1391}
1392
1394{
1395 return impl_->getPlanningPipelineId();
1396}
1397
1398std::string MoveGroupInterface::getDefaultPlannerId(const std::string& group) const
1399{
1400 return impl_->getDefaultPlannerId(group);
1401}
1402
1403void MoveGroupInterface::setPlannerId(const std::string& planner_id)
1404{
1405 impl_->setPlannerId(planner_id);
1406}
1407
1408const std::string& MoveGroupInterface::getPlannerId() const
1409{
1410 return impl_->getPlannerId();
1411}
1412
1413void MoveGroupInterface::setNumPlanningAttempts(unsigned int num_planning_attempts)
1414{
1415 impl_->setNumPlanningAttempts(num_planning_attempts);
1416}
1417
1418void MoveGroupInterface::setMaxVelocityScalingFactor(double max_velocity_scaling_factor)
1419{
1420 impl_->setMaxVelocityScalingFactor(max_velocity_scaling_factor);
1421}
1422
1424{
1425 return impl_->getMaxVelocityScalingFactor();
1426}
1427
1428void MoveGroupInterface::setMaxAccelerationScalingFactor(double max_acceleration_scaling_factor)
1429{
1430 impl_->setMaxAccelerationScalingFactor(max_acceleration_scaling_factor);
1431}
1432
1434{
1435 return impl_->getMaxAccelerationScalingFactor();
1436}
1437
1439{
1440 return impl_->move(false);
1441}
1442
1443rclcpp_action::Client<moveit_msgs::action::MoveGroup>& MoveGroupInterface::getMoveGroupClient() const
1444{
1445 return impl_->getMoveGroupClient();
1446}
1447
1449{
1450 return impl_->move(true);
1451}
1452
1454 const std::vector<std::string>& controllers)
1455{
1456 return impl_->execute(plan.trajectory, false, controllers);
1457}
1458
1459moveit::core::MoveItErrorCode MoveGroupInterface::asyncExecute(const moveit_msgs::msg::RobotTrajectory& trajectory,
1460 const std::vector<std::string>& controllers)
1461{
1462 return impl_->execute(trajectory, false, controllers);
1463}
1464
1465moveit::core::MoveItErrorCode MoveGroupInterface::execute(const Plan& plan, const std::vector<std::string>& controllers)
1466{
1467 return impl_->execute(plan.trajectory, true, controllers);
1468}
1469
1470moveit::core::MoveItErrorCode MoveGroupInterface::execute(const moveit_msgs::msg::RobotTrajectory& trajectory,
1471 const std::vector<std::string>& controllers)
1472{
1473 return impl_->execute(trajectory, true, controllers);
1474}
1475
1480
1481double MoveGroupInterface::computeCartesianPath(const std::vector<geometry_msgs::msg::Pose>& waypoints, double eef_step,
1482 moveit_msgs::msg::RobotTrajectory& trajectory, bool avoid_collisions,
1483 moveit_msgs::msg::MoveItErrorCodes* error_code)
1484{
1485 moveit_msgs::msg::Constraints path_constraints_tmp;
1486 return computeCartesianPath(waypoints, eef_step, trajectory, moveit_msgs::msg::Constraints(), avoid_collisions,
1487 error_code);
1488}
1489
1490double MoveGroupInterface::computeCartesianPath(const std::vector<geometry_msgs::msg::Pose>& waypoints, double eef_step,
1491 moveit_msgs::msg::RobotTrajectory& trajectory,
1492 const moveit_msgs::msg::Constraints& path_constraints,
1493 bool avoid_collisions, moveit_msgs::msg::MoveItErrorCodes* error_code)
1494{
1495 if (error_code)
1496 {
1497 return impl_->computeCartesianPath(waypoints, eef_step, trajectory, path_constraints, avoid_collisions, *error_code);
1498 }
1499 else
1500 {
1501 moveit_msgs::msg::MoveItErrorCodes err_tmp;
1502 err_tmp.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;
1503 moveit_msgs::msg::MoveItErrorCodes& err = error_code ? *error_code : err_tmp;
1504 return impl_->computeCartesianPath(waypoints, eef_step, trajectory, path_constraints, avoid_collisions, err);
1505 }
1506}
1507
1509{
1510 impl_->stop();
1511}
1512
1513void MoveGroupInterface::setStartState(const moveit_msgs::msg::RobotState& start_state)
1514{
1515 impl_->setStartState(start_state);
1516}
1517
1519{
1520 impl_->setStartState(start_state);
1521}
1522
1524{
1525 impl_->setStartStateToCurrentState();
1526}
1527
1529{
1530 impl_->getTargetRobotState().setToRandomPositions();
1531 impl_->setTargetType(JOINT);
1532}
1533
1534const std::vector<std::string>& MoveGroupInterface::getJointNames() const
1535{
1536 return impl_->getJointModelGroup()->getVariableNames();
1537}
1538
1539const std::vector<std::string>& MoveGroupInterface::getLinkNames() const
1540{
1541 return impl_->getJointModelGroup()->getLinkModelNames();
1542}
1543
1544std::map<std::string, double> MoveGroupInterface::getNamedTargetValues(const std::string& name) const
1545{
1546 std::map<std::string, std::vector<double>>::const_iterator it = remembered_joint_values_.find(name);
1547 std::map<std::string, double> positions;
1548
1549 if (it != remembered_joint_values_.cend())
1550 {
1551 std::vector<std::string> names = impl_->getJointModelGroup()->getVariableNames();
1552 for (size_t x = 0; x < names.size(); ++x)
1553 {
1554 positions[names[x]] = it->second[x];
1555 }
1556 }
1557 else
1558 {
1559 if (!impl_->getJointModelGroup()->getVariableDefaultPositions(name, positions))
1560 {
1561 RCLCPP_ERROR(logger_, "The requested named target '%s' does not exist, returning empty positions.", name.c_str());
1562 }
1563 }
1564 return positions;
1565}
1566
1567bool MoveGroupInterface::setNamedTarget(const std::string& name)
1568{
1569 std::map<std::string, std::vector<double>>::const_iterator it = remembered_joint_values_.find(name);
1570 if (it != remembered_joint_values_.end())
1571 {
1572 return setJointValueTarget(it->second);
1573 }
1574 else
1575 {
1576 if (impl_->getTargetRobotState().setToDefaultValues(impl_->getJointModelGroup(), name))
1577 {
1578 impl_->setTargetType(JOINT);
1579 return true;
1580 }
1581 RCLCPP_ERROR(logger_, "The requested named target '%s' does not exist", name.c_str());
1582 return false;
1583 }
1584}
1585
1586void MoveGroupInterface::getJointValueTarget(std::vector<double>& group_variable_values) const
1587{
1588 impl_->getTargetRobotState().copyJointGroupPositions(impl_->getJointModelGroup(), group_variable_values);
1589}
1590
1591bool MoveGroupInterface::setJointValueTarget(const std::vector<double>& joint_values)
1592{
1593 const auto n_group_joints = impl_->getJointModelGroup()->getVariableCount();
1594 if (joint_values.size() != n_group_joints)
1595 {
1596 RCLCPP_DEBUG_STREAM(logger_, "Provided joint value list has length " << joint_values.size() << " but group "
1597 << impl_->getJointModelGroup()->getName()
1598 << " has " << n_group_joints << " joints");
1599 return false;
1600 }
1601 impl_->setTargetType(JOINT);
1602 impl_->getTargetRobotState().setJointGroupPositions(impl_->getJointModelGroup(), joint_values);
1603 return impl_->getTargetRobotState().satisfiesBounds(impl_->getJointModelGroup(), impl_->getGoalJointTolerance());
1604}
1605
1606bool MoveGroupInterface::setJointValueTarget(const std::map<std::string, double>& variable_values)
1607{
1608 const auto& allowed = impl_->getJointModelGroup()->getVariableNames();
1609 for (const auto& pair : variable_values)
1610 {
1611 if (std::find(allowed.begin(), allowed.end(), pair.first) == allowed.end())
1612 {
1613 RCLCPP_ERROR_STREAM(logger_, "joint variable " << pair.first << " is not part of group "
1614 << impl_->getJointModelGroup()->getName());
1615 return false;
1616 }
1617 }
1618
1619 impl_->setTargetType(JOINT);
1620 impl_->getTargetRobotState().setVariablePositions(variable_values);
1621 return impl_->getTargetRobotState().satisfiesBounds(impl_->getGoalJointTolerance());
1622}
1623
1624bool MoveGroupInterface::setJointValueTarget(const std::vector<std::string>& variable_names,
1625 const std::vector<double>& variable_values)
1626{
1627 if (variable_names.size() != variable_values.size())
1628 {
1629 RCLCPP_ERROR_STREAM(logger_, "sizes of name and position arrays do not match");
1630 return false;
1631 }
1632 const auto& allowed = impl_->getJointModelGroup()->getVariableNames();
1633 for (const auto& variable_name : variable_names)
1634 {
1635 if (std::find(allowed.begin(), allowed.end(), variable_name) == allowed.end())
1636 {
1637 RCLCPP_ERROR_STREAM(logger_, "joint variable " << variable_name << " is not part of group "
1638 << impl_->getJointModelGroup()->getName());
1639 return false;
1640 }
1641 }
1642
1643 impl_->setTargetType(JOINT);
1644 impl_->getTargetRobotState().setVariablePositions(variable_names, variable_values);
1645 return impl_->getTargetRobotState().satisfiesBounds(impl_->getGoalJointTolerance());
1646}
1647
1649{
1650 impl_->setTargetType(JOINT);
1651 impl_->getTargetRobotState() = rstate;
1652 return impl_->getTargetRobotState().satisfiesBounds(impl_->getGoalJointTolerance());
1653}
1654
1655bool MoveGroupInterface::setJointValueTarget(const std::string& joint_name, double value)
1656{
1657 std::vector<double> values(1, value);
1658 return setJointValueTarget(joint_name, values);
1659}
1660
1661bool MoveGroupInterface::setJointValueTarget(const std::string& joint_name, const std::vector<double>& values)
1662{
1663 impl_->setTargetType(JOINT);
1664 const moveit::core::JointModel* jm = impl_->getJointModelGroup()->getJointModel(joint_name);
1665 if (jm && jm->getVariableCount() == values.size())
1666 {
1667 impl_->getTargetRobotState().setJointPositions(jm, values);
1668 return impl_->getTargetRobotState().satisfiesBounds(jm, impl_->getGoalJointTolerance());
1669 }
1670
1671 RCLCPP_ERROR_STREAM(logger_,
1672 "joint " << joint_name << " is not part of group " << impl_->getJointModelGroup()->getName());
1673 return false;
1674}
1675
1676bool MoveGroupInterface::setJointValueTarget(const sensor_msgs::msg::JointState& state)
1677{
1678 return setJointValueTarget(state.name, state.position);
1679}
1680
1681bool MoveGroupInterface::setJointValueTarget(const geometry_msgs::msg::Pose& eef_pose,
1682 const std::string& end_effector_link)
1683{
1684 return impl_->setJointValueTarget(eef_pose, end_effector_link, "", false);
1685}
1686
1687bool MoveGroupInterface::setJointValueTarget(const geometry_msgs::msg::PoseStamped& eef_pose,
1688 const std::string& end_effector_link)
1689{
1690 return impl_->setJointValueTarget(eef_pose.pose, end_effector_link, eef_pose.header.frame_id, false);
1691}
1692
1693bool MoveGroupInterface::setJointValueTarget(const Eigen::Isometry3d& eef_pose, const std::string& end_effector_link)
1694{
1695 geometry_msgs::msg::Pose msg = tf2::toMsg(eef_pose);
1696 return setJointValueTarget(msg, end_effector_link);
1697}
1698
1699bool MoveGroupInterface::setApproximateJointValueTarget(const geometry_msgs::msg::Pose& eef_pose,
1700 const std::string& end_effector_link)
1701{
1702 return impl_->setJointValueTarget(eef_pose, end_effector_link, "", true);
1703}
1704
1705bool MoveGroupInterface::setApproximateJointValueTarget(const geometry_msgs::msg::PoseStamped& eef_pose,
1706 const std::string& end_effector_link)
1707{
1708 return impl_->setJointValueTarget(eef_pose.pose, end_effector_link, eef_pose.header.frame_id, true);
1709}
1710
1711bool MoveGroupInterface::setApproximateJointValueTarget(const Eigen::Isometry3d& eef_pose,
1712 const std::string& end_effector_link)
1713{
1714 geometry_msgs::msg::Pose msg = tf2::toMsg(eef_pose);
1715 return setApproximateJointValueTarget(msg, end_effector_link);
1716}
1717
1719{
1720 return impl_->getTargetRobotState();
1721}
1722
1724{
1725 return impl_->getEndEffectorLink();
1726}
1727
1728const std::string& MoveGroupInterface::getEndEffector() const
1729{
1730 return impl_->getEndEffector();
1731}
1732
1733bool MoveGroupInterface::setEndEffectorLink(const std::string& link_name)
1734{
1735 if (impl_->getEndEffectorLink().empty() || link_name.empty())
1736 return false;
1737 impl_->setEndEffectorLink(link_name);
1738 impl_->setTargetType(POSE);
1739 return true;
1740}
1741
1742bool MoveGroupInterface::setEndEffector(const std::string& eef_name)
1743{
1744 const moveit::core::JointModelGroup* jmg = impl_->getRobotModel()->getEndEffector(eef_name);
1745 if (jmg)
1746 return setEndEffectorLink(jmg->getEndEffectorParentGroup().second);
1747 return false;
1748}
1749
1750void MoveGroupInterface::clearPoseTarget(const std::string& end_effector_link)
1751{
1752 impl_->clearPoseTarget(end_effector_link);
1753}
1754
1756{
1757 impl_->clearPoseTargets();
1758}
1759
1760bool MoveGroupInterface::setPoseTarget(const Eigen::Isometry3d& pose, const std::string& end_effector_link)
1761{
1762 std::vector<geometry_msgs::msg::PoseStamped> pose_msg(1);
1763 pose_msg[0].pose = tf2::toMsg(pose);
1764 pose_msg[0].header.frame_id = getPoseReferenceFrame();
1765 pose_msg[0].header.stamp = impl_->getClock()->now();
1766 return setPoseTargets(pose_msg, end_effector_link);
1767}
1768
1769bool MoveGroupInterface::setPoseTarget(const geometry_msgs::msg::Pose& target, const std::string& end_effector_link)
1770{
1771 std::vector<geometry_msgs::msg::PoseStamped> pose_msg(1);
1772 pose_msg[0].pose = target;
1773 pose_msg[0].header.frame_id = getPoseReferenceFrame();
1774 pose_msg[0].header.stamp = impl_->getClock()->now();
1775 return setPoseTargets(pose_msg, end_effector_link);
1776}
1777
1778bool MoveGroupInterface::setPoseTarget(const geometry_msgs::msg::PoseStamped& target,
1779 const std::string& end_effector_link)
1780{
1781 std::vector<geometry_msgs::msg::PoseStamped> targets(1, target);
1782 return setPoseTargets(targets, end_effector_link);
1783}
1784
1785bool MoveGroupInterface::setPoseTargets(const EigenSTL::vector_Isometry3d& target, const std::string& end_effector_link)
1786{
1787 std::vector<geometry_msgs::msg::PoseStamped> pose_out(target.size());
1788 rclcpp::Time tm = impl_->getClock()->now();
1789 const std::string& frame_id = getPoseReferenceFrame();
1790 for (std::size_t i = 0; i < target.size(); ++i)
1791 {
1792 pose_out[i].pose = tf2::toMsg(target[i]);
1793 pose_out[i].header.stamp = tm;
1794 pose_out[i].header.frame_id = frame_id;
1795 }
1796 return setPoseTargets(pose_out, end_effector_link);
1797}
1798
1799bool MoveGroupInterface::setPoseTargets(const std::vector<geometry_msgs::msg::Pose>& target,
1800 const std::string& end_effector_link)
1801{
1802 std::vector<geometry_msgs::msg::PoseStamped> target_stamped(target.size());
1803 rclcpp::Time tm = impl_->getClock()->now();
1804 const std::string& frame_id = getPoseReferenceFrame();
1805 for (std::size_t i = 0; i < target.size(); ++i)
1806 {
1807 target_stamped[i].pose = target[i];
1808 target_stamped[i].header.stamp = tm;
1809 target_stamped[i].header.frame_id = frame_id;
1810 }
1811 return setPoseTargets(target_stamped, end_effector_link);
1812}
1813
1814bool MoveGroupInterface::setPoseTargets(const std::vector<geometry_msgs::msg::PoseStamped>& target,
1815 const std::string& end_effector_link)
1816{
1817 if (target.empty())
1818 {
1819 RCLCPP_ERROR(logger_, "No pose specified as goal target");
1820 return false;
1821 }
1822 else
1823 {
1824 impl_->setTargetType(POSE);
1825 return impl_->setPoseTargets(target, end_effector_link);
1826 }
1827}
1828
1829const geometry_msgs::msg::PoseStamped& MoveGroupInterface::getPoseTarget(const std::string& end_effector_link) const
1830{
1831 return impl_->getPoseTarget(end_effector_link);
1832}
1833
1834const std::vector<geometry_msgs::msg::PoseStamped>&
1835MoveGroupInterface::getPoseTargets(const std::string& end_effector_link) const
1836{
1837 return impl_->getPoseTargets(end_effector_link);
1838}
1839
1840namespace
1841{
1842inline void transformPose(const tf2_ros::Buffer& tf_buffer, const std::string& desired_frame,
1843 geometry_msgs::msg::PoseStamped& target)
1844{
1845 if (desired_frame != target.header.frame_id)
1846 {
1847 geometry_msgs::msg::PoseStamped target_in(target);
1848 tf_buffer.transform(target_in, target, desired_frame);
1849 // we leave the stamp to ros::Time(0) on purpose
1850 target.header.stamp = rclcpp::Time(0);
1851 }
1852}
1853} // namespace
1854
1855bool MoveGroupInterface::setPositionTarget(double x, double y, double z, const std::string& end_effector_link)
1856{
1857 geometry_msgs::msg::PoseStamped target;
1858 if (impl_->hasPoseTarget(end_effector_link))
1859 {
1860 target = getPoseTarget(end_effector_link);
1861 transformPose(*impl_->getTF(), impl_->getPoseReferenceFrame(), target);
1862 }
1863 else
1864 {
1865 target.pose.orientation.x = 0.0;
1866 target.pose.orientation.y = 0.0;
1867 target.pose.orientation.z = 0.0;
1868 target.pose.orientation.w = 1.0;
1869 target.header.frame_id = impl_->getPoseReferenceFrame();
1870 }
1871
1872 target.pose.position.x = x;
1873 target.pose.position.y = y;
1874 target.pose.position.z = z;
1875 bool result = setPoseTarget(target, end_effector_link);
1876 impl_->setTargetType(POSITION);
1877 return result;
1878}
1879
1880bool MoveGroupInterface::setRPYTarget(double r, double p, double y, const std::string& end_effector_link)
1881{
1882 geometry_msgs::msg::PoseStamped target;
1883 if (impl_->hasPoseTarget(end_effector_link))
1884 {
1885 target = getPoseTarget(end_effector_link);
1886 transformPose(*impl_->getTF(), impl_->getPoseReferenceFrame(), target);
1887 }
1888 else
1889 {
1890 target.pose.position.x = 0.0;
1891 target.pose.position.y = 0.0;
1892 target.pose.position.z = 0.0;
1893 target.header.frame_id = impl_->getPoseReferenceFrame();
1894 }
1895 tf2::Quaternion q;
1896 q.setRPY(r, p, y);
1897 target.pose.orientation = tf2::toMsg(q);
1898 bool result = setPoseTarget(target, end_effector_link);
1899 impl_->setTargetType(ORIENTATION);
1900 return result;
1901}
1902
1903bool MoveGroupInterface::setOrientationTarget(double x, double y, double z, double w,
1904 const std::string& end_effector_link)
1905{
1906 geometry_msgs::msg::PoseStamped target;
1907 if (impl_->hasPoseTarget(end_effector_link))
1908 {
1909 target = getPoseTarget(end_effector_link);
1910 transformPose(*impl_->getTF(), impl_->getPoseReferenceFrame(), target);
1911 }
1912 else
1913 {
1914 target.pose.position.x = 0.0;
1915 target.pose.position.y = 0.0;
1916 target.pose.position.z = 0.0;
1917 target.header.frame_id = impl_->getPoseReferenceFrame();
1918 }
1919
1920 target.pose.orientation.x = x;
1921 target.pose.orientation.y = y;
1922 target.pose.orientation.z = z;
1923 target.pose.orientation.w = w;
1924 bool result = setPoseTarget(target, end_effector_link);
1925 impl_->setTargetType(ORIENTATION);
1926 return result;
1927}
1928
1929void MoveGroupInterface::setPoseReferenceFrame(const std::string& pose_reference_frame)
1930{
1931 impl_->setPoseReferenceFrame(pose_reference_frame);
1932}
1933
1935{
1936 return impl_->getPoseReferenceFrame();
1937}
1938
1940{
1941 return impl_->getGoalJointTolerance();
1942}
1943
1945{
1946 return impl_->getGoalPositionTolerance();
1947}
1948
1950{
1951 return impl_->getGoalOrientationTolerance();
1952}
1953
1955{
1956 setGoalJointTolerance(tolerance);
1957 setGoalPositionTolerance(tolerance);
1958 setGoalOrientationTolerance(tolerance);
1959}
1960
1962{
1963 impl_->setGoalJointTolerance(tolerance);
1964}
1965
1967{
1968 impl_->setGoalPositionTolerance(tolerance);
1969}
1970
1972{
1973 impl_->setGoalOrientationTolerance(tolerance);
1974}
1975
1976void MoveGroupInterface::rememberJointValues(const std::string& name)
1977{
1979}
1980
1982{
1983 return impl_->startStateMonitor(wait);
1984}
1985
1987{
1988 moveit::core::RobotStatePtr current_state;
1989 std::vector<double> values;
1990 if (impl_->getCurrentState(current_state))
1991 current_state->copyJointGroupPositions(getName(), values);
1992 return values;
1993}
1994
1996{
1997 std::vector<double> r;
1998 impl_->getJointModelGroup()->getVariableRandomPositions(impl_->getTargetRobotState().getRandomNumberGenerator(), r);
1999 return r;
2000}
2001
2002geometry_msgs::msg::PoseStamped MoveGroupInterface::getRandomPose(const std::string& end_effector_link) const
2003{
2004 const std::string& eef = end_effector_link.empty() ? getEndEffectorLink() : end_effector_link;
2005 Eigen::Isometry3d pose;
2006 pose.setIdentity();
2007 if (eef.empty())
2008 {
2009 RCLCPP_ERROR(logger_, "No end-effector specified");
2010 }
2011 else
2012 {
2013 moveit::core::RobotStatePtr current_state;
2014 if (impl_->getCurrentState(current_state))
2015 {
2016 current_state->setToRandomPositions(impl_->getJointModelGroup());
2017 const moveit::core::LinkModel* lm = current_state->getLinkModel(eef);
2018 if (lm)
2019 pose = current_state->getGlobalLinkTransform(lm);
2020 }
2021 }
2022 geometry_msgs::msg::PoseStamped pose_msg;
2023 pose_msg.header.stamp = impl_->getClock()->now();
2024 pose_msg.header.frame_id = impl_->getRobotModel()->getModelFrame();
2025 pose_msg.pose = tf2::toMsg(pose);
2026 return pose_msg;
2027}
2028
2029geometry_msgs::msg::PoseStamped MoveGroupInterface::getCurrentPose(const std::string& end_effector_link) const
2030{
2031 const std::string& eef = end_effector_link.empty() ? getEndEffectorLink() : end_effector_link;
2032 Eigen::Isometry3d pose;
2033 pose.setIdentity();
2034 if (eef.empty())
2035 {
2036 RCLCPP_ERROR(logger_, "No end-effector specified");
2037 }
2038 else
2039 {
2040 moveit::core::RobotStatePtr current_state;
2041 if (impl_->getCurrentState(current_state))
2042 {
2043 const moveit::core::LinkModel* lm = current_state->getLinkModel(eef);
2044 if (lm)
2045 pose = current_state->getGlobalLinkTransform(lm);
2046 }
2047 }
2048 geometry_msgs::msg::PoseStamped pose_msg;
2049 pose_msg.header.stamp = impl_->getClock()->now();
2050 pose_msg.header.frame_id = impl_->getRobotModel()->getModelFrame();
2051 pose_msg.pose = tf2::toMsg(pose);
2052 return pose_msg;
2053}
2054
2055std::vector<double> MoveGroupInterface::getCurrentRPY(const std::string& end_effector_link) const
2056{
2057 std::vector<double> result;
2058 const std::string& eef = end_effector_link.empty() ? getEndEffectorLink() : end_effector_link;
2059 if (eef.empty())
2060 {
2061 RCLCPP_ERROR(logger_, "No end-effector specified");
2062 }
2063 else
2064 {
2065 moveit::core::RobotStatePtr current_state;
2066 if (impl_->getCurrentState(current_state))
2067 {
2068 const moveit::core::LinkModel* lm = current_state->getLinkModel(eef);
2069 if (lm)
2070 {
2071 result.resize(3);
2072 geometry_msgs::msg::TransformStamped tfs = tf2::eigenToTransform(current_state->getGlobalLinkTransform(lm));
2073 double pitch, roll, yaw;
2074 tf2::getEulerYPR<geometry_msgs::msg::Quaternion>(tfs.transform.rotation, yaw, pitch, roll);
2075 result[0] = roll;
2076 result[1] = pitch;
2077 result[2] = yaw;
2078 }
2079 }
2080 }
2081 return result;
2082}
2083
2084const std::vector<std::string>& MoveGroupInterface::getActiveJoints() const
2085{
2086 return impl_->getJointModelGroup()->getActiveJointModelNames();
2087}
2088
2089const std::vector<std::string>& MoveGroupInterface::getJoints() const
2090{
2091 return impl_->getJointModelGroup()->getJointModelNames();
2092}
2093
2095{
2096 return impl_->getJointModelGroup()->getVariableCount();
2097}
2098
2099moveit::core::RobotStatePtr MoveGroupInterface::getCurrentState(double wait) const
2100{
2101 moveit::core::RobotStatePtr current_state;
2102 impl_->getCurrentState(current_state, wait);
2103 return current_state;
2104}
2105
2106void MoveGroupInterface::rememberJointValues(const std::string& name, const std::vector<double>& values)
2107{
2108 remembered_joint_values_[name] = values;
2109}
2110
2111void MoveGroupInterface::forgetJointValues(const std::string& name)
2112{
2113 remembered_joint_values_.erase(name);
2114}
2115
2117{
2118 impl_->can_look_ = flag;
2119 RCLCPP_DEBUG(logger_, "Looking around: %s", flag ? "yes" : "no");
2120}
2121
2123{
2124 if (attempts < 0)
2125 {
2126 RCLCPP_ERROR(logger_, "Tried to set negative number of look-around attempts");
2127 }
2128 else
2129 {
2130 RCLCPP_DEBUG_STREAM(logger_, "Look around attempts: " << attempts);
2131 impl_->look_around_attempts_ = attempts;
2132 }
2133}
2134
2136{
2137 impl_->can_replan_ = flag;
2138 RCLCPP_DEBUG(logger_, "Replanning: %s", flag ? "yes" : "no");
2139}
2140
2142{
2143 if (attempts < 0)
2144 {
2145 RCLCPP_ERROR(logger_, "Tried to set negative number of replan attempts");
2146 }
2147 else
2148 {
2149 RCLCPP_DEBUG_STREAM(logger_, "Replan Attempts: " << attempts);
2150 impl_->replan_attempts_ = attempts;
2151 }
2152}
2153
2155{
2156 if (delay < 0.0)
2157 {
2158 RCLCPP_ERROR(logger_, "Tried to set negative replan delay");
2159 }
2160 else
2161 {
2162 RCLCPP_DEBUG_STREAM(logger_, "Replan Delay: " << delay);
2163 impl_->replan_delay_ = delay;
2164 }
2165}
2166
2167std::vector<std::string> MoveGroupInterface::getKnownConstraints() const
2168{
2169 return impl_->getKnownConstraints();
2170}
2171
2172moveit_msgs::msg::Constraints MoveGroupInterface::getPathConstraints() const
2173{
2174 return impl_->getPathConstraints();
2175}
2176
2177bool MoveGroupInterface::setPathConstraints(const std::string& constraint)
2178{
2179 return impl_->setPathConstraints(constraint);
2180}
2181
2182void MoveGroupInterface::setPathConstraints(const moveit_msgs::msg::Constraints& constraint)
2183{
2184 impl_->setPathConstraints(constraint);
2185}
2186
2188{
2189 impl_->clearPathConstraints();
2190}
2191
2192moveit_msgs::msg::TrajectoryConstraints MoveGroupInterface::getTrajectoryConstraints() const
2193{
2194 return impl_->getTrajectoryConstraints();
2195}
2196
2197void MoveGroupInterface::setTrajectoryConstraints(const moveit_msgs::msg::TrajectoryConstraints& constraint)
2198{
2199 impl_->setTrajectoryConstraints(constraint);
2200}
2201
2203{
2204 impl_->clearTrajectoryConstraints();
2205}
2206
2207void MoveGroupInterface::setConstraintsDatabase(const std::string& host, unsigned int port)
2208{
2209 impl_->initializeConstraintsStorage(host, port);
2210}
2211
2212void MoveGroupInterface::setWorkspace(double minx, double miny, double minz, double maxx, double maxy, double maxz)
2213{
2214 impl_->setWorkspace(minx, miny, minz, maxx, maxy, maxz);
2215}
2216
2219{
2220 impl_->setPlanningTime(seconds);
2221}
2222
2225{
2226 return impl_->getPlanningTime();
2227}
2228
2229const rclcpp::Node::SharedPtr& MoveGroupInterface::getNode() const
2230{
2231 return impl_->node_;
2232}
2233
2235{
2236 return impl_->getRobotModel()->getModelFrame();
2237}
2238
2239const std::vector<std::string>& MoveGroupInterface::getJointModelGroupNames() const
2240{
2241 return impl_->getRobotModel()->getJointModelGroupNames();
2242}
2243
2244bool MoveGroupInterface::attachObject(const std::string& object, const std::string& link)
2245{
2246 return attachObject(object, link, std::vector<std::string>());
2247}
2248
2249bool MoveGroupInterface::attachObject(const std::string& object, const std::string& link,
2250 const std::vector<std::string>& touch_links)
2251{
2252 return impl_->attachObject(object, link, touch_links);
2253}
2254
2255bool MoveGroupInterface::detachObject(const std::string& name)
2256{
2257 return impl_->detachObject(name);
2258}
2259
2260void MoveGroupInterface::constructRobotState(moveit_msgs::msg::RobotState& state)
2261{
2262 impl_->constructRobotState(state);
2263}
2264
2265void MoveGroupInterface::constructMotionPlanRequest(moveit_msgs::msg::MotionPlanRequest& goal_out)
2266{
2267 impl_->constructMotionPlanRequest(goal_out);
2268}
2269
2270} // namespace planning_interface
2271} // namespace moveit
const std::pair< std::string, std::string > & getEndEffectorParentGroup() const
Get the name of the group this end-effector attaches to (first) and the name of the link in that grou...
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
std::size_t getVariableCount() const
Get the number of variables that describe this joint.
A link from the robot. Contains the constant transform applied to the link and its geometry.
a wrapper around moveit_msgs::MoveItErrorCodes to make it easier to return an error code message from...
Representation of a robot's state. This includes position, velocity, acceleration and effort.
const Eigen::Isometry3d & getFrameTransform(const std::string &frame_id, bool *frame_found=nullptr)
Get the transformation matrix from the model frame (root of model) to the frame identified by frame_i...
bool satisfiesBounds(double margin=0.0) const
bool setFromIK(const JointModelGroup *group, const geometry_msgs::msg::Pose &pose, double timeout=0.0, const GroupStateValidityCallbackFn &constraint=GroupStateValidityCallbackFn(), const kinematics::KinematicsQueryOptions &options=kinematics::KinematicsQueryOptions(), const kinematics::KinematicsBase::IKCostFn &cost_function=kinematics::KinematicsBase::IKCostFn())
If the group this state corresponds to is a chain and a solver is available, then the joint values ca...
static bool sameFrame(const std::string &frame1, const std::string &frame2)
Check if two frames end up being the same once the missing / are added as prefix (if they are missing...
rclcpp_action::Client< moveit_msgs::action::MoveGroup > & getMoveGroupClient() const
void constructGoal(moveit_msgs::action::MoveGroup::Goal &goal) const
void setMaxScalingFactor(double &variable, const double target_value, const char *factor_name, double fallback_value)
bool getCurrentState(moveit::core::RobotStatePtr &current_state, double wait_seconds=1.0)
bool attachObject(const std::string &object, const std::string &link, const std::vector< std::string > &touch_links)
std::map< std::string, std::string > getPlannerParams(const std::string &planner_id, const std::string &group="")
void initializeConstraintsStorage(const std::string &host, unsigned int port)
void setPathConstraints(const moveit_msgs::msg::Constraints &constraint)
double computeCartesianPath(const std::vector< geometry_msgs::msg::Pose > &waypoints, double step, moveit_msgs::msg::RobotTrajectory &msg, const moveit_msgs::msg::Constraints &path_constraints, bool avoid_collisions, moveit_msgs::msg::MoveItErrorCodes &error_code)
void setTrajectoryConstraints(const moveit_msgs::msg::TrajectoryConstraints &constraint)
void constructMotionPlanRequest(moveit_msgs::msg::MotionPlanRequest &request) const
MoveGroupInterfaceImpl(const rclcpp::Node::SharedPtr &node, const Options &opt, const std::shared_ptr< tf2_ros::Buffer > &tf_buffer, const rclcpp::Duration &wait_for_servers)
bool setPoseTargets(const std::vector< geometry_msgs::msg::PoseStamped > &poses, const std::string &end_effector_link)
const geometry_msgs::msg::PoseStamped & getPoseTarget(const std::string &end_effector_link) const
moveit::core::MoveItErrorCode execute(const moveit_msgs::msg::RobotTrajectory &trajectory, bool wait, const std::vector< std::string > &controllers=std::vector< std::string >())
bool getInterfaceDescription(moveit_msgs::msg::PlannerInterfaceDescription &desc)
void setStartState(const moveit_msgs::msg::RobotState &start_state)
const std::vector< geometry_msgs::msg::PoseStamped > & getPoseTargets(const std::string &end_effector_link) const
bool setJointValueTarget(const geometry_msgs::msg::Pose &eef_pose, const std::string &end_effector_link, const std::string &frame, bool approx)
void setPlannerParams(const std::string &planner_id, const std::string &group, const std::map< std::string, std::string > &params, bool replace=false)
bool getInterfaceDescriptions(std::vector< moveit_msgs::msg::PlannerInterfaceDescription > &desc)
void setWorkspace(double minx, double miny, double minz, double maxx, double maxy, double maxz)
std::vector< double > getRandomJointValues() const
Get random joint values for the joints planned for by this instance (see getJoints()).
double computeCartesianPath(const std::vector< geometry_msgs::msg::Pose > &waypoints, double eef_step, double, moveit_msgs::msg::RobotTrajectory &trajectory, bool avoid_collisions=true, moveit_msgs::msg::MoveItErrorCodes *error_code=nullptr)
Compute a Cartesian path that follows specified waypoints with a step size of at most eef_step meters...
void setMaxVelocityScalingFactor(double max_velocity_scaling_factor)
Set a scaling factor for optionally reducing the maximum joint velocity. Allowed values are in (0,...
const std::string & getEndEffectorLink() const
Get the current end-effector link. This returns the value set by setEndEffectorLink() (or indirectly ...
static const std::string ROBOT_DESCRIPTION
Default ROS parameter name from where to read the robot's URDF. Set to 'robot_description'.
const std::vector< std::string > & getNamedTargets() const
Get the names of the named robot states available as targets, both either remembered states or defaul...
std::map< std::string, std::string > getPlannerParams(const std::string &planner_id, const std::string &group="") const
Get the planner parameters for given group and planner_id.
void stop()
Stop any trajectory execution, if one is active.
MoveGroupInterface(const rclcpp::Node::SharedPtr &node, const Options &opt, const std::shared_ptr< tf2_ros::Buffer > &tf_buffer=std::shared_ptr< tf2_ros::Buffer >(), const rclcpp::Duration &wait_for_servers=rclcpp::Duration::from_seconds(-1))
Construct a MoveGroupInterface instance call using a specified set of options opt.
const std::string & getPlannerId() const
Get the current planner_id.
void setReplanDelay(double delay)
Sleep this duration between replanning attempts (in walltime seconds).
MoveGroupInterface & operator=(const MoveGroupInterface &)=delete
moveit::core::MoveItErrorCode plan(Plan &plan)
Compute a motion plan that takes the group declared in the constructor from the current state to the ...
void setGoalTolerance(double tolerance)
Set the tolerance that is used for reaching the goal. For joint state goals, this will be distance fo...
void setGoalPositionTolerance(double tolerance)
Set the position tolerance that is used for reaching the goal when moving to a pose.
const std::string & getPlanningFrame() const
Get the name of the frame in which the robot is planning.
bool setPoseTargets(const EigenSTL::vector_Isometry3d &end_effector_pose, const std::string &end_effector_link="")
Set goal poses for end_effector_link.
bool setPoseTarget(const Eigen::Isometry3d &end_effector_pose, const std::string &end_effector_link="")
Set the goal pose of the end-effector end_effector_link.
moveit::core::MoveItErrorCode asyncMove()
Plan and execute a trajectory that takes the group of joints declared in the constructor to the speci...
void setPlanningPipelineId(const std::string &pipeline_id)
Specify a planning pipeline to be used for further planning.
double getGoalJointTolerance() const
Get the tolerance that is used for reaching a joint goal. This is distance for each joint in configur...
bool setEndEffectorLink(const std::string &end_effector_link)
Specify the parent link of the end-effector. This end_effector_link will be used in calls to pose tar...
void setStartStateToCurrentState()
Set the starting state for planning to be that reported by the robot's joint state publication.
bool getInterfaceDescriptions(std::vector< moveit_msgs::msg::PlannerInterfaceDescription > &desc) const
Get the descriptions of all planning plugins loaded by the action server.
void setMaxAccelerationScalingFactor(double max_acceleration_scaling_factor)
Set a scaling factor for optionally reducing the maximum joint acceleration. Allowed values are in (0...
bool setPositionTarget(double x, double y, double z, const std::string &end_effector_link="")
Set the goal position of the end-effector end_effector_link to be (x, y, z).
const std::string & getEndEffector() const
Get the current end-effector name. This returns the value set by setEndEffector() (or indirectly by s...
void clearPathConstraints()
Specify that no path constraints are to be used. This removes any path constraints set in previous ca...
bool attachObject(const std::string &object, const std::string &link="")
Given the name of an object in the planning scene, make the object attached to a link of the robot....
moveit_msgs::msg::Constraints getPathConstraints() const
Get the actual set of constraints in use with this MoveGroupInterface.
void setNumPlanningAttempts(unsigned int num_planning_attempts)
Set the number of times the motion plan is to be computed from scratch before the shortest solution i...
rclcpp_action::Client< moveit_msgs::action::MoveGroup > & getMoveGroupClient() const
Get the move_group action client used by the MoveGroupInterface. The client can be used for querying ...
std::vector< double > getCurrentJointValues() const
Get the current joint values for the joints planned for by this instance (see getJoints()).
bool setNamedTarget(const std::string &name)
Set the current joint values to be ones previously remembered by rememberJointValues() or,...
const std::vector< std::string > & getJointNames() const
Get vector of names of joints available in move group.
moveit::core::MoveItErrorCode move()
Plan and execute a trajectory that takes the group of joints declared in the constructor to the speci...
void setReplanAttempts(int32_t attempts)
Maximum number of replanning attempts.
void allowReplanning(bool flag)
Specify whether the robot is allowed to replan if it detects changes in the environment.
moveit::core::RobotModelConstPtr getRobotModel() const
Get the RobotModel object.
moveit::core::MoveItErrorCode execute(const Plan &plan, const std::vector< std::string > &controllers=std::vector< std::string >())
Given a plan, execute it while waiting for completion.
void constructMotionPlanRequest(moveit_msgs::msg::MotionPlanRequest &request)
Build the MotionPlanRequest that would be sent to the move_group action with plan() or move() and sto...
bool setOrientationTarget(double x, double y, double z, double w, const std::string &end_effector_link="")
Set the goal orientation of the end-effector end_effector_link to be the quaternion (x,...
bool setJointValueTarget(const std::vector< double > &group_variable_values)
Set the JointValueTarget and use it for future planning requests.
const rclcpp::Node::SharedPtr & getNode() const
Get the ROS node handle of this instance operates on.
bool setRPYTarget(double roll, double pitch, double yaw, const std::string &end_effector_link="")
Set the goal orientation of the end-effector end_effector_link to be (roll,pitch,yaw) radians.
void setGoalOrientationTolerance(double tolerance)
Set the orientation tolerance that is used for reaching the goal when moving to a pose.
void clearPoseTarget(const std::string &end_effector_link="")
Forget pose(s) specified for end_effector_link.
const geometry_msgs::msg::PoseStamped & getPoseTarget(const std::string &end_effector_link="") const
void setGoalJointTolerance(double tolerance)
Set the joint tolerance (for each joint) that is used for reaching the goal when moving to a joint va...
std::string getDefaultPlannerId(const std::string &group="") const
Get the default planner of the current planning pipeline for the given group (or the pipeline's defau...
void setRandomTarget()
Set the joint state goal to a random joint configuration.
moveit::core::RobotStatePtr getCurrentState(double wait=1) const
Get the current state of the robot within the duration specified by wait.
void getJointValueTarget(std::vector< double > &group_variable_values) const
Get the current joint state goal in a form compatible to setJointValueTarget().
const std::vector< std::string > & getActiveJoints() const
Get only the active (actuated) joints this instance operates on.
void rememberJointValues(const std::string &name)
Remember the current joint values (of the robot being monitored) under name. These can be used by set...
void setLookAroundAttempts(int32_t attempts)
How often is the system allowed to move the camera to update environment model when looking.
bool getInterfaceDescription(moveit_msgs::msg::PlannerInterfaceDescription &desc) const
Get the description of the default planning plugin loaded by the action server.
const std::string & getName() const
Get the name of the group this instance operates on.
moveit::core::MoveItErrorCode asyncExecute(const Plan &plan, const std::vector< std::string > &controllers=std::vector< std::string >())
Given a plan, execute it without waiting for completion.
const std::vector< std::string > & getJoints() const
Get all the joints this instance operates on (including fixed joints).
bool detachObject(const std::string &name="")
Detach an object. name specifies the name of the object attached to this group, or the name of the li...
void setPoseReferenceFrame(const std::string &pose_reference_frame)
Specify which reference frame to assume for poses specified without a reference frame.
const std::shared_ptr< tf2_ros::Buffer > & getTF() const
Get the tf2_ros::Buffer.
const std::vector< geometry_msgs::msg::PoseStamped > & getPoseTargets(const std::string &end_effector_link="") const
double getMaxVelocityScalingFactor() const
Get the max velocity scaling factor set by setMaxVelocityScalingFactor().
moveit_msgs::msg::TrajectoryConstraints getTrajectoryConstraints() const
const std::vector< std::string > & getLinkNames() const
Get vector of names of links available in move group.
double getMaxAccelerationScalingFactor() const
Get the max acceleration scaling factor set by setMaxAccelerationScalingFactor().
void setStartState(const moveit_msgs::msg::RobotState &start_state)
If a different start state should be considered instead of the current state of the robot,...
bool setPathConstraints(const std::string &constraint)
Specify a set of path constraints to use. The constraints are looked up by name from the Mongo databa...
void clearPoseTargets()
Forget any poses specified for all end-effectors.
void setPlannerId(const std::string &planner_id)
Specify a planner to be used for further planning.
bool setEndEffector(const std::string &eef_name)
Specify the name of the end-effector to use. This is equivalent to setting the EndEffectorLink to the...
const std::string & getPoseReferenceFrame() const
Get the reference frame set by setPoseReferenceFrame(). By default this is the reference frame of the...
const std::string & getPlanningPipelineId() const
Get the current planning_pipeline_id.
void setConstraintsDatabase(const std::string &host, unsigned int port)
Specify where the database server that holds known constraints resides.
std::vector< double > getCurrentRPY(const std::string &end_effector_link="") const
Get the roll-pitch-yaw (XYZ) for the end-effector end_effector_link. If end_effector_link is empty (t...
void forgetJointValues(const std::string &name)
Forget the joint values remembered under name.
std::vector< std::string > getKnownConstraints() const
Get the names of the known constraints as read from the Mongo database, if a connection was achieved.
void setTrajectoryConstraints(const moveit_msgs::msg::TrajectoryConstraints &constraint)
const moveit::core::RobotState & getTargetRobotState() const
geometry_msgs::msg::PoseStamped getRandomPose(const std::string &end_effector_link="") const
Get a random reachable pose for the end-effector end_effector_link. If end_effector_link is empty (th...
double getGoalOrientationTolerance() const
Get the tolerance that is used for reaching an orientation goal. This is the tolerance for roll,...
void allowLooking(bool flag)
Specify whether the robot is allowed to look around before moving if it determines it should (default...
std::map< std::string, double > getNamedTargetValues(const std::string &name) const
Get the joint angles for targets specified by name.
geometry_msgs::msg::PoseStamped getCurrentPose(const std::string &end_effector_link="") const
Get the pose for the end-effector end_effector_link. If end_effector_link is empty (the default value...
bool startStateMonitor(double wait=1.0)
When reasoning about the current state of a robot, a CurrentStateMonitor instance is automatically co...
unsigned int getVariableCount() const
Get the number of variables used to describe the state of this group. This is larger or equal to the ...
double getGoalPositionTolerance() const
Get the tolerance that is used for reaching a position goal. This is be the radius of a sphere where ...
double getPlanningTime() const
Get the number of seconds set by setPlanningTime().
void setPlanningTime(double seconds)
Specify the maximum amount of time to use when planning.
bool setApproximateJointValueTarget(const geometry_msgs::msg::Pose &eef_pose, const std::string &end_effector_link="")
Set the joint state goal for a particular joint by computing IK.
void constructRobotState(moveit_msgs::msg::RobotState &state)
Build a RobotState message for use with plan() or computeCartesianPath() If the move_group has a cust...
void setPlannerParams(const std::string &planner_id, const std::string &group, const std::map< std::string, std::string > &params, bool bReplace=false)
Set the planner parameters for given group and planner_id.
void setWorkspace(double minx, double miny, double minz, double maxx, double maxy, double maxz)
Specify the workspace bounding box. The box is specified in the planning frame (i....
const std::vector< std::string > & getJointModelGroupNames() const
Get the available planning group names.
static const std::string DEFAULT_ATTACHED_COLLISION_OBJECT_TOPIC
The name of the topic used by default for attached collision objects.
moveit_msgs::msg::Constraints constructGoalConstraints(const moveit::core::RobotState &state, const moveit::core::JointModelGroup *jmg, double tolerance_below, double tolerance_above)
Generates a constraint message intended to be used as a goal constraint for a joint group....
Definition utils.cpp:152
moveit_msgs::msg::Constraints mergeConstraints(const moveit_msgs::msg::Constraints &first, const moveit_msgs::msg::Constraints &second)
Merge two sets of constraints into one.
Definition utils.cpp:64
void robotStateToRobotStateMsg(const RobotState &state, moveit_msgs::msg::RobotState &robot_state, bool copy_attached_bodies=true)
Convert a MoveIt robot state to a robot state message.
std::function< bool(RobotState *robot_state, const JointModelGroup *joint_group, const double *joint_group_variable_values)> GroupStateValidityCallbackFn
Signature for functions that can verify that if the group joint_group in robot_state is set to joint_...
bool robotStateMsgToRobotState(const Transforms &tf, const moveit_msgs::msg::RobotState &robot_state, RobotState &state, bool copy_attached_bodies=true)
Convert a robot state msg (with accompanying extra transforms) to a MoveIt robot state.
Simple interface to MoveIt components.
moveit::core::RobotModelConstPtr getSharedRobotModel(const rclcpp::Node::SharedPtr &node, const std::string &robot_description)
std::shared_ptr< tf2_ros::Buffer > getSharedTF()
planning_scene_monitor::CurrentStateMonitorPtr getSharedStateMonitor(const rclcpp::Node::SharedPtr &node, const moveit::core::RobotModelConstPtr &robot_model, const std::shared_ptr< tf2_ros::Buffer > &tf_buffer)
getSharedStateMonitor
warehouse_ros::DatabaseConnection::Ptr loadDatabase(const rclcpp::Node::SharedPtr &node)
Load a database connection.
warehouse_ros::MessageWithMetadata< moveit_msgs::msg::Constraints >::ConstPtr ConstraintsWithMetadata
Main namespace for MoveIt.
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)
A set of options for the kinematics solver.
Specification of options to use when constructing the MoveGroupInterface class.
std::string robot_description
The robot description parameter name (if different from default).
moveit::core::RobotModelConstPtr robot_model
Optionally, an instance of the RobotModel to use can be also specified.
std::string group_name
The group to construct the class instance for.
The representation of a motion plan (as ROS messages).