55 const std::unordered_map<std::string, planning_pipeline::PlanningPipelinePtr>& planning_pipelines)
58 auto it = planning_pipelines.find(motion_plan_request.pipeline_id);
59 if (it == planning_pipelines.end())
61 RCLCPP_ERROR(
getLogger(),
"No planning pipeline available for name '%s'", motion_plan_request.pipeline_id.c_str());
62 motion_plan_response.
error_code = moveit::core::MoveItErrorCode::FAILURE;
63 return motion_plan_response;
65 const planning_pipeline::PlanningPipelinePtr pipeline = it->second;
66 if (!pipeline->generatePlan(
planning_scene, motion_plan_request, motion_plan_response))
68 if ((motion_plan_response.
error_code.val == moveit::core::MoveItErrorCode::SUCCESS) ||
69 (motion_plan_response.
error_code.val == moveit::core::MoveItErrorCode::UNDEFINED))
71 RCLCPP_ERROR(
getLogger(),
"Planning pipeline '%s' failed to plan, but did not set an error code",
72 motion_plan_request.pipeline_id.c_str());
73 motion_plan_response.
error_code = moveit::core::MoveItErrorCode::FAILURE;
76 return motion_plan_response;
80 const std::vector<::planning_interface::MotionPlanRequest>& motion_plan_requests,
82 const std::unordered_map<std::string, planning_pipeline::PlanningPipelinePtr>& planning_pipelines,
88 std::vector<std::thread> planning_threads;
89 planning_threads.reserve(motion_plan_requests.size());
93 const auto hardware_concurrency = std::thread::hardware_concurrency();
94 if (motion_plan_requests.size() > hardware_concurrency && hardware_concurrency != 0)
97 "More parallel planning problems defined ('%ld') than possible to solve concurrently with the "
99 motion_plan_requests.size(), hardware_concurrency);
103 for (
const auto& request : motion_plan_requests)
105 auto planning_thread = std::thread([&]() {
112 catch (
const std::exception& e)
114 RCLCPP_ERROR(
getLogger(),
"Planning pipeline '%s' threw exception '%s'", request.pipeline_id.c_str(), e.what());
116 plan_solution.error_code = moveit::core::MoveItErrorCode::FAILURE;
118 plan_solution.planner_id = request.planner_id;
119 plan_responses_container.pushBack(plan_solution);
121 if (stopping_criterion_callback !=
nullptr)
123 if (stopping_criterion_callback(plan_responses_container, motion_plan_requests))
126 RCLCPP_INFO(
getLogger(),
"Stopping criterion met: Terminating planning pipelines that are still active");
127 for (
const auto& request : motion_plan_requests)
137 catch (
const std::out_of_range&)
139 RCLCPP_WARN(
getLogger(),
"Cannot terminate pipeline '%s' because no pipeline with that name exists",
140 request.pipeline_id.c_str());
146 planning_threads.push_back(std::move(planning_thread));
150 for (
auto& planning_thread : planning_threads)
152 if (planning_thread.joinable())
154 planning_thread.join();
159 if (solution_selection_function)
161 std::vector<::planning_interface::MotionPlanResponse> solutions;
162 solutions.reserve(1);
163 solutions.push_back(solution_selection_function(plan_responses_container.getSolutions()));
168 return plan_responses_container.getSolutions();
173 const moveit::core::RobotModelConstPtr& robot_model,
const rclcpp::Node::SharedPtr& node,
174 const std::string& parameter_namespace)
176 std::unordered_map<std::string, planning_pipeline::PlanningPipelinePtr> planning_pipelines;
177 for (
const auto& planning_pipeline_name : pipeline_names)
180 if (planning_pipelines.count(planning_pipeline_name) > 0)
182 RCLCPP_WARN(
getLogger(),
"Skipping duplicate entry for planning pipeline '%s'.", planning_pipeline_name.c_str());
187 planning_pipeline::PlanningPipelinePtr pipeline = std::make_shared<planning_pipeline::PlanningPipeline>(
188 robot_model, node, parameter_namespace + planning_pipeline_name);
192 RCLCPP_ERROR(
getLogger(),
"Failed to initialize planning pipeline '%s'.", planning_pipeline_name.c_str());
196 planning_pipelines[planning_pipeline_name] = pipeline;
199 return planning_pipelines;
::planning_interface::MotionPlanResponse planWithSinglePipeline(const ::planning_interface::MotionPlanRequest &motion_plan_request, const ::planning_scene::PlanningSceneConstPtr &planning_scene, const std::unordered_map< std::string, planning_pipeline::PlanningPipelinePtr > &planning_pipelines)
Function to calculate the MotionPlanResponse for a given MotionPlanRequest and a PlanningScene.
std::unordered_map< std::string, planning_pipeline::PlanningPipelinePtr > createPlanningPipelineMap(const std::vector< std::string > &pipeline_names, const moveit::core::RobotModelConstPtr &robot_model, const rclcpp::Node::SharedPtr &node, const std::string ¶meter_namespace=std::string())
Utility function to create a map of named planning pipelines.
const std::vector<::planning_interface::MotionPlanResponse > planWithParallelPipelines(const std::vector<::planning_interface::MotionPlanRequest > &motion_plan_requests, const ::planning_scene::PlanningSceneConstPtr &planning_scene, const std::unordered_map< std::string, planning_pipeline::PlanningPipelinePtr > &planning_pipelines, const StoppingCriterionFunction &stopping_criterion_callback=nullptr, const SolutionSelectionFunction &solution_selection_function=nullptr)
Function to solve multiple planning problems in parallel threads with multiple planning pipelines at ...