moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
move_group_capability.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2012, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Author: Ioan Sucan */
36
41#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
43
44#include <sstream>
45#include <string>
46
47namespace move_group
48{
49namespace
50{
51rclcpp::Logger getLogger()
52{
53 return moveit::getLogger("moveit.ros.move_group.capability");
54}
55} // namespace
56
57void MoveGroupCapability::setContext(const MoveGroupContextPtr& context)
58{
59 context_ = context;
60}
61
62void MoveGroupCapability::convertToMsg(const std::vector<plan_execution::ExecutableTrajectory>& trajectory,
63 moveit_msgs::msg::RobotState& first_state_msg,
64 std::vector<moveit_msgs::msg::RobotTrajectory>& trajectory_msg) const
65{
66 if (!trajectory.empty())
67 {
68 bool first = true;
69 trajectory_msg.resize(trajectory.size());
70 for (std::size_t i = 0; i < trajectory.size(); ++i)
71 {
72 if (trajectory[i].trajectory)
73 {
74 if (first && !trajectory[i].trajectory->empty())
75 {
76 moveit::core::robotStateToRobotStateMsg(trajectory[i].trajectory->getFirstWayPoint(), first_state_msg);
77 first = false;
78 }
79 trajectory[i].trajectory->getRobotTrajectoryMsg(trajectory_msg[i]);
80 }
81 }
82 }
83}
84
85void MoveGroupCapability::convertToMsg(const robot_trajectory::RobotTrajectoryPtr& trajectory,
86 moveit_msgs::msg::RobotState& first_state_msg,
87 moveit_msgs::msg::RobotTrajectory& trajectory_msg) const
88{
89 if (trajectory && !trajectory->empty())
90 {
91 moveit::core::robotStateToRobotStateMsg(trajectory->getFirstWayPoint(), first_state_msg);
92 trajectory->getRobotTrajectoryMsg(trajectory_msg);
93 }
94}
95
96void MoveGroupCapability::convertToMsg(const std::vector<plan_execution::ExecutableTrajectory>& trajectory,
97 moveit_msgs::msg::RobotState& first_state_msg,
98 moveit_msgs::msg::RobotTrajectory& trajectory_msg) const
99{
100 if (trajectory.size() > 1)
101 {
102 RCLCPP_ERROR_STREAM(getLogger(),
103 "Internal logic error: trajectory component ignored. !!! THIS IS A SERIOUS ERROR !!!");
104 }
105 if (!trajectory.empty())
106 {
107 convertToMsg(trajectory[0].trajectory, first_state_msg, trajectory_msg);
108 }
109}
110
113{
115 r.start_state = moveit_msgs::msg::RobotState();
116 r.start_state.is_diff = true;
117 RCLCPP_WARN(getLogger(),
118 "Execution of motions should always start at the robot's current state. Ignoring the state supplied as "
119 "start state in the motion planning request");
120 return r;
121}
122
123moveit_msgs::msg::PlanningScene
124MoveGroupCapability::clearSceneRobotState(const moveit_msgs::msg::PlanningScene& scene) const
125{
126 moveit_msgs::msg::PlanningScene r = scene;
127 r.robot_state = moveit_msgs::msg::RobotState();
128 r.robot_state.is_diff = true;
129 RCLCPP_WARN(getLogger(),
130 "Execution of motions should always start at the robot's current state. Ignoring the state supplied as "
131 "difference in the planning scene diff");
132 return r;
133}
134
135std::string MoveGroupCapability::getActionResultString(const moveit_msgs::msg::MoveItErrorCodes& error_code,
136 bool planned_trajectory_empty, bool plan_only)
137{
138 switch (error_code.val)
139 {
140 case moveit_msgs::msg::MoveItErrorCodes::SUCCESS:
141 if (planned_trajectory_empty)
142 {
143 return "Requested path and goal constraints are already met.";
144 }
145 else
146 {
147 if (plan_only)
148 {
149 return "Motion plan was computed successfully.";
150 }
151 else
152 {
153 return "Solution was found and executed.";
154 }
155 }
156 case moveit_msgs::msg::MoveItErrorCodes::INVALID_GROUP_NAME:
157 return "Invalid group in motion plan request";
158 case moveit_msgs::msg::MoveItErrorCodes::PLANNING_FAILED:
159 case moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN:
160 if (planned_trajectory_empty)
161 {
162 return "No motion plan found. No execution attempted.";
163 }
164 else
165 {
166 return "Motion plan was found but it seems to be invalid (possibly due to postprocessing). Not executing.";
167 }
168 case moveit_msgs::msg::MoveItErrorCodes::UNABLE_TO_AQUIRE_SENSOR_DATA:
169 return "Motion plan was found but it seems to be too costly and looking around did not help.";
170 case moveit_msgs::msg::MoveItErrorCodes::MOTION_PLAN_INVALIDATED_BY_ENVIRONMENT_CHANGE:
171 return "Solution found but the environment changed during execution and the path was aborted";
172 default:
173 return moveit::core::errorCodeToString(error_code);
174 }
175}
176
178{
179 switch (state)
180 {
181 case IDLE:
182 return "IDLE";
183 case PLANNING:
184 return "PLANNING";
185 case MONITOR:
186 return "MONITOR";
187 case LOOK:
188 return "LOOK";
189 default:
190 return "UNKNOWN";
191 }
192}
193
194bool MoveGroupCapability::performTransform(geometry_msgs::msg::PoseStamped& pose_msg,
195 const std::string& target_frame) const
196{
197 if (!context_ || !context_->planning_scene_monitor_->getTFClient())
198 return false;
199 if (pose_msg.header.frame_id == target_frame)
200 return true;
201 if (pose_msg.header.frame_id.empty())
202 {
203 pose_msg.header.frame_id = target_frame;
204 return true;
205 }
206
207 try
208 {
209 geometry_msgs::msg::TransformStamped common_tf = context_->planning_scene_monitor_->getTFClient()->lookupTransform(
210 pose_msg.header.frame_id, target_frame, rclcpp::Time(0.0));
211 geometry_msgs::msg::PoseStamped pose_msg_in(pose_msg);
212 pose_msg_in.header.stamp = common_tf.header.stamp;
213 context_->planning_scene_monitor_->getTFClient()->transform(pose_msg_in, pose_msg, target_frame);
214 }
215 catch (tf2::TransformException& ex)
216 {
217 RCLCPP_ERROR(getLogger(), "TF Problem: %s", ex.what());
218 return false;
219 }
220 return true;
221}
222
223planning_pipeline::PlanningPipelinePtr MoveGroupCapability::resolvePlanningPipeline(const std::string& pipeline_id) const
224{
225 if (pipeline_id.empty())
226 {
227 // Without specified planning pipeline we use the default
228 return context_->planning_pipeline_;
229 }
230 else
231 {
232 // Attempt to get the planning pipeline for the specified identifier
233 try
234 {
235 auto pipeline = context_->moveit_cpp_->getPlanningPipelines().at(pipeline_id);
236 RCLCPP_INFO(getLogger(), "Using planning pipeline '%s'", pipeline_id.c_str());
237 return pipeline;
238 }
239 catch (const std::out_of_range&)
240 {
241 RCLCPP_WARN(getLogger(), "Couldn't find requested planning pipeline '%s'", pipeline_id.c_str());
242 }
243 }
244
245 return planning_pipeline::PlanningPipelinePtr();
246}
247
248} // namespace move_group
void setContext(const MoveGroupContextPtr &context)
moveit_msgs::msg::PlanningScene clearSceneRobotState(const moveit_msgs::msg::PlanningScene &scene) const
planning_interface::MotionPlanRequest clearRequestStartState(const planning_interface::MotionPlanRequest &request) const
void convertToMsg(const std::vector< plan_execution::ExecutableTrajectory > &trajectory, moveit_msgs::msg::RobotState &first_state_msg, std::vector< moveit_msgs::msg::RobotTrajectory > &trajectory_msg) const
bool performTransform(geometry_msgs::msg::PoseStamped &pose_msg, const std::string &target_frame) const
std::string getActionResultString(const moveit_msgs::msg::MoveItErrorCodes &error_code, bool planned_trajectory_empty, bool plan_only)
std::string stateToStr(MoveGroupState state) const
planning_pipeline::PlanningPipelinePtr resolvePlanningPipeline(const std::string &pipeline_id) const
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::string errorCodeToString(const MoveItErrorCode &error_code)
Convenience function to translated error message into string.
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
Definition logger.cpp:79
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest