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