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