42 #include <moveit_msgs/DisplayTrajectory.h>
43 #include <visualization_msgs/MarkerArray.h>
44 #include <boost/tokenizer.hpp>
45 #include <boost/algorithm/string/join.hpp>
54 const std::string& planner_plugin_param_name,
55 const std::string& adapter_plugins_param_name)
56 : active_{
false }, pipeline_nh_(pipeline_nh), private_nh_(
"~"), robot_model_(model)
59 if (pipeline_nh_.getParam(planner_plugin_param_name, planner))
60 planner_plugin_name_ = planner;
63 if (pipeline_nh_.getParam(adapter_plugins_param_name, adapters))
65 boost::char_separator<char> sep(
" ");
66 boost::tokenizer<boost::char_separator<char>> tok(adapters, sep);
67 for (boost::tokenizer<boost::char_separator<char>>::iterator beg = tok.begin(); beg != tok.end(); ++beg)
68 adapter_plugin_names_.push_back(*beg);
76 const std::string& planner_plugin_name,
77 const std::vector<std::string>& adapter_plugin_names)
79 , pipeline_nh_(pipeline_nh)
81 , planner_plugin_name_(planner_plugin_name)
82 , adapter_plugin_names_(adapter_plugin_names)
90 check_solution_paths_ =
false;
91 publish_received_requests_ =
false;
92 display_computed_motion_plans_ =
false;
97 planner_plugin_loader_ = std::make_unique<pluginlib::ClassLoader<planning_interface::PlannerManager>>(
98 "moveit_core",
"planning_interface::PlannerManager");
102 ROS_FATAL_STREAM(
"Exception while creating planning plugin loader " << ex.what());
105 std::vector<std::string> classes;
106 if (planner_plugin_loader_)
107 classes = planner_plugin_loader_->getDeclaredClasses();
108 if (planner_plugin_name_.empty() && classes.size() == 1)
110 planner_plugin_name_ = classes[0];
111 ROS_INFO(
"No '~planning_plugin' parameter specified, but only '%s' planning plugin is available. Using that one.",
112 planner_plugin_name_.c_str());
114 if (planner_plugin_name_.empty() && classes.size() > 1)
116 planner_plugin_name_ = classes[0];
117 ROS_INFO(
"Multiple planning plugins available. You should specify the '~planning_plugin' parameter. Using '%s' for "
119 planner_plugin_name_.c_str());
123 planner_instance_ = planner_plugin_loader_->createUniqueInstance(planner_plugin_name_);
124 if (!planner_instance_->initialize(robot_model_, pipeline_nh_.getNamespace()))
125 throw std::runtime_error(
"Unable to initialize planning plugin");
126 ROS_INFO_STREAM(
"Using planning interface '" << planner_instance_->getDescription() <<
"'");
131 << planner_plugin_name_ <<
"': " << ex.what() << std::endl
132 <<
"Available plugins: " << boost::algorithm::join(classes,
", "));
136 if (!adapter_plugin_names_.empty())
138 std::vector<planning_request_adapter::PlanningRequestAdapterConstPtr> ads;
141 adapter_plugin_loader_ =
142 std::make_unique<pluginlib::ClassLoader<planning_request_adapter::PlanningRequestAdapter>>(
143 "moveit_core",
"planning_request_adapter::PlanningRequestAdapter");
147 ROS_ERROR_STREAM(
"Exception while creating planning plugin loader " << ex.what());
150 if (adapter_plugin_loader_)
151 for (
const std::string& adapter_plugin_name : adapter_plugin_names_)
153 planning_request_adapter::PlanningRequestAdapterPtr ad;
156 ad = adapter_plugin_loader_->createUniqueInstance(adapter_plugin_name);
160 ROS_ERROR_STREAM(
"Exception while loading planning adapter plugin '" << adapter_plugin_name
161 <<
"': " << ex.what());
165 ad->initialize(pipeline_nh_);
166 ads.push_back(std::move(ad));
171 adapter_chain_ = std::make_unique<planning_request_adapter::PlanningRequestAdapterChain>();
172 for (planning_request_adapter::PlanningRequestAdapterConstPtr& ad : ads)
174 ROS_INFO_STREAM(
"Using planning request adapter '" << ad->getDescription() <<
"'");
175 adapter_chain_->addAdapter(ad);
179 displayComputedMotionPlans(
true);
180 checkSolutionPaths(
true);
185 if (display_computed_motion_plans_ && !flag)
186 display_path_publisher_.shutdown();
187 else if (!display_computed_motion_plans_ && flag)
188 display_path_publisher_ = private_nh_.advertise<moveit_msgs::DisplayTrajectory>(DISPLAY_PATH_TOPIC, 10,
true);
189 display_computed_motion_plans_ = flag;
194 if (publish_received_requests_ && !flag)
195 received_request_publisher_.shutdown();
196 else if (!publish_received_requests_ && flag)
197 received_request_publisher_ =
198 private_nh_.advertise<moveit_msgs::MotionPlanRequest>(MOTION_PLAN_REQUEST_TOPIC, 10,
true);
199 publish_received_requests_ = flag;
204 if (check_solution_paths_ && !flag)
205 contacts_publisher_.shutdown();
206 else if (!check_solution_paths_ && flag)
207 contacts_publisher_ = private_nh_.advertise<visualization_msgs::MarkerArray>(MOTION_CONTACTS_TOPIC, 100,
true);
208 check_solution_paths_ = flag;
215 std::vector<std::size_t> dummy;
222 std::vector<std::size_t>& adapter_added_state_index)
const
228 if (publish_received_requests_)
229 received_request_publisher_.publish(request);
230 adapter_added_state_index.clear();
232 if (!planner_instance_)
234 ROS_ERROR(
"No planning plugin loaded. Cannot plan.");
243 for (moveit_msgs::Constraints& constraint : req.goal_constraints)
251 solved = adapter_chain_->adaptAndPlan(planner_instance_,
planning_scene, req, res, adapter_added_state_index);
252 if (!adapter_added_state_index.empty())
254 std::stringstream ss;
255 for (std::size_t added_index : adapter_added_state_index)
256 ss << added_index <<
" ";
257 ROS_INFO(
"Planning adapters have added states at index positions: [ %s]", ss.str().c_str());
262 planning_interface::PlanningContextPtr context =
264 solved = context ? context->solve(res) :
false;
267 catch (std::exception& ex)
269 ROS_ERROR(
"Exception caught: '%s'", ex.what());
278 std::size_t state_count = res.
trajectory_->getWayPointCount();
279 ROS_DEBUG_STREAM(
"Motion planner reported a solution path with " << state_count <<
" states");
280 if (check_solution_paths_)
282 visualization_msgs::MarkerArray arr;
283 visualization_msgs::Marker m;
284 m.action = visualization_msgs::Marker::DELETEALL;
285 arr.markers.push_back(m);
287 std::vector<std::size_t>
index;
292 bool problem =
false;
293 for (std::size_t i = 0; i <
index.size() && !problem; ++i)
296 for (std::size_t added_index : adapter_added_state_index)
297 if (
index[i] == added_index)
308 ROS_DEBUG(
"It appears the robot is starting at an invalid state, but that is ok.");
312 res.
error_code_.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN;
315 std::stringstream ss;
316 for (std::size_t it :
index)
318 ROS_ERROR_STREAM(
"Computed path is not valid. Invalid states at index locations: [ "
319 << ss.str() <<
"] out of " << state_count
320 <<
". Explanations follow in command line. Contacts are published on "
321 << private_nh_.resolveName(MOTION_CONTACTS_TOPIC));
324 for (std::size_t it :
index)
328 planning_scene->isStateValid(robot_state, req.path_constraints, req.group_name,
true);
340 visualization_msgs::MarkerArray arr_i;
343 arr.markers.insert(arr.markers.end(), arr_i.markers.begin(), arr_i.markers.end());
350 ROS_DEBUG(
"Planned path was found to be valid, except for states that were added by planning request "
351 "adapters, but that is ok.");
354 ROS_DEBUG(
"Planned path was found to be valid when rechecked");
355 contacts_publisher_.publish(arr);
360 if (display_computed_motion_plans_ && solved)
362 moveit_msgs::DisplayTrajectory disp;
363 disp.model_id = robot_model_->getName();
364 disp.trajectory.resize(1);
365 res.
trajectory_->getRobotTrajectoryMsg(disp.trajectory[0]);
367 display_path_publisher_.publish(disp);
374 bool stacked_constraints =
false;
375 if (req.path_constraints.position_constraints.size() > 1 || req.path_constraints.orientation_constraints.size() > 1)
376 stacked_constraints =
true;
377 for (
const auto& constraint : req.goal_constraints)
379 if (constraint.position_constraints.size() > 1 || constraint.orientation_constraints.size() > 1)
380 stacked_constraints =
true;
382 if (stacked_constraints)
383 ROS_WARN(
"More than one constraint is set. If your move_group does not have multiple end effectors/arms, this is "
384 "unusual. Are you using a move_group_interface and forgetting to call clearPoseTargets() or "
389 return solved && valid;
394 if (planner_instance_)
395 planner_instance_->terminate();