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