Skip to content

Commit 8eb93dc

Browse files
committed
Merge branch 'cleanup-moveit#450'
2 parents 21787b3 + d0ac68e commit 8eb93dc

File tree

2 files changed

+79
-116
lines changed

2 files changed

+79
-116
lines changed

core/include/moveit/task_constructor/solvers/pipeline_planner.h

Lines changed: 36 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -61,63 +61,52 @@ class PipelinePlanner : public PlannerInterface
6161
public:
6262
/** Simple Constructor to use only a single pipeline
6363
* \param [in] node ROS 2 node
64-
* \param [in] pipeline_name Name of the planning pipeline to be used. This is also the assumed namespace where the
65-
* parameters of this pipeline can be found \param [in] planner_id Planner id to be used for planning
64+
* \param [in] pipeline_name Name of the planning pipeline to be used.
65+
* This is also the assumed namespace where the parameters of this pipeline can be found
66+
* \param [in] planner_id Planner id to be used for planning. Empty string means default.
6667
*/
6768
PipelinePlanner(const rclcpp::Node::SharedPtr& node, const std::string& pipeline_name = "ompl",
68-
const std::string& planner_id = "");
69-
70-
[[deprecated("Deprecated: Use new constructor implementations.")]] // clang-format off
71-
PipelinePlanner(const planning_pipeline::PlanningPipelinePtr& /*planning_pipeline*/){};
69+
const std::string& planner_id = "")
70+
: PipelinePlanner(node, { { pipeline_name, planner_id } }) {}
7271

7372
/** \brief Constructor
7473
* \param [in] node ROS 2 node
75-
* \param [in] pipeline_id_planner_id_map A map containing pairs of planning pipeline name and planner plugin name
76-
* for the planning requests
77-
* \param [in] planning_pipelines Optional: A map with the pipeline names and initialized corresponding planning
78-
* pipelines
79-
* \param [in] stopping_criterion_callback Callback function to stop parallel planning pipeline according to a user defined criteria
80-
* \param [in] solution_selection_function Callback function to choose the best solution when multiple pipelines are used
74+
* \param [in] pipeline_id_planner_id_map map containing pairs of pipeline and plugin names to be used for planning
75+
* \param [in] stopping_criterion_callback callback to decide when to stop parallel planning
76+
* \param [in] solution_selection_function callback to choose the best solution from multiple ran pipelines
8177
*/
82-
PipelinePlanner(const rclcpp::Node::SharedPtr& node,
83-
const std::unordered_map<std::string, std::string>& pipeline_id_planner_id_map,
84-
const std::unordered_map<std::string, planning_pipeline::PlanningPipelinePtr>& planning_pipelines =
85-
std::unordered_map<std::string, planning_pipeline::PlanningPipelinePtr>(),
86-
const moveit::planning_pipeline_interfaces::StoppingCriterionFunction& stopping_criterion_callback = nullptr,
87-
const moveit::planning_pipeline_interfaces::SolutionSelectionFunction& solution_selection_function =
88-
&moveit::planning_pipeline_interfaces::getShortestSolution);
89-
90-
[[deprecated("Replaced with setPlannerId(pipeline_name, planner_id)")]] // clang-format off
91-
void setPlannerId(const std::string& /*planner*/) { /* Do nothing */
92-
}
93-
94-
/** \brief Set the planner id for a specific planning pipeline for the planning requests
95-
* \param [in] pipeline_name Name of the planning pipeline for which the planner id is set
96-
* \param [in] planner_id Name of the planner ID that should be used by the planning pipeline
78+
PipelinePlanner(
79+
const rclcpp::Node::SharedPtr& node,
80+
const std::unordered_map<std::string, std::string>& pipeline_id_planner_id_map,
81+
const moveit::planning_pipeline_interfaces::StoppingCriterionFunction& stopping_criterion_callback = nullptr,
82+
const moveit::planning_pipeline_interfaces::SolutionSelectionFunction& solution_selection_function =
83+
&moveit::planning_pipeline_interfaces::getShortestSolution);
84+
85+
/** \brief Set the planner id for a specific planning pipeline
86+
* \param [in] pipeline_name Name of the to-be-used planning pipeline
87+
* \param [in] planner_id Name of the to-be-used planner ID
9788
* \return true if the pipeline exists and the corresponding ID is set successfully
9889
*/
9990
bool setPlannerId(const std::string& pipeline_name, const std::string& planner_id);
10091

10192
/** \brief Set stopping criterion function for parallel planning
10293
* \param [in] stopping_criterion_callback New stopping criterion function that will be used
103-
*/
104-
void setStoppingCriterionFunction(const moveit::planning_pipeline_interfaces::StoppingCriterionFunction& stopping_criterion_callback);
94+
*/
95+
void setStoppingCriterionFunction(
96+
const moveit::planning_pipeline_interfaces::StoppingCriterionFunction& stopping_criterion_callback);
10597

10698
/** \brief Set solution selection function for parallel planning
10799
* \param [in] solution_selection_function New solution selection that will be used
108-
*/
109-
void setSolutionSelectionFunction(const moveit::planning_pipeline_interfaces::SolutionSelectionFunction& solution_selection_function);
110-
111-
/** \brief This function is called when an MTC task that uses this solver is initialized. If no pipelines are
112-
* configured when this function is invoked, the planning pipelines named in the 'pipeline_id_planner_id_map' are
113-
* initialized with the given robot model.
114-
* \param [in] robot_model A robot model that is used to initialize the
115-
* planning pipelines of this solver
100+
*/
101+
void setSolutionSelectionFunction(
102+
const moveit::planning_pipeline_interfaces::SolutionSelectionFunction& solution_selection_function);
103+
104+
/** \brief If not yet done, initialize pipelines from pipeline_id_planner_id_map
105+
* \param [in] robot_model robot model used to initialize the planning pipelines of this solver
116106
*/
117107
void init(const moveit::core::RobotModelConstPtr& robot_model) override;
118108

119-
/**
120-
* \brief Plan a trajectory from a planning scene 'from' to scene 'to'
109+
/** \brief Plan a trajectory from a planning scene 'from' to scene 'to'
121110
* \param [in] from Start planning scene
122111
* \param [in] to Goal planning scene (used to create goal constraints)
123112
* \param [in] joint_model_group Group of joints for which this trajectory is created
@@ -131,7 +120,7 @@ class PipelinePlanner : public PlannerInterface
131120
robot_trajectory::RobotTrajectoryPtr& result,
132121
const moveit_msgs::msg::Constraints& path_constraints = moveit_msgs::msg::Constraints()) override;
133122

134-
/** \brief Plan a trajectory from a planning scene 'from' to a target pose with an offset
123+
/** \brief Plan a trajectory from a planning scene 'from' to a Cartesian target pose with an offset
135124
* \param [in] from Start planning scene
136125
* \param [in] link Link for which a target pose is given
137126
* \param [in] offset Offset to be applied to a given target pose
@@ -149,20 +138,14 @@ class PipelinePlanner : public PlannerInterface
149138
const moveit_msgs::msg::Constraints& path_constraints = moveit_msgs::msg::Constraints()) override;
150139

151140
protected:
152-
/** \brief Function that actually uses the planning pipelines to solve the given planning problem. It is called by
153-
* the public plan function after the goal constraints are generated. This function uses a predefined number of
154-
* planning pipelines in parallel to solve the planning problem and choose the best (user-defined) solution.
141+
/** \brief Actual plan() implementation, targeting the given goal_constraints.
155142
* \param [in] planning_scene Scene for which the planning should be solved
156-
* \param [in] joint_model_group
157-
* Group of joints for which this trajectory is created
158-
* \param [in] goal_constraints Set of constraints that need to
159-
* be satisfied by the solution
143+
* \param [in] joint_model_group Group of joints for which this trajectory is created
144+
* \param [in] goal_constraints Set of constraints that need to be satisfied by the solution
160145
* \param [in] timeout Maximum planning timeout for an individual stage that is using the pipeline planner in seconds
161-
* \param [in] result Reference to the location where the created
162-
* trajectory is stored if planning is successful
163-
* \param [in] path_constraints Path contraints for the planning
164-
* problem
165-
* \return true If the solver found a successful solution for the given planning problem
146+
* \param [in] result Reference to the location where the created trajectory is stored if planning is successful
147+
* \param [in] path_constraints Path contraints for the planning problem
148+
* \return true if the solver found a successful solution for the given planning problem
166149
*/
167150
bool plan(const planning_scene::PlanningSceneConstPtr& planning_scene,
168151
const moveit::core::JointModelGroup* joint_model_group,
@@ -172,18 +155,11 @@ class PipelinePlanner : public PlannerInterface
172155

173156
rclcpp::Node::SharedPtr node_;
174157

175-
/** \brief Map of pipeline names (ids) and their corresponding planner ids. The planning problem is solved for every
176-
* pipeline-planner pair in this map. If no pipelines are passed via constructor argument, the pipeline names are
177-
* used to initialize a set of planning pipelines. */
178-
std::unordered_map<std::string, std::string> pipeline_id_planner_id_map_;
179-
180-
/** \brief Map of pipelines names and planning pipelines. This map is used to quickly search for a requested motion
181-
* planning pipeline when during plan(..) */
158+
/** \brief Map of instantiated (and named) planning pipelines. */
182159
std::unordered_map<std::string, planning_pipeline::PlanningPipelinePtr> planning_pipelines_;
183160

184161
moveit::planning_pipeline_interfaces::StoppingCriterionFunction stopping_criterion_callback_;
185162
moveit::planning_pipeline_interfaces::SolutionSelectionFunction solution_selection_function_;
186-
187163
};
188164
} // namespace solvers
189165
} // namespace task_constructor

core/src/solvers/pipeline_planner.cpp

Lines changed: 43 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -53,28 +53,15 @@ namespace moveit {
5353
namespace task_constructor {
5454
namespace solvers {
5555

56-
PipelinePlanner::PipelinePlanner(const rclcpp::Node::SharedPtr& node, const std::string& pipeline_name,
57-
const std::string& planner_id)
58-
: PipelinePlanner(node, [&]() {
59-
std::unordered_map<std::string, std::string> pipeline_id_planner_id_map;
60-
pipeline_id_planner_id_map[pipeline_name] = planner_id;
61-
return pipeline_id_planner_id_map;
62-
}()) {}
56+
using PipelineMap = std::unordered_map<std::string, std::string>;
6357

6458
PipelinePlanner::PipelinePlanner(
65-
const rclcpp::Node::SharedPtr& node, const std::unordered_map<std::string, std::string>& pipeline_id_planner_id_map,
66-
const std::unordered_map<std::string, planning_pipeline::PlanningPipelinePtr>& planning_pipelines,
59+
const rclcpp::Node::SharedPtr& node, const PipelineMap& pipeline_id_planner_id_map,
6760
const moveit::planning_pipeline_interfaces::StoppingCriterionFunction& stopping_criterion_callback,
6861
const moveit::planning_pipeline_interfaces::SolutionSelectionFunction& solution_selection_function)
6962
: node_(node)
70-
, pipeline_id_planner_id_map_(pipeline_id_planner_id_map)
7163
, stopping_criterion_callback_(stopping_criterion_callback)
7264
, solution_selection_function_(solution_selection_function) {
73-
// If the pipeline name - pipeline map is passed as constructor argument, use it. Otherwise, it will be created in
74-
// the init(..) function
75-
if (!planning_pipelines.empty()) {
76-
planning_pipelines_ = planning_pipelines;
77-
}
7865
// Declare properties of the MotionPlanRequest
7966
properties().declare<uint>("num_planning_attempts", 1u, "number of planning attempts");
8067
properties().declare<moveit_msgs::msg::WorkspaceParameters>(
@@ -84,20 +71,22 @@ PipelinePlanner::PipelinePlanner(
8471
properties().declare<double>("goal_position_tolerance", 1e-4, "tolerance for reaching position goals");
8572
properties().declare<double>("goal_orientation_tolerance", 1e-4, "tolerance for reaching orientation goals");
8673
// Declare properties that configure the planning pipeline
87-
properties().declare<std::unordered_map<std::string, std::string>>(
88-
"pipeline_id_planner_id_map", std::unordered_map<std::string, std::string>(),
89-
"Set of pipelines and planners used for planning");
74+
properties().declare("pipeline_id_planner_id_map", pipeline_id_planner_id_map,
75+
"Set of pipelines and planners used for planning");
9076
}
9177

9278
bool PipelinePlanner::setPlannerId(const std::string& pipeline_name, const std::string& planner_id) {
9379
// Only set ID if pipeline exists. It is not possible to create new pipelines with this command.
94-
if (pipeline_id_planner_id_map_.count(pipeline_name) == 0) {
80+
PipelineMap map = properties().get<PipelineMap>("pipeline_id_planner_id_map");
81+
auto it = map.find(pipeline_name);
82+
if (it == map.end()) {
9583
RCLCPP_ERROR(node_->get_logger(),
9684
"PipelinePlanner does not have a pipeline called '%s'. Cannot set pipeline ID '%s'",
9785
pipeline_name.c_str(), planner_id.c_str());
9886
return false;
9987
}
100-
pipeline_id_planner_id_map_[pipeline_name] = planner_id;
88+
it->second = planner_id;
89+
properties().set("pipeline_id_planner_id_map", std::move(map));
10190
return true;
10291
}
10392

@@ -111,31 +100,34 @@ void PipelinePlanner::setSolutionSelectionFunction(
111100
}
112101

113102
void PipelinePlanner::init(const core::RobotModelConstPtr& robot_model) {
114-
// If no planning pipelines exist, create them based on the pipeline names provided in pipeline_id_planner_id_map_.
115-
// The assumption here is that all parameters required by the planning pipeline can be found in a namespace that
116-
// equals the pipeline name.
103+
// Create planning pipelines once from pipeline_id_planner_id_map.
104+
// We assume that all parameters required by the pipeline can be found
105+
// in the namespace of the pipeline name.
117106
if (planning_pipelines_.empty()) {
118-
planning_pipelines_ = moveit::planning_pipeline_interfaces::createPlanningPipelineMap(
119-
[&]() {
120-
// Create pipeline name vector from the keys of pipeline_id_planner_id_map_
121-
if (pipeline_id_planner_id_map_.empty()) {
122-
throw std::runtime_error("Cannot initialize PipelinePlanner: No planning pipeline was provided and "
123-
"pipeline_id_planner_id_map_ is empty!");
124-
}
125-
126-
std::vector<std::string> pipeline_names;
127-
for (const auto& pipeline_name_planner_id_pair : pipeline_id_planner_id_map_) {
128-
pipeline_names.push_back(pipeline_name_planner_id_pair.first);
129-
}
130-
return pipeline_names;
131-
}(),
132-
robot_model, node_);
133-
}
107+
auto map = properties().get<PipelineMap>("pipeline_id_planner_id_map");
108+
// Create pipeline name vector from the keys of pipeline_id_planner_id_map_
109+
if (map.empty()) {
110+
throw std::runtime_error("Cannot initialize PipelinePlanner: pipeline_id_planner_id_map is empty!");
111+
}
134112

135-
// Check if it is still empty
136-
if (planning_pipelines_.empty()) {
137-
throw std::runtime_error(
138-
"Cannot initialize PipelinePlanner: Could not create any valid entries for planning pipeline maps!");
113+
std::vector<std::string> pipeline_names;
114+
for (const auto& pipeline_name_planner_id_pair : map) {
115+
pipeline_names.push_back(pipeline_name_planner_id_pair.first);
116+
}
117+
planning_pipelines_ = moveit::planning_pipeline_interfaces::createPlanningPipelineMap(std::move(pipeline_names),
118+
robot_model, node_);
119+
// Check if it is still empty
120+
if (planning_pipelines_.empty()) {
121+
throw std::runtime_error("Failed to initialize PipelinePlanner: Could not create any valid pipeline");
122+
}
123+
} else {
124+
// Validate that all pipelines use the task's robot model
125+
for (const auto& pair : planning_pipelines_) {
126+
if (pair.second->getRobotModel() != robot_model) {
127+
throw std::runtime_error(
128+
"The robot model of the planning pipeline isn't the same as the task's robot model -- ");
129+
}
130+
}
139131
}
140132
}
141133

@@ -172,28 +164,23 @@ bool PipelinePlanner::plan(const planning_scene::PlanningSceneConstPtr& planning
172164
const moveit_msgs::msg::Constraints& goal_constraints, double timeout,
173165
robot_trajectory::RobotTrajectoryPtr& result,
174166
const moveit_msgs::msg::Constraints& path_constraints) {
167+
const auto& map = properties().get<PipelineMap>("pipeline_id_planner_id_map");
168+
175169
// Create a request for every planning pipeline that should run in parallel
176170
std::vector<moveit_msgs::msg::MotionPlanRequest> requests;
177-
requests.reserve(pipeline_id_planner_id_map_.size());
171+
requests.reserve(map.size());
178172

179-
auto const property_pipeline_id_planner_id_map =
180-
properties().get<std::unordered_map<std::string, std::string>>("pipeline_id_planner_id_map");
181-
for (auto const& pipeline_id_planner_id_pair :
182-
(!property_pipeline_id_planner_id_map.empty() ? property_pipeline_id_planner_id_map :
183-
pipeline_id_planner_id_map_)) {
173+
for (const auto& [pipeline_id, planner_id] : map) {
184174
// Check that requested pipeline exists and skip it if it doesn't exist
185-
if (planning_pipelines_.find(pipeline_id_planner_id_pair.first) == planning_pipelines_.end()) {
186-
RCLCPP_WARN(
187-
node_->get_logger(),
188-
"Pipeline '%s' is not available of this PipelineSolver instance. Skipping a request for this pipeline.",
189-
pipeline_id_planner_id_pair.first.c_str());
175+
if (planning_pipelines_.count(pipeline_id) == 0) {
176+
RCLCPP_WARN(node_->get_logger(), "Pipeline '%s' was not created. Skipping.", pipeline_id.c_str());
190177
continue;
191178
}
192179
// Create MotionPlanRequest for pipeline
193180
moveit_msgs::msg::MotionPlanRequest request;
194-
request.pipeline_id = pipeline_id_planner_id_pair.first;
181+
request.pipeline_id = pipeline_id;
195182
request.group_name = joint_model_group->getName();
196-
request.planner_id = pipeline_id_planner_id_pair.second;
183+
request.planner_id = planner_id;
197184
request.allowed_planning_time = timeout;
198185
request.start_state.is_diff = true; // we don't specify an extra start state
199186
request.num_planning_attempts = properties().get<uint>("num_planning_attempts");

0 commit comments

Comments
 (0)