moveit2
The MoveIt Motion Planning Framework for ROS 2.
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>
60 #include <moveit/utils/logger.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 
70 namespace moveit
71 {
72 namespace planning_interface
73 {
74 const std::string MoveGroupInterface::ROBOT_DESCRIPTION =
75  "robot_description"; // name of the robot description (a param name, so it can be changed externally)
76 
77 const std::string GRASP_PLANNING_SERVICE_NAME = "plan_grasps"; // name of the service that can be used to plan grasps
78 
79 namespace
80 {
81 enum ActiveTargetType
82 {
83  JOINT,
84  POSE,
85  POSITION,
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
93 auto qosDefault()
94 {
95  return rclcpp::SystemDefaultsQoS();
96 }
97 #else // Humble
98 auto qosDefault()
99 {
100  return rmw_qos_profile_services_default;
101 }
102 #endif
103 
104 } // namespace
105 
107 {
108  friend MoveGroupInterface;
109 
110 public:
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("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 
299  std::string getDefaultPlanningPipelineId() const
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 
357  void setMaxVelocityScalingFactor(double value)
358  {
359  setMaxScalingFactor(max_velocity_scaling_factor_, value, "velocity_scaling_factor", 0.1);
360  }
361 
363  {
364  setMaxScalingFactor(max_acceleration_scaling_factor_, value, "acceleration_scaling_factor", 0.1);
365  }
366 
367  void setMaxScalingFactor(double& variable, const double target_value, const char* factor_name, double fallback_value)
368  {
369  if (target_value > 1.0)
370  {
371  RCLCPP_WARN(logger_, "Limiting max_%s (%.2f) to 1.0.", factor_name, target_value);
372  variable = 1.0;
373  }
374  else if (target_value <= 0.0)
375  {
376  node_->get_parameter_or<double>(std::string("robot_description_planning.default_") + factor_name, variable,
377  fallback_value);
378  if (target_value < 0.0)
379  {
380  RCLCPP_WARN(logger_, "max_%s < 0.0! Setting to default: %.2f.", factor_name, variable);
381  }
382  }
383  else
384  {
385  variable = target_value;
386  }
387  }
388 
390  {
391  return *joint_state_target_;
392  }
393 
395  {
396  return *joint_state_target_;
397  }
398 
399  void setStartState(const moveit::core::RobotState& start_state)
400  {
401  considered_start_state_ = std::make_shared<moveit::core::RobotState>(start_state);
402  }
403 
405  {
406  considered_start_state_.reset();
407  }
408 
409  moveit::core::RobotStatePtr getStartState()
410  {
411  if (considered_start_state_)
412  {
413  return considered_start_state_;
414  }
415  else
416  {
417  moveit::core::RobotStatePtr s;
418  getCurrentState(s);
419  return s;
420  }
421  }
422 
423  bool setJointValueTarget(const geometry_msgs::msg::Pose& eef_pose, const std::string& end_effector_link,
424  const std::string& frame, bool approx)
425  {
426  const std::string& eef = end_effector_link.empty() ? getEndEffectorLink() : end_effector_link;
427  // this only works if we have an end-effector
428  if (!eef.empty())
429  {
430  // first we set the goal to be the same as the start state
431  moveit::core::RobotStatePtr c = getStartState();
432  if (c)
433  {
435  c->enforceBounds();
436  getTargetRobotState() = *c;
437  if (!getTargetRobotState().satisfiesBounds(getGoalJointTolerance()))
438  return false;
439  }
440  else
441  return false;
442 
443  // we may need to do approximate IK
445  o.return_approximate_solution = approx;
446 
447  // if no frame transforms are needed, call IK directly
448  if (frame.empty() || moveit::core::Transforms::sameFrame(frame, getRobotModel()->getModelFrame()))
449  {
450  return getTargetRobotState().setFromIK(getJointModelGroup(), eef_pose, eef, 0.0,
452  }
453  else
454  {
455  // transform the pose into the model frame, then do IK
456  bool frame_found;
457  const Eigen::Isometry3d& t = getTargetRobotState().getFrameTransform(frame, &frame_found);
458  if (frame_found)
459  {
460  Eigen::Isometry3d p;
461  tf2::fromMsg(eef_pose, p);
462  return getTargetRobotState().setFromIK(getJointModelGroup(), t * p, eef, 0.0,
464  }
465  else
466  {
467  RCLCPP_ERROR(logger_, "Unable to transform from frame '%s' to frame '%s'", frame.c_str(),
468  getRobotModel()->getModelFrame().c_str());
469  return false;
470  }
471  }
472  }
473  else
474  return false;
475  }
476 
477  void setEndEffectorLink(const std::string& end_effector)
478  {
479  end_effector_link_ = end_effector;
480  }
481 
482  void clearPoseTarget(const std::string& end_effector_link)
483  {
484  pose_targets_.erase(end_effector_link);
485  }
486 
488  {
489  pose_targets_.clear();
490  }
491 
492  const std::string& getEndEffectorLink() const
493  {
494  return end_effector_link_;
495  }
496 
497  const std::string& getEndEffector() const
498  {
499  if (!end_effector_link_.empty())
500  {
501  const std::vector<std::string>& possible_eefs =
502  getRobotModel()->getJointModelGroup(opt_.group_name)->getAttachedEndEffectorNames();
503  for (const std::string& possible_eef : possible_eefs)
504  {
505  if (getRobotModel()->getEndEffector(possible_eef)->hasLinkModel(end_effector_link_))
506  return possible_eef;
507  }
508  }
509  static std::string empty;
510  return empty;
511  }
512 
513  bool setPoseTargets(const std::vector<geometry_msgs::msg::PoseStamped>& poses, const std::string& end_effector_link)
514  {
515  const std::string& eef = end_effector_link.empty() ? end_effector_link_ : end_effector_link;
516  if (eef.empty())
517  {
518  RCLCPP_ERROR(logger_, "No end-effector to set the pose for");
519  return false;
520  }
521  else
522  {
523  pose_targets_[eef] = poses;
524  // make sure we don't store an actual stamp, since that will become stale can potentially cause tf errors
525  std::vector<geometry_msgs::msg::PoseStamped>& stored_poses = pose_targets_[eef];
526  for (geometry_msgs::msg::PoseStamped& stored_pose : stored_poses)
527  stored_pose.header.stamp = rclcpp::Time(0);
528  }
529  return true;
530  }
531 
532  bool hasPoseTarget(const std::string& end_effector_link) const
533  {
534  const std::string& eef = end_effector_link.empty() ? end_effector_link_ : end_effector_link;
535  return pose_targets_.find(eef) != pose_targets_.end();
536  }
537 
538  const geometry_msgs::msg::PoseStamped& getPoseTarget(const std::string& end_effector_link) const
539  {
540  const std::string& eef = end_effector_link.empty() ? end_effector_link_ : end_effector_link;
541 
542  // if multiple pose targets are set, return the first one
543  std::map<std::string, std::vector<geometry_msgs::msg::PoseStamped>>::const_iterator jt = pose_targets_.find(eef);
544  if (jt != pose_targets_.end())
545  {
546  if (!jt->second.empty())
547  return jt->second.at(0);
548  }
549 
550  // or return an error
551  static const geometry_msgs::msg::PoseStamped UNKNOWN;
552  RCLCPP_ERROR(logger_, "Pose for end-effector '%s' not known.", eef.c_str());
553  return UNKNOWN;
554  }
555 
556  const std::vector<geometry_msgs::msg::PoseStamped>& getPoseTargets(const std::string& end_effector_link) const
557  {
558  const std::string& eef = end_effector_link.empty() ? end_effector_link_ : end_effector_link;
559 
560  std::map<std::string, std::vector<geometry_msgs::msg::PoseStamped>>::const_iterator jt = pose_targets_.find(eef);
561  if (jt != pose_targets_.end())
562  {
563  if (!jt->second.empty())
564  return jt->second;
565  }
566 
567  // or return an error
568  static const std::vector<geometry_msgs::msg::PoseStamped> EMPTY;
569  RCLCPP_ERROR(logger_, "Poses for end-effector '%s' are not known.", eef.c_str());
570  return EMPTY;
571  }
572 
573  void setPoseReferenceFrame(const std::string& pose_reference_frame)
574  {
575  pose_reference_frame_ = pose_reference_frame;
576  }
577 
578  void setSupportSurfaceName(const std::string& support_surface)
579  {
580  support_surface_ = support_surface;
581  }
582 
583  const std::string& getPoseReferenceFrame() const
584  {
585  return pose_reference_frame_;
586  }
587 
588  void setTargetType(ActiveTargetType type)
589  {
590  active_target_ = type;
591  }
592 
593  ActiveTargetType getTargetType() const
594  {
595  return active_target_;
596  }
597 
598  bool startStateMonitor(double wait)
599  {
600  if (!current_state_monitor_)
601  {
602  RCLCPP_ERROR(logger_, "Unable to monitor current robot state");
603  return false;
604  }
605 
606  // if needed, start the monitor and wait up to 1 second for a full robot state
607  if (!current_state_monitor_->isActive())
608  current_state_monitor_->startStateMonitor();
609 
610  current_state_monitor_->waitForCompleteState(opt_.group_name, wait);
611  return true;
612  }
613 
614  bool getCurrentState(moveit::core::RobotStatePtr& current_state, double wait_seconds = 1.0)
615  {
616  if (!current_state_monitor_)
617  {
618  RCLCPP_ERROR(logger_, "Unable to get current robot state");
619  return false;
620  }
621 
622  // if needed, start the monitor and wait up to 1 second for a full robot state
623  if (!current_state_monitor_->isActive())
624  current_state_monitor_->startStateMonitor();
625 
626  if (!current_state_monitor_->waitForCurrentState(node_->now(), wait_seconds))
627  {
628  RCLCPP_ERROR(logger_, "Failed to fetch current robot state");
629  return false;
630  }
631 
632  current_state = current_state_monitor_->getCurrentState();
633  return true;
634  }
635 
637  {
638  if (!move_action_client_ || !move_action_client_->action_server_is_ready())
639  {
640  RCLCPP_INFO_STREAM(logger_, "MoveGroup action client/server not ready");
641  return moveit::core::MoveItErrorCode::FAILURE;
642  }
643  RCLCPP_INFO_STREAM(logger_, "MoveGroup action client/server ready");
644 
645  moveit_msgs::action::MoveGroup::Goal goal;
646  constructGoal(goal);
647  goal.planning_options.plan_only = true;
648  goal.planning_options.look_around = false;
649  goal.planning_options.replan = false;
650  goal.planning_options.planning_scene_diff.is_diff = true;
651  goal.planning_options.planning_scene_diff.robot_state.is_diff = true;
652 
653  bool done = false;
654  rclcpp_action::ResultCode code = rclcpp_action::ResultCode::UNKNOWN;
655  std::shared_ptr<moveit_msgs::action::MoveGroup::Result> res;
656  auto send_goal_opts = rclcpp_action::Client<moveit_msgs::action::MoveGroup>::SendGoalOptions();
657 
658  send_goal_opts.goal_response_callback =
659  [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::MoveGroup>::SharedPtr& goal_handle) {
660  if (!goal_handle)
661  {
662  done = true;
663  RCLCPP_INFO(logger_, "Planning request rejected");
664  }
665  else
666  RCLCPP_INFO(logger_, "Planning request accepted");
667  };
668  send_goal_opts.result_callback =
669  [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::MoveGroup>::WrappedResult& result) {
670  res = result.result;
671  code = result.code;
672  done = true;
673 
674  switch (result.code)
675  {
676  case rclcpp_action::ResultCode::SUCCEEDED:
677  RCLCPP_INFO(logger_, "Planning request complete!");
678  break;
679  case rclcpp_action::ResultCode::ABORTED:
680  RCLCPP_INFO(logger_, "Planning request aborted");
681  return;
682  case rclcpp_action::ResultCode::CANCELED:
683  RCLCPP_INFO(logger_, "Planning request canceled");
684  return;
685  default:
686  RCLCPP_INFO(logger_, "Planning request unknown result code");
687  return;
688  }
689  };
690 
691  auto goal_handle_future = move_action_client_->async_send_goal(goal, send_goal_opts);
692 
693  // wait until send_goal_opts.result_callback is called
694  while (!done)
695  {
696  std::this_thread::sleep_for(std::chrono::milliseconds(1));
697  }
698 
699  if (code != rclcpp_action::ResultCode::SUCCEEDED)
700  {
701  RCLCPP_ERROR_STREAM(logger_, "MoveGroupInterface::plan() failed or timeout reached");
702  return res->error_code;
703  }
704 
705  plan.trajectory = res->planned_trajectory;
706  plan.start_state = res->trajectory_start;
707  plan.planning_time = res->planning_time;
708  RCLCPP_INFO(logger_, "time taken to generate plan: %g seconds", plan.planning_time);
709 
710  return res->error_code;
711  }
712 
714  {
715  if (!move_action_client_ || !move_action_client_->action_server_is_ready())
716  {
717  RCLCPP_INFO_STREAM(logger_, "MoveGroup action client/server not ready");
718  return moveit::core::MoveItErrorCode::FAILURE;
719  }
720 
721  moveit_msgs::action::MoveGroup::Goal goal;
722  constructGoal(goal);
723  goal.planning_options.plan_only = false;
724  goal.planning_options.look_around = can_look_;
725  goal.planning_options.replan = can_replan_;
726  goal.planning_options.replan_delay = replan_delay_;
727  goal.planning_options.planning_scene_diff.is_diff = true;
728  goal.planning_options.planning_scene_diff.robot_state.is_diff = true;
729 
730  bool done = false;
731  rclcpp_action::ResultCode code = rclcpp_action::ResultCode::UNKNOWN;
732  std::shared_ptr<moveit_msgs::action::MoveGroup_Result> res;
733  auto send_goal_opts = rclcpp_action::Client<moveit_msgs::action::MoveGroup>::SendGoalOptions();
734 
735  send_goal_opts.goal_response_callback =
736  [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::MoveGroup>::SharedPtr& goal_handle) {
737  if (!goal_handle)
738  {
739  done = true;
740  RCLCPP_INFO(logger_, "Plan and Execute request rejected");
741  }
742  else
743  RCLCPP_INFO(logger_, "Plan and Execute request accepted");
744  };
745  send_goal_opts.result_callback =
746  [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::MoveGroup>::WrappedResult& result) {
747  res = result.result;
748  code = result.code;
749  done = true;
750 
751  switch (result.code)
752  {
753  case rclcpp_action::ResultCode::SUCCEEDED:
754  RCLCPP_INFO(logger_, "Plan and Execute request complete!");
755  break;
756  case rclcpp_action::ResultCode::ABORTED:
757  RCLCPP_INFO(logger_, "Plan and Execute request aborted");
758  return;
759  case rclcpp_action::ResultCode::CANCELED:
760  RCLCPP_INFO(logger_, "Plan and Execute request canceled");
761  return;
762  default:
763  RCLCPP_INFO(logger_, "Plan and Execute request unknown result code");
764  return;
765  }
766  };
767  auto goal_handle_future = move_action_client_->async_send_goal(goal, send_goal_opts);
768  if (!wait)
769  return moveit::core::MoveItErrorCode::SUCCESS;
770 
771  // wait until send_goal_opts.result_callback is called
772  while (!done)
773  {
774  std::this_thread::sleep_for(std::chrono::milliseconds(1));
775  }
776 
777  if (code != rclcpp_action::ResultCode::SUCCEEDED)
778  {
779  RCLCPP_ERROR_STREAM(logger_, "MoveGroupInterface::move() failed or timeout reached");
780  }
781  return res->error_code;
782  }
783 
784  moveit::core::MoveItErrorCode execute(const moveit_msgs::msg::RobotTrajectory& trajectory, bool wait,
785  const std::vector<std::string>& controllers = std::vector<std::string>())
786  {
787  if (!execute_action_client_ || !execute_action_client_->action_server_is_ready())
788  {
789  RCLCPP_INFO_STREAM(logger_, "execute_action_client_ client/server not ready");
790  return moveit::core::MoveItErrorCode::FAILURE;
791  }
792 
793  bool done = false;
794  rclcpp_action::ResultCode code = rclcpp_action::ResultCode::UNKNOWN;
795  std::shared_ptr<moveit_msgs::action::ExecuteTrajectory_Result> res;
796  auto send_goal_opts = rclcpp_action::Client<moveit_msgs::action::ExecuteTrajectory>::SendGoalOptions();
797 
798  send_goal_opts.goal_response_callback =
799  [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::ExecuteTrajectory>::SharedPtr& goal_handle) {
800  if (!goal_handle)
801  {
802  done = true;
803  RCLCPP_INFO(logger_, "Execute request rejected");
804  }
805  else
806  RCLCPP_INFO(logger_, "Execute request accepted");
807  };
808  send_goal_opts.result_callback =
809  [&](const rclcpp_action::ClientGoalHandle<moveit_msgs::action::ExecuteTrajectory>::WrappedResult& result) {
810  res = result.result;
811  code = result.code;
812  done = true;
813 
814  switch (result.code)
815  {
816  case rclcpp_action::ResultCode::SUCCEEDED:
817  RCLCPP_INFO(logger_, "Execute request success!");
818  break;
819  case rclcpp_action::ResultCode::ABORTED:
820  RCLCPP_INFO(logger_, "Execute request aborted");
821  return;
822  case rclcpp_action::ResultCode::CANCELED:
823  RCLCPP_INFO(logger_, "Execute request canceled");
824  return;
825  default:
826  RCLCPP_INFO(logger_, "Execute request unknown result code");
827  return;
828  }
829  };
830 
831  moveit_msgs::action::ExecuteTrajectory::Goal goal;
832  goal.trajectory = trajectory;
833  goal.controller_names = controllers;
834 
835  auto goal_handle_future = execute_action_client_->async_send_goal(goal, send_goal_opts);
836  if (!wait)
837  return moveit::core::MoveItErrorCode::SUCCESS;
838 
839  // wait until send_goal_opts.result_callback is called
840  while (!done)
841  {
842  std::this_thread::sleep_for(std::chrono::milliseconds(1));
843  }
844 
845  if (code != rclcpp_action::ResultCode::SUCCEEDED)
846  {
847  RCLCPP_ERROR_STREAM(logger_, "MoveGroupInterface::execute() failed or timeout reached");
848  }
849  return res->error_code;
850  }
851 
852  double computeCartesianPath(const std::vector<geometry_msgs::msg::Pose>& waypoints, double step,
853  double jump_threshold, moveit_msgs::msg::RobotTrajectory& msg,
854  const moveit_msgs::msg::Constraints& path_constraints, bool avoid_collisions,
855  moveit_msgs::msg::MoveItErrorCodes& error_code)
856  {
857  auto req = std::make_shared<moveit_msgs::srv::GetCartesianPath::Request>();
858  moveit_msgs::srv::GetCartesianPath::Response::SharedPtr response;
859 
860  if (considered_start_state_)
861  {
862  moveit::core::robotStateToRobotStateMsg(*considered_start_state_, req->start_state);
863  }
864  else
865  {
866  req->start_state.is_diff = true;
867  }
868 
869  req->group_name = opt_.group_name;
870  req->header.frame_id = getPoseReferenceFrame();
871  req->header.stamp = getClock()->now();
872  req->waypoints = waypoints;
873  req->max_step = step;
874  req->jump_threshold = jump_threshold;
875  req->path_constraints = path_constraints;
876  req->avoid_collisions = avoid_collisions;
877  req->link_name = getEndEffectorLink();
878  req->max_velocity_scaling_factor = max_velocity_scaling_factor_;
879  req->max_acceleration_scaling_factor = max_acceleration_scaling_factor_;
880 
881  auto future_response = cartesian_path_service_->async_send_request(req);
882  if (future_response.valid())
883  {
884  response = future_response.get();
885  error_code = response->error_code;
886  if (response->error_code.val == moveit_msgs::msg::MoveItErrorCodes::SUCCESS)
887  {
888  msg = response->solution;
889  return response->fraction;
890  }
891  else
892  return -1.0;
893  }
894  else
895  {
896  error_code.val = error_code.FAILURE;
897  return -1.0;
898  }
899  }
900 
901  void stop()
902  {
903  if (trajectory_event_publisher_)
904  {
905  std_msgs::msg::String event;
906  event.data = "stop";
907  trajectory_event_publisher_->publish(event);
908  }
909  }
910 
911  bool attachObject(const std::string& object, const std::string& link, const std::vector<std::string>& touch_links)
912  {
913  std::string l = link.empty() ? getEndEffectorLink() : link;
914  if (l.empty())
915  {
916  const std::vector<std::string>& links = joint_model_group_->getLinkModelNames();
917  if (!links.empty())
918  l = links[0];
919  }
920  if (l.empty())
921  {
922  RCLCPP_ERROR(logger_, "No known link to attach object '%s' to", object.c_str());
923  return false;
924  }
925  moveit_msgs::msg::AttachedCollisionObject aco;
926  aco.object.id = object;
927  aco.link_name.swap(l);
928  if (touch_links.empty())
929  {
930  aco.touch_links.push_back(aco.link_name);
931  }
932  else
933  {
934  aco.touch_links = touch_links;
935  }
936  aco.object.operation = moveit_msgs::msg::CollisionObject::ADD;
937  attached_object_publisher_->publish(aco);
938  return true;
939  }
940 
941  bool detachObject(const std::string& name)
942  {
943  moveit_msgs::msg::AttachedCollisionObject aco;
944  // if name is a link
945  if (!name.empty() && joint_model_group_->hasLinkModel(name))
946  {
947  aco.link_name = name;
948  }
949  else
950  {
951  aco.object.id = name;
952  }
953  aco.object.operation = moveit_msgs::msg::CollisionObject::REMOVE;
954  if (aco.link_name.empty() && aco.object.id.empty())
955  {
956  // we only want to detach objects for this group
957  const std::vector<std::string>& lnames = joint_model_group_->getLinkModelNames();
958  for (const std::string& lname : lnames)
959  {
960  aco.link_name = lname;
961  attached_object_publisher_->publish(aco);
962  }
963  }
964  else
965  {
966  attached_object_publisher_->publish(aco);
967  }
968  return true;
969  }
970 
972  {
973  return goal_position_tolerance_;
974  }
975 
977  {
978  return goal_orientation_tolerance_;
979  }
980 
981  double getGoalJointTolerance() const
982  {
983  return goal_joint_tolerance_;
984  }
985 
986  void setGoalJointTolerance(double tolerance)
987  {
988  goal_joint_tolerance_ = tolerance;
989  }
990 
991  void setGoalPositionTolerance(double tolerance)
992  {
993  goal_position_tolerance_ = tolerance;
994  }
995 
996  void setGoalOrientationTolerance(double tolerance)
997  {
998  goal_orientation_tolerance_ = tolerance;
999  }
1000 
1001  void setPlanningTime(double seconds)
1002  {
1003  if (seconds > 0.0)
1004  allowed_planning_time_ = seconds;
1005  }
1006 
1007  double getPlanningTime() const
1008  {
1009  return allowed_planning_time_;
1010  }
1011 
1013  {
1014  request.group_name = opt_.group_name;
1015  request.num_planning_attempts = num_planning_attempts_;
1016  request.max_velocity_scaling_factor = max_velocity_scaling_factor_;
1017  request.max_acceleration_scaling_factor = max_acceleration_scaling_factor_;
1018  request.allowed_planning_time = allowed_planning_time_;
1019  request.pipeline_id = planning_pipeline_id_;
1020  request.planner_id = planner_id_;
1021  request.workspace_parameters = workspace_parameters_;
1022 
1023  if (considered_start_state_)
1024  {
1025  moveit::core::robotStateToRobotStateMsg(*considered_start_state_, request.start_state);
1026  }
1027  else
1028  {
1029  request.start_state.is_diff = true;
1030  }
1031 
1032  if (active_target_ == JOINT)
1033  {
1034  request.goal_constraints.resize(1);
1035  request.goal_constraints[0] = kinematic_constraints::constructGoalConstraints(
1036  getTargetRobotState(), joint_model_group_, goal_joint_tolerance_);
1037  }
1038  else if (active_target_ == POSE || active_target_ == POSITION || active_target_ == ORIENTATION)
1039  {
1040  // find out how many goals are specified
1041  std::size_t goal_count = 0;
1042  for (const auto& pose_target : pose_targets_)
1043  goal_count = std::max(goal_count, pose_target.second.size());
1044 
1045  // start filling the goals;
1046  // each end effector has a number of possible poses (K) as valid goals
1047  // but there could be multiple end effectors specified, so we want each end effector
1048  // to reach the goal that corresponds to the goals of the other end effectors
1049  request.goal_constraints.resize(goal_count);
1050 
1051  for (const auto& pose_target : pose_targets_)
1052  {
1053  for (std::size_t i = 0; i < pose_target.second.size(); ++i)
1054  {
1055  moveit_msgs::msg::Constraints c = kinematic_constraints::constructGoalConstraints(
1056  pose_target.first, pose_target.second[i], goal_position_tolerance_, goal_orientation_tolerance_);
1057  if (active_target_ == ORIENTATION)
1058  c.position_constraints.clear();
1059  if (active_target_ == POSITION)
1060  c.orientation_constraints.clear();
1061  request.goal_constraints[i] = kinematic_constraints::mergeConstraints(request.goal_constraints[i], c);
1062  }
1063  }
1064  }
1065  else
1066  RCLCPP_ERROR(logger_, "Unable to construct MotionPlanRequest representation");
1067 
1068  if (path_constraints_)
1069  request.path_constraints = *path_constraints_;
1070  if (trajectory_constraints_)
1071  request.trajectory_constraints = *trajectory_constraints_;
1072  }
1073 
1074  void constructGoal(moveit_msgs::action::MoveGroup::Goal& goal) const
1075  {
1076  constructMotionPlanRequest(goal.request);
1077  }
1078 
1079  // moveit_msgs::action::Pickup::Goal constructPickupGoal(const std::string& object,
1080  // std::vector<moveit_msgs::msg::Grasp>&& grasps,
1081  // bool plan_only = false) const
1082  // {
1083  // moveit_msgs::action::Pickup::Goal goal;
1084  // goal.target_name = object;
1085  // goal.group_name = opt_.group_name;
1086  // goal.end_effector = getEndEffector();
1087  // goal.support_surface_name = support_surface_;
1088  // goal.possible_grasps = std::move(grasps);
1089  // if (!support_surface_.empty())
1090  // goal.allow_gripper_support_collision = true;
1091  //
1092  // if (path_constraints_)
1093  // goal.path_constraints = *path_constraints_;
1094  //
1095  // goal.planner_id = planner_id_;
1096  // goal.allowed_planning_time = allowed_planning_time_;
1097  //
1098  // goal.planning_options.plan_only = plan_only;
1099  // goal.planning_options.look_around = can_look_;
1100  // goal.planning_options.replan = can_replan_;
1101  // goal.planning_options.replan_delay = replan_delay_;
1102  // goal.planning_options.planning_scene_diff.is_diff = true;
1103  // goal.planning_options.planning_scene_diff.robot_state.is_diff = true;
1104  // return goal;
1105  // }
1106 
1107  // moveit_msgs::action::Place::Goal constructPlaceGoal(const std::string& object,
1108  // std::vector<moveit_msgs::msg::PlaceLocation>&& locations,
1109  // bool plan_only = false) const
1110  // {
1111  // moveit_msgs::action::Place::Goal goal;
1112  // goal.group_name = opt_.group_name;
1113  // goal.attached_object_name = object;
1114  // goal.support_surface_name = support_surface_;
1115  // goal.place_locations = std::move(locations);
1116  // if (!support_surface_.empty())
1117  // goal.allow_gripper_support_collision = true;
1118  //
1119  // if (path_constraints_)
1120  // goal.path_constraints = *path_constraints_;
1121  //
1122  // goal.planner_id = planner_id_;
1123  // goal.allowed_planning_time = allowed_planning_time_;
1124  //
1125  // goal.planning_options.plan_only = plan_only;
1126  // goal.planning_options.look_around = can_look_;
1127  // goal.planning_options.replan = can_replan_;
1128  // goal.planning_options.replan_delay = replan_delay_;
1129  // goal.planning_options.planning_scene_diff.is_diff = true;
1130  // goal.planning_options.planning_scene_diff.robot_state.is_diff = true;
1131  // return goal;
1132  // }
1133 
1134  void setPathConstraints(const moveit_msgs::msg::Constraints& constraint)
1135  {
1136  path_constraints_ = std::make_unique<moveit_msgs::msg::Constraints>(constraint);
1137  }
1138 
1139  bool setPathConstraints(const std::string& constraint)
1140  {
1141  if (constraints_storage_)
1142  {
1144  if (constraints_storage_->getConstraints(msg_m, constraint, robot_model_->getName(), opt_.group_name))
1145  {
1146  path_constraints_ =
1147  std::make_unique<moveit_msgs::msg::Constraints>(static_cast<moveit_msgs::msg::Constraints>(*msg_m));
1148  return true;
1149  }
1150  else
1151  return false;
1152  }
1153  else
1154  return false;
1155  }
1156 
1158  {
1159  path_constraints_.reset();
1160  }
1161 
1162  void setTrajectoryConstraints(const moveit_msgs::msg::TrajectoryConstraints& constraint)
1163  {
1164  trajectory_constraints_ = std::make_unique<moveit_msgs::msg::TrajectoryConstraints>(constraint);
1165  }
1166 
1168  {
1169  trajectory_constraints_.reset();
1170  }
1171 
1172  std::vector<std::string> getKnownConstraints() const
1173  {
1174  while (initializing_constraints_)
1175  {
1176  std::chrono::duration<double> d(0.01);
1177  rclcpp::sleep_for(std::chrono::duration_cast<std::chrono::nanoseconds>(d), rclcpp::Context::SharedPtr(nullptr));
1178  }
1179 
1180  std::vector<std::string> c;
1181  if (constraints_storage_)
1182  constraints_storage_->getKnownConstraints(c, robot_model_->getName(), opt_.group_name);
1183 
1184  return c;
1185  }
1186 
1187  moveit_msgs::msg::Constraints getPathConstraints() const
1188  {
1189  if (path_constraints_)
1190  {
1191  return *path_constraints_;
1192  }
1193  else
1194  {
1195  return moveit_msgs::msg::Constraints();
1196  }
1197  }
1198 
1199  moveit_msgs::msg::TrajectoryConstraints getTrajectoryConstraints() const
1200  {
1201  if (trajectory_constraints_)
1202  {
1203  return *trajectory_constraints_;
1204  }
1205  else
1206  {
1207  return moveit_msgs::msg::TrajectoryConstraints();
1208  }
1209  }
1210 
1211  void initializeConstraintsStorage(const std::string& host, unsigned int port)
1212  {
1213  initializing_constraints_ = true;
1214  if (constraints_init_thread_)
1215  constraints_init_thread_->join();
1216  constraints_init_thread_ =
1217  std::make_unique<std::thread>([this, host, port] { initializeConstraintsStorageThread(host, port); });
1218  }
1219 
1220  void setWorkspace(double minx, double miny, double minz, double maxx, double maxy, double maxz)
1221  {
1222  workspace_parameters_.header.frame_id = getRobotModel()->getModelFrame();
1223  workspace_parameters_.header.stamp = getClock()->now();
1224  workspace_parameters_.min_corner.x = minx;
1225  workspace_parameters_.min_corner.y = miny;
1226  workspace_parameters_.min_corner.z = minz;
1227  workspace_parameters_.max_corner.x = maxx;
1228  workspace_parameters_.max_corner.y = maxy;
1229  workspace_parameters_.max_corner.z = maxz;
1230  }
1231 
1232  rclcpp::Clock::SharedPtr getClock()
1233  {
1234  return node_->get_clock();
1235  }
1236 
1237 private:
1238  void initializeConstraintsStorageThread(const std::string& host, unsigned int port)
1239  {
1240  // Set up db
1241  try
1242  {
1243  warehouse_ros::DatabaseConnection::Ptr conn = moveit_warehouse::loadDatabase(node_);
1244  conn->setParams(host, port);
1245  if (conn->connect())
1246  {
1247  constraints_storage_ = std::make_unique<moveit_warehouse::ConstraintsStorage>(conn);
1248  }
1249  }
1250  catch (std::exception& ex)
1251  {
1252  RCLCPP_ERROR(logger_, "%s", ex.what());
1253  }
1254  initializing_constraints_ = false;
1255  }
1256 
1257  Options opt_;
1258  rclcpp::Node::SharedPtr node_;
1259  rclcpp::Logger logger_;
1260  rclcpp::CallbackGroup::SharedPtr callback_group_;
1261  rclcpp::executors::SingleThreadedExecutor callback_executor_;
1262  std::thread callback_thread_;
1263  std::shared_ptr<tf2_ros::Buffer> tf_buffer_;
1264  moveit::core::RobotModelConstPtr robot_model_;
1265  planning_scene_monitor::CurrentStateMonitorPtr current_state_monitor_;
1266 
1267  std::shared_ptr<rclcpp_action::Client<moveit_msgs::action::MoveGroup>> move_action_client_;
1268  // std::shared_ptr<rclcpp_action::Client<moveit_msgs::action::Pickup>> pick_action_client_;
1269  // std::shared_ptr<rclcpp_action::Client<moveit_msgs::action::Place>> place_action_client_;
1270  std::shared_ptr<rclcpp_action::Client<moveit_msgs::action::ExecuteTrajectory>> execute_action_client_;
1271 
1272  // general planning params
1273  moveit::core::RobotStatePtr considered_start_state_;
1274  moveit_msgs::msg::WorkspaceParameters workspace_parameters_;
1275  double allowed_planning_time_;
1276  std::string planning_pipeline_id_;
1277  std::string planner_id_;
1278  unsigned int num_planning_attempts_;
1279  double max_velocity_scaling_factor_;
1280  double max_acceleration_scaling_factor_;
1281  double goal_joint_tolerance_;
1282  double goal_position_tolerance_;
1283  double goal_orientation_tolerance_;
1284  bool can_look_;
1285  int32_t look_around_attempts_;
1286  bool can_replan_;
1287  int32_t replan_attempts_;
1288  double replan_delay_;
1289 
1290  // joint state goal
1291  moveit::core::RobotStatePtr joint_state_target_;
1292  const moveit::core::JointModelGroup* joint_model_group_;
1293 
1294  // pose goal;
1295  // for each link we have a set of possible goal locations;
1296  std::map<std::string, std::vector<geometry_msgs::msg::PoseStamped>> pose_targets_;
1297 
1298  // common properties for goals
1299  ActiveTargetType active_target_;
1300  std::unique_ptr<moveit_msgs::msg::Constraints> path_constraints_;
1301  std::unique_ptr<moveit_msgs::msg::TrajectoryConstraints> trajectory_constraints_;
1302  std::string end_effector_link_;
1303  std::string pose_reference_frame_;
1304  std::string support_surface_;
1305 
1306  // ROS communication
1307  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr trajectory_event_publisher_;
1308  rclcpp::Publisher<moveit_msgs::msg::AttachedCollisionObject>::SharedPtr attached_object_publisher_;
1309  rclcpp::Client<moveit_msgs::srv::QueryPlannerInterfaces>::SharedPtr query_service_;
1310  rclcpp::Client<moveit_msgs::srv::GetPlannerParams>::SharedPtr get_params_service_;
1311  rclcpp::Client<moveit_msgs::srv::SetPlannerParams>::SharedPtr set_params_service_;
1312  rclcpp::Client<moveit_msgs::srv::GetCartesianPath>::SharedPtr cartesian_path_service_;
1313  // rclcpp::Client<moveit_msgs::srv::GraspPlanning>::SharedPtr plan_grasps_service_;
1314  std::unique_ptr<moveit_warehouse::ConstraintsStorage> constraints_storage_;
1315  std::unique_ptr<std::thread> constraints_init_thread_;
1316  bool initializing_constraints_;
1317 };
1318 
1319 MoveGroupInterface::MoveGroupInterface(const rclcpp::Node::SharedPtr& node, const std::string& group_name,
1320  const std::shared_ptr<tf2_ros::Buffer>& tf_buffer,
1321  const rclcpp::Duration& wait_for_servers)
1322  : logger_(moveit::getLogger("move_group_interface"))
1323 {
1324  if (!rclcpp::ok())
1325  throw std::runtime_error("ROS does not seem to be running");
1326  impl_ =
1327  new MoveGroupInterfaceImpl(node, Options(group_name), tf_buffer ? tf_buffer : getSharedTF(), wait_for_servers);
1328 }
1329 
1330 MoveGroupInterface::MoveGroupInterface(const rclcpp::Node::SharedPtr& node, const Options& opt,
1331  const std::shared_ptr<tf2_ros::Buffer>& tf_buffer,
1332  const rclcpp::Duration& wait_for_servers)
1333  : logger_(moveit::getLogger("move_group_interface"))
1334 {
1335  impl_ = new MoveGroupInterfaceImpl(node, opt, tf_buffer ? tf_buffer : getSharedTF(), wait_for_servers);
1336 }
1337 
1339 {
1340  delete impl_;
1341 }
1342 
1344  : remembered_joint_values_(std::move(other.remembered_joint_values_))
1345  , impl_(other.impl_)
1346  , logger_(std::move(other.logger_))
1347 {
1348  other.impl_ = nullptr;
1349 }
1350 
1352 {
1353  if (this != &other)
1354  {
1355  delete impl_;
1356  impl_ = other.impl_;
1357  logger_ = other.logger_;
1358  remembered_joint_values_ = std::move(other.remembered_joint_values_);
1359  other.impl_ = nullptr;
1360  }
1361 
1362  return *this;
1363 }
1364 
1365 const std::string& MoveGroupInterface::getName() const
1366 {
1367  return impl_->getOptions().group_name;
1368 }
1369 
1370 const std::vector<std::string>& MoveGroupInterface::getNamedTargets() const
1371 {
1372  // The pointer returned by getJointModelGroup is guaranteed by the class
1373  // constructor to always be non-null
1374  return impl_->getJointModelGroup()->getDefaultStateNames();
1375 }
1376 
1377 moveit::core::RobotModelConstPtr MoveGroupInterface::getRobotModel() const
1378 {
1379  return impl_->getRobotModel();
1380 }
1381 
1382 bool MoveGroupInterface::getInterfaceDescription(moveit_msgs::msg::PlannerInterfaceDescription& desc) const
1383 {
1384  return impl_->getInterfaceDescription(desc);
1385 }
1386 
1387 bool MoveGroupInterface::getInterfaceDescriptions(std::vector<moveit_msgs::msg::PlannerInterfaceDescription>& desc) const
1388 {
1389  return impl_->getInterfaceDescriptions(desc);
1390 }
1391 
1392 std::map<std::string, std::string> MoveGroupInterface::getPlannerParams(const std::string& planner_id,
1393  const std::string& group) const
1394 {
1395  return impl_->getPlannerParams(planner_id, group);
1396 }
1397 
1398 void MoveGroupInterface::setPlannerParams(const std::string& planner_id, const std::string& group,
1399  const std::map<std::string, std::string>& params, bool replace)
1400 {
1401  impl_->setPlannerParams(planner_id, group, params, replace);
1402 }
1403 
1405 {
1406  return impl_->getDefaultPlanningPipelineId();
1407 }
1408 
1409 void MoveGroupInterface::setPlanningPipelineId(const std::string& pipeline_id)
1410 {
1411  impl_->setPlanningPipelineId(pipeline_id);
1412 }
1413 
1415 {
1416  return impl_->getPlanningPipelineId();
1417 }
1418 
1419 std::string MoveGroupInterface::getDefaultPlannerId(const std::string& group) const
1420 {
1421  return impl_->getDefaultPlannerId(group);
1422 }
1423 
1424 void MoveGroupInterface::setPlannerId(const std::string& planner_id)
1425 {
1426  impl_->setPlannerId(planner_id);
1427 }
1428 
1429 const std::string& MoveGroupInterface::getPlannerId() const
1430 {
1431  return impl_->getPlannerId();
1432 }
1433 
1434 void MoveGroupInterface::setNumPlanningAttempts(unsigned int num_planning_attempts)
1435 {
1436  impl_->setNumPlanningAttempts(num_planning_attempts);
1437 }
1438 
1439 void MoveGroupInterface::setMaxVelocityScalingFactor(double max_velocity_scaling_factor)
1440 {
1441  impl_->setMaxVelocityScalingFactor(max_velocity_scaling_factor);
1442 }
1443 
1444 void MoveGroupInterface::setMaxAccelerationScalingFactor(double max_acceleration_scaling_factor)
1445 {
1446  impl_->setMaxAccelerationScalingFactor(max_acceleration_scaling_factor);
1447 }
1448 
1450 {
1451  return impl_->move(false);
1452 }
1453 
1454 rclcpp_action::Client<moveit_msgs::action::MoveGroup>& MoveGroupInterface::getMoveGroupClient() const
1455 {
1456  return impl_->getMoveGroupClient();
1457 }
1458 
1460 {
1461  return impl_->move(true);
1462 }
1463 
1465  const std::vector<std::string>& controllers)
1466 {
1467  return impl_->execute(plan.trajectory, false, controllers);
1468 }
1469 
1470 moveit::core::MoveItErrorCode MoveGroupInterface::asyncExecute(const moveit_msgs::msg::RobotTrajectory& trajectory,
1471  const std::vector<std::string>& controllers)
1472 {
1473  return impl_->execute(trajectory, false, controllers);
1474 }
1475 
1476 moveit::core::MoveItErrorCode MoveGroupInterface::execute(const Plan& plan, const std::vector<std::string>& controllers)
1477 {
1478  return impl_->execute(plan.trajectory, true, controllers);
1479 }
1480 
1481 moveit::core::MoveItErrorCode MoveGroupInterface::execute(const moveit_msgs::msg::RobotTrajectory& trajectory,
1482  const std::vector<std::string>& controllers)
1483 {
1484  return impl_->execute(trajectory, true, controllers);
1485 }
1486 
1488 {
1489  return impl_->plan(plan);
1490 }
1491 
1492 // moveit_msgs::action::Pickup::Goal MoveGroupInterface::constructPickupGoal(const std::string& object,
1493 // std::vector<moveit_msgs::msg::Grasp> grasps,
1494 // bool plan_only = false) const
1495 //{
1496 // return impl_->constructPickupGoal(object, std::move(grasps), plan_only);
1497 //}
1498 //
1499 // moveit_msgs::action::Place::Goal MoveGroupInterface::constructPlaceGoal(
1500 // const std::string& object, std::vector<moveit_msgs::msg::PlaceLocation> locations, bool plan_only = false) const
1501 //{
1502 // return impl_->constructPlaceGoal(object, std::move(locations), plan_only);
1503 //}
1504 //
1505 // std::vector<moveit_msgs::msg::PlaceLocation>
1506 // MoveGroupInterface::posesToPlaceLocations(const std::vector<geometry_msgs::msg::PoseStamped>& poses) const
1507 //{
1508 // return impl_->posesToPlaceLocations(poses);
1509 //}
1510 //
1511 // moveit::core::MoveItErrorCode MoveGroupInterface::pick(const moveit_msgs::action::Pickup::Goal& goal)
1512 //{
1513 // return impl_->pick(goal);
1514 //}
1515 //
1516 // moveit::core::MoveItErrorCode MoveGroupInterface::planGraspsAndPick(const std::string& object, bool plan_only)
1517 //{
1518 // return impl_->planGraspsAndPick(object, plan_only);
1519 //}
1520 //
1521 // moveit::core::MoveItErrorCode MoveGroupInterface::planGraspsAndPick(const moveit_msgs::msg::CollisionObject& object,
1522 // bool plan_only)
1523 //{
1524 // return impl_->planGraspsAndPick(object, plan_only);
1525 //}
1526 //
1527 // moveit::core::MoveItErrorCode MoveGroupInterface::place(const moveit_msgs::action::Place::Goal& goal)
1528 //{
1529 // return impl_->place(goal);
1530 //}
1531 
1532 double MoveGroupInterface::computeCartesianPath(const std::vector<geometry_msgs::msg::Pose>& waypoints, double eef_step,
1533  double jump_threshold, moveit_msgs::msg::RobotTrajectory& trajectory,
1534  bool avoid_collisions, moveit_msgs::msg::MoveItErrorCodes* error_code)
1535 {
1536  moveit_msgs::msg::Constraints path_constraints_tmp;
1537  return computeCartesianPath(waypoints, eef_step, jump_threshold, trajectory, moveit_msgs::msg::Constraints(),
1538  avoid_collisions, error_code);
1539 }
1540 
1541 double MoveGroupInterface::computeCartesianPath(const std::vector<geometry_msgs::msg::Pose>& waypoints, double eef_step,
1542  double jump_threshold, moveit_msgs::msg::RobotTrajectory& trajectory,
1543  const moveit_msgs::msg::Constraints& path_constraints,
1544  bool avoid_collisions, moveit_msgs::msg::MoveItErrorCodes* error_code)
1545 {
1546  if (error_code)
1547  {
1548  return impl_->computeCartesianPath(waypoints, eef_step, jump_threshold, trajectory, path_constraints,
1549  avoid_collisions, *error_code);
1550  }
1551  else
1552  {
1553  moveit_msgs::msg::MoveItErrorCodes err_tmp;
1554  err_tmp.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;
1555  moveit_msgs::msg::MoveItErrorCodes& err = error_code ? *error_code : err_tmp;
1556  return impl_->computeCartesianPath(waypoints, eef_step, jump_threshold, trajectory, path_constraints,
1557  avoid_collisions, err);
1558  }
1559 }
1560 
1562 {
1563  impl_->stop();
1564 }
1565 
1566 void MoveGroupInterface::setStartState(const moveit_msgs::msg::RobotState& start_state)
1567 {
1568  moveit::core::RobotStatePtr rs;
1569  if (start_state.is_diff)
1570  {
1571  impl_->getCurrentState(rs);
1572  }
1573  else
1574  {
1575  rs = std::make_shared<moveit::core::RobotState>(getRobotModel());
1576  rs->setToDefaultValues(); // initialize robot state values for conversion
1577  }
1578  moveit::core::robotStateMsgToRobotState(start_state, *rs);
1579  setStartState(*rs);
1580 }
1581 
1583 {
1584  impl_->setStartState(start_state);
1585 }
1586 
1588 {
1589  impl_->setStartStateToCurrentState();
1590 }
1591 
1593 {
1595  impl_->setTargetType(JOINT);
1596 }
1597 
1598 const std::vector<std::string>& MoveGroupInterface::getJointNames() const
1599 {
1600  return impl_->getJointModelGroup()->getVariableNames();
1601 }
1602 
1603 const std::vector<std::string>& MoveGroupInterface::getLinkNames() const
1604 {
1605  return impl_->getJointModelGroup()->getLinkModelNames();
1606 }
1607 
1608 std::map<std::string, double> MoveGroupInterface::getNamedTargetValues(const std::string& name) const
1609 {
1610  std::map<std::string, std::vector<double>>::const_iterator it = remembered_joint_values_.find(name);
1611  std::map<std::string, double> positions;
1612 
1613  if (it != remembered_joint_values_.cend())
1614  {
1615  std::vector<std::string> names = impl_->getJointModelGroup()->getVariableNames();
1616  for (size_t x = 0; x < names.size(); ++x)
1617  {
1618  positions[names[x]] = it->second[x];
1619  }
1620  }
1621  else
1622  {
1623  if (!impl_->getJointModelGroup()->getVariableDefaultPositions(name, positions))
1624  {
1625  RCLCPP_ERROR(logger_, "The requested named target '%s' does not exist, returning empty positions.", name.c_str());
1626  }
1627  }
1628  return positions;
1629 }
1630 
1632 {
1633  std::map<std::string, std::vector<double>>::const_iterator it = remembered_joint_values_.find(name);
1634  if (it != remembered_joint_values_.end())
1635  {
1636  return setJointValueTarget(it->second);
1637  }
1638  else
1639  {
1641  {
1642  impl_->setTargetType(JOINT);
1643  return true;
1644  }
1645  RCLCPP_ERROR(logger_, "The requested named target '%s' does not exist", name.c_str());
1646  return false;
1647  }
1648 }
1649 
1650 void MoveGroupInterface::getJointValueTarget(std::vector<double>& group_variable_values) const
1651 {
1652  impl_->getTargetRobotState().copyJointGroupPositions(impl_->getJointModelGroup(), group_variable_values);
1653 }
1654 
1655 bool MoveGroupInterface::setJointValueTarget(const std::vector<double>& joint_values)
1656 {
1657  const auto n_group_joints = impl_->getJointModelGroup()->getVariableCount();
1658  if (joint_values.size() != n_group_joints)
1659  {
1660  RCLCPP_DEBUG_STREAM(logger_, "Provided joint value list has length " << joint_values.size() << " but group "
1661  << impl_->getJointModelGroup()->getName()
1662  << " has " << n_group_joints << " joints");
1663  return false;
1664  }
1665  impl_->setTargetType(JOINT);
1666  impl_->getTargetRobotState().setJointGroupPositions(impl_->getJointModelGroup(), joint_values);
1668 }
1669 
1670 bool MoveGroupInterface::setJointValueTarget(const std::map<std::string, double>& variable_values)
1671 {
1672  const auto& allowed = impl_->getJointModelGroup()->getVariableNames();
1673  for (const auto& pair : variable_values)
1674  {
1675  if (std::find(allowed.begin(), allowed.end(), pair.first) == allowed.end())
1676  {
1677  RCLCPP_ERROR_STREAM(logger_, "joint variable " << pair.first << " is not part of group "
1678  << impl_->getJointModelGroup()->getName());
1679  return false;
1680  }
1681  }
1682 
1683  impl_->setTargetType(JOINT);
1684  impl_->getTargetRobotState().setVariablePositions(variable_values);
1685  return impl_->getTargetRobotState().satisfiesBounds(impl_->getGoalJointTolerance());
1686 }
1687 
1688 bool MoveGroupInterface::setJointValueTarget(const std::vector<std::string>& variable_names,
1689  const std::vector<double>& variable_values)
1690 {
1691  if (variable_names.size() != variable_values.size())
1692  {
1693  RCLCPP_ERROR_STREAM(logger_, "sizes of name and position arrays do not match");
1694  return false;
1695  }
1696  const auto& allowed = impl_->getJointModelGroup()->getVariableNames();
1697  for (const auto& variable_name : variable_names)
1698  {
1699  if (std::find(allowed.begin(), allowed.end(), variable_name) == allowed.end())
1700  {
1701  RCLCPP_ERROR_STREAM(logger_, "joint variable " << variable_name << " is not part of group "
1702  << impl_->getJointModelGroup()->getName());
1703  return false;
1704  }
1705  }
1706 
1707  impl_->setTargetType(JOINT);
1708  impl_->getTargetRobotState().setVariablePositions(variable_names, variable_values);
1709  return impl_->getTargetRobotState().satisfiesBounds(impl_->getGoalJointTolerance());
1710 }
1711 
1713 {
1714  impl_->setTargetType(JOINT);
1715  impl_->getTargetRobotState() = rstate;
1716  return impl_->getTargetRobotState().satisfiesBounds(impl_->getGoalJointTolerance());
1717 }
1718 
1719 bool MoveGroupInterface::setJointValueTarget(const std::string& joint_name, double value)
1720 {
1721  std::vector<double> values(1, value);
1722  return setJointValueTarget(joint_name, values);
1723 }
1724 
1725 bool MoveGroupInterface::setJointValueTarget(const std::string& joint_name, const std::vector<double>& values)
1726 {
1727  impl_->setTargetType(JOINT);
1728  const moveit::core::JointModel* jm = impl_->getJointModelGroup()->getJointModel(joint_name);
1729  if (jm && jm->getVariableCount() == values.size())
1730  {
1731  impl_->getTargetRobotState().setJointPositions(jm, values);
1732  return impl_->getTargetRobotState().satisfiesBounds(jm, impl_->getGoalJointTolerance());
1733  }
1734 
1735  RCLCPP_ERROR_STREAM(logger_,
1736  "joint " << joint_name << " is not part of group " << impl_->getJointModelGroup()->getName());
1737  return false;
1738 }
1739 
1740 bool MoveGroupInterface::setJointValueTarget(const sensor_msgs::msg::JointState& state)
1741 {
1742  return setJointValueTarget(state.name, state.position);
1743 }
1744 
1745 bool MoveGroupInterface::setJointValueTarget(const geometry_msgs::msg::Pose& eef_pose,
1746  const std::string& end_effector_link)
1747 {
1748  return impl_->setJointValueTarget(eef_pose, end_effector_link, "", false);
1749 }
1750 
1751 bool MoveGroupInterface::setJointValueTarget(const geometry_msgs::msg::PoseStamped& eef_pose,
1752  const std::string& end_effector_link)
1753 {
1754  return impl_->setJointValueTarget(eef_pose.pose, end_effector_link, eef_pose.header.frame_id, false);
1755 }
1756 
1757 bool MoveGroupInterface::setJointValueTarget(const Eigen::Isometry3d& eef_pose, const std::string& end_effector_link)
1758 {
1759  geometry_msgs::msg::Pose msg = tf2::toMsg(eef_pose);
1760  return setJointValueTarget(msg, end_effector_link);
1761 }
1762 
1763 bool MoveGroupInterface::setApproximateJointValueTarget(const geometry_msgs::msg::Pose& eef_pose,
1764  const std::string& end_effector_link)
1765 {
1766  return impl_->setJointValueTarget(eef_pose, end_effector_link, "", true);
1767 }
1768 
1769 bool MoveGroupInterface::setApproximateJointValueTarget(const geometry_msgs::msg::PoseStamped& eef_pose,
1770  const std::string& end_effector_link)
1771 {
1772  return impl_->setJointValueTarget(eef_pose.pose, end_effector_link, eef_pose.header.frame_id, true);
1773 }
1774 
1775 bool MoveGroupInterface::setApproximateJointValueTarget(const Eigen::Isometry3d& eef_pose,
1776  const std::string& end_effector_link)
1777 {
1778  geometry_msgs::msg::Pose msg = tf2::toMsg(eef_pose);
1779  return setApproximateJointValueTarget(msg, end_effector_link);
1780 }
1781 
1783 {
1784  return impl_->getTargetRobotState();
1785 }
1786 
1787 const std::string& MoveGroupInterface::getEndEffectorLink() const
1788 {
1789  return impl_->getEndEffectorLink();
1790 }
1791 
1792 const std::string& MoveGroupInterface::getEndEffector() const
1793 {
1794  return impl_->getEndEffector();
1795 }
1796 
1797 bool MoveGroupInterface::setEndEffectorLink(const std::string& link_name)
1798 {
1799  if (impl_->getEndEffectorLink().empty() || link_name.empty())
1800  return false;
1801  impl_->setEndEffectorLink(link_name);
1802  impl_->setTargetType(POSE);
1803  return true;
1804 }
1805 
1806 bool MoveGroupInterface::setEndEffector(const std::string& eef_name)
1807 {
1808  const moveit::core::JointModelGroup* jmg = impl_->getRobotModel()->getEndEffector(eef_name);
1809  if (jmg)
1810  return setEndEffectorLink(jmg->getEndEffectorParentGroup().second);
1811  return false;
1812 }
1813 
1814 void MoveGroupInterface::clearPoseTarget(const std::string& end_effector_link)
1815 {
1816  impl_->clearPoseTarget(end_effector_link);
1817 }
1818 
1820 {
1821  impl_->clearPoseTargets();
1822 }
1823 
1824 bool MoveGroupInterface::setPoseTarget(const Eigen::Isometry3d& pose, const std::string& end_effector_link)
1825 {
1826  std::vector<geometry_msgs::msg::PoseStamped> pose_msg(1);
1827  pose_msg[0].pose = tf2::toMsg(pose);
1828  pose_msg[0].header.frame_id = getPoseReferenceFrame();
1829  pose_msg[0].header.stamp = impl_->getClock()->now();
1830  return setPoseTargets(pose_msg, end_effector_link);
1831 }
1832 
1833 bool MoveGroupInterface::setPoseTarget(const geometry_msgs::msg::Pose& target, const std::string& end_effector_link)
1834 {
1835  std::vector<geometry_msgs::msg::PoseStamped> pose_msg(1);
1836  pose_msg[0].pose = target;
1837  pose_msg[0].header.frame_id = getPoseReferenceFrame();
1838  pose_msg[0].header.stamp = impl_->getClock()->now();
1839  return setPoseTargets(pose_msg, end_effector_link);
1840 }
1841 
1842 bool MoveGroupInterface::setPoseTarget(const geometry_msgs::msg::PoseStamped& target,
1843  const std::string& end_effector_link)
1844 {
1845  std::vector<geometry_msgs::msg::PoseStamped> targets(1, target);
1846  return setPoseTargets(targets, end_effector_link);
1847 }
1848 
1849 bool MoveGroupInterface::setPoseTargets(const EigenSTL::vector_Isometry3d& target, const std::string& end_effector_link)
1850 {
1851  std::vector<geometry_msgs::msg::PoseStamped> pose_out(target.size());
1852  rclcpp::Time tm = impl_->getClock()->now();
1853  const std::string& frame_id = getPoseReferenceFrame();
1854  for (std::size_t i = 0; i < target.size(); ++i)
1855  {
1856  pose_out[i].pose = tf2::toMsg(target[i]);
1857  pose_out[i].header.stamp = tm;
1858  pose_out[i].header.frame_id = frame_id;
1859  }
1860  return setPoseTargets(pose_out, end_effector_link);
1861 }
1862 
1863 bool MoveGroupInterface::setPoseTargets(const std::vector<geometry_msgs::msg::Pose>& target,
1864  const std::string& end_effector_link)
1865 {
1866  std::vector<geometry_msgs::msg::PoseStamped> target_stamped(target.size());
1867  rclcpp::Time tm = impl_->getClock()->now();
1868  const std::string& frame_id = getPoseReferenceFrame();
1869  for (std::size_t i = 0; i < target.size(); ++i)
1870  {
1871  target_stamped[i].pose = target[i];
1872  target_stamped[i].header.stamp = tm;
1873  target_stamped[i].header.frame_id = frame_id;
1874  }
1875  return setPoseTargets(target_stamped, end_effector_link);
1876 }
1877 
1878 bool MoveGroupInterface::setPoseTargets(const std::vector<geometry_msgs::msg::PoseStamped>& target,
1879  const std::string& end_effector_link)
1880 {
1881  if (target.empty())
1882  {
1883  RCLCPP_ERROR(logger_, "No pose specified as goal target");
1884  return false;
1885  }
1886  else
1887  {
1888  impl_->setTargetType(POSE);
1889  return impl_->setPoseTargets(target, end_effector_link);
1890  }
1891 }
1892 
1893 const geometry_msgs::msg::PoseStamped& MoveGroupInterface::getPoseTarget(const std::string& end_effector_link) const
1894 {
1895  return impl_->getPoseTarget(end_effector_link);
1896 }
1897 
1898 const std::vector<geometry_msgs::msg::PoseStamped>&
1899 MoveGroupInterface::getPoseTargets(const std::string& end_effector_link) const
1900 {
1901  return impl_->getPoseTargets(end_effector_link);
1902 }
1903 
1904 namespace
1905 {
1906 inline void transformPose(const tf2_ros::Buffer& tf_buffer, const std::string& desired_frame,
1907  geometry_msgs::msg::PoseStamped& target)
1908 {
1909  if (desired_frame != target.header.frame_id)
1910  {
1911  geometry_msgs::msg::PoseStamped target_in(target);
1912  tf_buffer.transform(target_in, target, desired_frame);
1913  // we leave the stamp to ros::Time(0) on purpose
1914  target.header.stamp = rclcpp::Time(0);
1915  }
1916 }
1917 } // namespace
1918 
1919 bool MoveGroupInterface::setPositionTarget(double x, double y, double z, const std::string& end_effector_link)
1920 {
1921  geometry_msgs::msg::PoseStamped target;
1922  if (impl_->hasPoseTarget(end_effector_link))
1923  {
1924  target = getPoseTarget(end_effector_link);
1925  transformPose(*impl_->getTF(), impl_->getPoseReferenceFrame(), target);
1926  }
1927  else
1928  {
1929  target.pose.orientation.x = 0.0;
1930  target.pose.orientation.y = 0.0;
1931  target.pose.orientation.z = 0.0;
1932  target.pose.orientation.w = 1.0;
1933  target.header.frame_id = impl_->getPoseReferenceFrame();
1934  }
1935 
1936  target.pose.position.x = x;
1937  target.pose.position.y = y;
1938  target.pose.position.z = z;
1939  bool result = setPoseTarget(target, end_effector_link);
1940  impl_->setTargetType(POSITION);
1941  return result;
1942 }
1943 
1944 bool MoveGroupInterface::setRPYTarget(double r, double p, double y, const std::string& end_effector_link)
1945 {
1946  geometry_msgs::msg::PoseStamped target;
1947  if (impl_->hasPoseTarget(end_effector_link))
1948  {
1949  target = getPoseTarget(end_effector_link);
1950  transformPose(*impl_->getTF(), impl_->getPoseReferenceFrame(), target);
1951  }
1952  else
1953  {
1954  target.pose.position.x = 0.0;
1955  target.pose.position.y = 0.0;
1956  target.pose.position.z = 0.0;
1957  target.header.frame_id = impl_->getPoseReferenceFrame();
1958  }
1959  tf2::Quaternion q;
1960  q.setRPY(r, p, y);
1961  target.pose.orientation = tf2::toMsg(q);
1962  bool result = setPoseTarget(target, end_effector_link);
1963  impl_->setTargetType(ORIENTATION);
1964  return result;
1965 }
1966 
1967 bool MoveGroupInterface::setOrientationTarget(double x, double y, double z, double w,
1968  const std::string& end_effector_link)
1969 {
1970  geometry_msgs::msg::PoseStamped target;
1971  if (impl_->hasPoseTarget(end_effector_link))
1972  {
1973  target = getPoseTarget(end_effector_link);
1974  transformPose(*impl_->getTF(), impl_->getPoseReferenceFrame(), target);
1975  }
1976  else
1977  {
1978  target.pose.position.x = 0.0;
1979  target.pose.position.y = 0.0;
1980  target.pose.position.z = 0.0;
1981  target.header.frame_id = impl_->getPoseReferenceFrame();
1982  }
1983 
1984  target.pose.orientation.x = x;
1985  target.pose.orientation.y = y;
1986  target.pose.orientation.z = z;
1987  target.pose.orientation.w = w;
1988  bool result = setPoseTarget(target, end_effector_link);
1989  impl_->setTargetType(ORIENTATION);
1990  return result;
1991 }
1992 
1993 void MoveGroupInterface::setPoseReferenceFrame(const std::string& pose_reference_frame)
1994 {
1995  impl_->setPoseReferenceFrame(pose_reference_frame);
1996 }
1997 
1999 {
2000  return impl_->getPoseReferenceFrame();
2001 }
2002 
2004 {
2005  return impl_->getGoalJointTolerance();
2006 }
2007 
2009 {
2010  return impl_->getGoalPositionTolerance();
2011 }
2012 
2014 {
2015  return impl_->getGoalOrientationTolerance();
2016 }
2017 
2019 {
2020  setGoalJointTolerance(tolerance);
2021  setGoalPositionTolerance(tolerance);
2022  setGoalOrientationTolerance(tolerance);
2023 }
2024 
2026 {
2027  impl_->setGoalJointTolerance(tolerance);
2028 }
2029 
2031 {
2032  impl_->setGoalPositionTolerance(tolerance);
2033 }
2034 
2036 {
2037  impl_->setGoalOrientationTolerance(tolerance);
2038 }
2039 
2041 {
2043 }
2044 
2046 {
2047  return impl_->startStateMonitor(wait);
2048 }
2049 
2051 {
2052  moveit::core::RobotStatePtr current_state;
2053  std::vector<double> values;
2054  if (impl_->getCurrentState(current_state))
2055  current_state->copyJointGroupPositions(getName(), values);
2056  return values;
2057 }
2058 
2059 std::vector<double> MoveGroupInterface::getRandomJointValues() const
2060 {
2061  std::vector<double> r;
2063  return r;
2064 }
2065 
2066 geometry_msgs::msg::PoseStamped MoveGroupInterface::getRandomPose(const std::string& end_effector_link) const
2067 {
2068  const std::string& eef = end_effector_link.empty() ? getEndEffectorLink() : end_effector_link;
2069  Eigen::Isometry3d pose;
2070  pose.setIdentity();
2071  if (eef.empty())
2072  {
2073  RCLCPP_ERROR(logger_, "No end-effector specified");
2074  }
2075  else
2076  {
2077  moveit::core::RobotStatePtr current_state;
2078  if (impl_->getCurrentState(current_state))
2079  {
2080  current_state->setToRandomPositions(impl_->getJointModelGroup());
2081  const moveit::core::LinkModel* lm = current_state->getLinkModel(eef);
2082  if (lm)
2083  pose = current_state->getGlobalLinkTransform(lm);
2084  }
2085  }
2086  geometry_msgs::msg::PoseStamped pose_msg;
2087  pose_msg.header.stamp = impl_->getClock()->now();
2088  pose_msg.header.frame_id = impl_->getRobotModel()->getModelFrame();
2089  pose_msg.pose = tf2::toMsg(pose);
2090  return pose_msg;
2091 }
2092 
2093 geometry_msgs::msg::PoseStamped MoveGroupInterface::getCurrentPose(const std::string& end_effector_link) const
2094 {
2095  const std::string& eef = end_effector_link.empty() ? getEndEffectorLink() : end_effector_link;
2096  Eigen::Isometry3d pose;
2097  pose.setIdentity();
2098  if (eef.empty())
2099  {
2100  RCLCPP_ERROR(logger_, "No end-effector specified");
2101  }
2102  else
2103  {
2104  moveit::core::RobotStatePtr current_state;
2105  if (impl_->getCurrentState(current_state))
2106  {
2107  const moveit::core::LinkModel* lm = current_state->getLinkModel(eef);
2108  if (lm)
2109  pose = current_state->getGlobalLinkTransform(lm);
2110  }
2111  }
2112  geometry_msgs::msg::PoseStamped pose_msg;
2113  pose_msg.header.stamp = impl_->getClock()->now();
2114  pose_msg.header.frame_id = impl_->getRobotModel()->getModelFrame();
2115  pose_msg.pose = tf2::toMsg(pose);
2116  return pose_msg;
2117 }
2118 
2119 std::vector<double> MoveGroupInterface::getCurrentRPY(const std::string& end_effector_link) const
2120 {
2121  std::vector<double> result;
2122  const std::string& eef = end_effector_link.empty() ? getEndEffectorLink() : end_effector_link;
2123  if (eef.empty())
2124  {
2125  RCLCPP_ERROR(logger_, "No end-effector specified");
2126  }
2127  else
2128  {
2129  moveit::core::RobotStatePtr current_state;
2130  if (impl_->getCurrentState(current_state))
2131  {
2132  const moveit::core::LinkModel* lm = current_state->getLinkModel(eef);
2133  if (lm)
2134  {
2135  result.resize(3);
2136  geometry_msgs::msg::TransformStamped tfs = tf2::eigenToTransform(current_state->getGlobalLinkTransform(lm));
2137  double pitch, roll, yaw;
2138  tf2::getEulerYPR<geometry_msgs::msg::Quaternion>(tfs.transform.rotation, yaw, pitch, roll);
2139  result[0] = roll;
2140  result[1] = pitch;
2141  result[2] = yaw;
2142  }
2143  }
2144  }
2145  return result;
2146 }
2147 
2148 const std::vector<std::string>& MoveGroupInterface::getActiveJoints() const
2149 {
2150  return impl_->getJointModelGroup()->getActiveJointModelNames();
2151 }
2152 
2153 const std::vector<std::string>& MoveGroupInterface::getJoints() const
2154 {
2155  return impl_->getJointModelGroup()->getJointModelNames();
2156 }
2157 
2159 {
2160  return impl_->getJointModelGroup()->getVariableCount();
2161 }
2162 
2163 moveit::core::RobotStatePtr MoveGroupInterface::getCurrentState(double wait) const
2164 {
2165  moveit::core::RobotStatePtr current_state;
2166  impl_->getCurrentState(current_state, wait);
2167  return current_state;
2168 }
2169 
2170 void MoveGroupInterface::rememberJointValues(const std::string& name, const std::vector<double>& values)
2171 {
2172  remembered_joint_values_[name] = values;
2173 }
2174 
2176 {
2177  remembered_joint_values_.erase(name);
2178 }
2179 
2181 {
2182  impl_->can_look_ = flag;
2183  RCLCPP_DEBUG(logger_, "Looking around: %s", flag ? "yes" : "no");
2184 }
2185 
2187 {
2188  if (attempts < 0)
2189  {
2190  RCLCPP_ERROR(logger_, "Tried to set negative number of look-around attempts");
2191  }
2192  else
2193  {
2194  RCLCPP_DEBUG_STREAM(logger_, "Look around attempts: " << attempts);
2195  impl_->look_around_attempts_ = attempts;
2196  }
2197 }
2198 
2200 {
2201  impl_->can_replan_ = flag;
2202  RCLCPP_DEBUG(logger_, "Replanning: %s", flag ? "yes" : "no");
2203 }
2204 
2206 {
2207  if (attempts < 0)
2208  {
2209  RCLCPP_ERROR(logger_, "Tried to set negative number of replan attempts");
2210  }
2211  else
2212  {
2213  RCLCPP_DEBUG_STREAM(logger_, "Replan Attempts: " << attempts);
2214  impl_->replan_attempts_ = attempts;
2215  }
2216 }
2217 
2219 {
2220  if (delay < 0.0)
2221  {
2222  RCLCPP_ERROR(logger_, "Tried to set negative replan delay");
2223  }
2224  else
2225  {
2226  RCLCPP_DEBUG_STREAM(logger_, "Replan Delay: " << delay);
2227  impl_->replan_delay_ = delay;
2228  }
2229 }
2230 
2231 std::vector<std::string> MoveGroupInterface::getKnownConstraints() const
2232 {
2233  return impl_->getKnownConstraints();
2234 }
2235 
2236 moveit_msgs::msg::Constraints MoveGroupInterface::getPathConstraints() const
2237 {
2238  return impl_->getPathConstraints();
2239 }
2240 
2241 bool MoveGroupInterface::setPathConstraints(const std::string& constraint)
2242 {
2243  return impl_->setPathConstraints(constraint);
2244 }
2245 
2246 void MoveGroupInterface::setPathConstraints(const moveit_msgs::msg::Constraints& constraint)
2247 {
2248  impl_->setPathConstraints(constraint);
2249 }
2250 
2252 {
2253  impl_->clearPathConstraints();
2254 }
2255 
2256 moveit_msgs::msg::TrajectoryConstraints MoveGroupInterface::getTrajectoryConstraints() const
2257 {
2258  return impl_->getTrajectoryConstraints();
2259 }
2260 
2261 void MoveGroupInterface::setTrajectoryConstraints(const moveit_msgs::msg::TrajectoryConstraints& constraint)
2262 {
2263  impl_->setTrajectoryConstraints(constraint);
2264 }
2265 
2267 {
2268  impl_->clearTrajectoryConstraints();
2269 }
2270 
2271 void MoveGroupInterface::setConstraintsDatabase(const std::string& host, unsigned int port)
2272 {
2273  impl_->initializeConstraintsStorage(host, port);
2274 }
2275 
2276 void MoveGroupInterface::setWorkspace(double minx, double miny, double minz, double maxx, double maxy, double maxz)
2277 {
2278  impl_->setWorkspace(minx, miny, minz, maxx, maxy, maxz);
2279 }
2280 
2283 {
2284  impl_->setPlanningTime(seconds);
2285 }
2286 
2289 {
2290  return impl_->getPlanningTime();
2291 }
2292 
2294 {
2295  impl_->setSupportSurfaceName(name);
2296 }
2297 
2298 const std::string& MoveGroupInterface::getPlanningFrame() const
2299 {
2300  return impl_->getRobotModel()->getModelFrame();
2301 }
2302 
2303 const std::vector<std::string>& MoveGroupInterface::getJointModelGroupNames() const
2304 {
2305  return impl_->getRobotModel()->getJointModelGroupNames();
2306 }
2307 
2308 bool MoveGroupInterface::attachObject(const std::string& object, const std::string& link)
2309 {
2310  return attachObject(object, link, std::vector<std::string>());
2311 }
2312 
2313 bool MoveGroupInterface::attachObject(const std::string& object, const std::string& link,
2314  const std::vector<std::string>& touch_links)
2315 {
2316  return impl_->attachObject(object, link, touch_links);
2317 }
2318 
2319 bool MoveGroupInterface::detachObject(const std::string& name)
2320 {
2321  return impl_->detachObject(name);
2322 }
2323 
2325 {
2326  impl_->constructMotionPlanRequest(goal_out);
2327 }
2328 
2329 } // namespace planning_interface
2330 } // namespace moveit
const std::vector< std::string > & getLinkModelNames() const
Get the names of the links that are part of this joint group.
bool isChain() const
Check if this group is a linear chain.
const std::string & getName() const
Get the name of the joint group.
void getVariableRandomPositions(random_numbers::RandomNumberGenerator &rng, double *values) const
Compute random values for the state of the joint group.
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...
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 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 > & getVariableNames() const
Get the names of the variables that make up the joints included in this group. The number of returned...
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)
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...
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
Definition: joint_model.h:117
std::size_t getVariableCount() const
Get the number of variables that describe this joint.
Definition: joint_model.h:210
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...
Definition: robot_state.h:583
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...
Definition: robot_state.h:669
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.
Definition: robot_state.h:1562
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)
Definition: robot_state.h:515
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...
Definition: transforms.cpp:70
void constructGoal(moveit_msgs::action::MoveGroup::Goal &goal) const
double computeCartesianPath(const std::vector< geometry_msgs::msg::Pose > &waypoints, double step, double jump_threshold, moveit_msgs::msg::RobotTrajectory &msg, const moveit_msgs::msg::Constraints &path_constraints, bool avoid_collisions, moveit_msgs::msg::MoveItErrorCodes &error_code)
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)
rclcpp_action::Client< moveit_msgs::action::MoveGroup > & getMoveGroupClient() const
bool attachObject(const std::string &object, const std::string &link, const std::vector< std::string > &touch_links)
void initializeConstraintsStorage(const std::string &host, unsigned int port)
void setPathConstraints(const moveit_msgs::msg::Constraints &constraint)
std::map< std::string, std::string > getPlannerParams(const std::string &planner_id, const std::string &group="")
const geometry_msgs::msg::PoseStamped & getPoseTarget(const std::string &end_effector_link) const
void setTrajectoryConstraints(const moveit_msgs::msg::TrajectoryConstraints &constraint)
void constructMotionPlanRequest(moveit_msgs::msg::MotionPlanRequest &request) const
moveit_msgs::msg::TrajectoryConstraints getTrajectoryConstraints() 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)
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)
bool setJointValueTarget(const geometry_msgs::msg::Pose &eef_pose, const std::string &end_effector_link, const std::string &frame, bool approx)
const std::vector< geometry_msgs::msg::PoseStamped > & getPoseTargets(const std::string &end_effector_link) const
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.
double computeCartesianPath(const std::vector< geometry_msgs::msg::Pose > &waypoints, double eef_step, double jump_threshold, 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...
std::vector< double > getRandomJointValues() const
Get random joint values for the joints planned for by this instance (see getJoints())
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)
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 ...
MoveGroupInterface & operator=(const MoveGroupInterface &)=delete
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.
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::vector< geometry_msgs::msg::PoseStamped > & getPoseTargets(const std::string &end_effector_link="") const
moveit_msgs::msg::TrajectoryConstraints getTrajectoryConstraints() const
const std::vector< std::string > & getLinkNames() const
Get vector of names of links available in move group.
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 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
planning_interface::MotionPlanResponse plan(std::shared_ptr< moveit_cpp::PlanningComponent > &planning_component, std::shared_ptr< moveit_cpp::PlanningComponent::PlanRequestParameters > &single_plan_parameters, std::shared_ptr< moveit_cpp::PlanningComponent::MultiPipelinePlanRequestParameters > &multi_plan_parameters, std::shared_ptr< planning_scene::PlanningScene > &planning_scene, std::optional< const moveit::planning_pipeline_interfaces::SolutionSelectionFunction > solution_selection_function, std::optional< moveit::planning_pipeline_interfaces::StoppingCriterionFunction > stopping_criterion_callback)
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
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
Definition: logger.cpp:79
This namespace includes the base class for MoveIt planners.
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
std::string append(const std::string &left, const std::string &right)
name
Definition: setup.py:7
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 messasges)