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