moveit2
The MoveIt Motion Planning Framework for ROS 2.
ompl_interface.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, 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 
43 #include <fstream>
44 
45 namespace ompl_interface
46 {
47 static const rclcpp::Logger LOGGER = rclcpp::get_logger("moveit.ompl_planning.ompl_interface");
48 
49 OMPLInterface::OMPLInterface(const moveit::core::RobotModelConstPtr& robot_model, const rclcpp::Node::SharedPtr& node,
50  const std::string& parameter_namespace)
51  : node_(node)
52  , parameter_namespace_(parameter_namespace)
53  , robot_model_(robot_model)
54  , constraint_sampler_manager_(std::make_shared<constraint_samplers::ConstraintSamplerManager>())
55  , context_manager_(robot_model, constraint_sampler_manager_)
56  , use_constraints_approximations_(true)
57 {
58  RCLCPP_DEBUG(LOGGER, "Initializing OMPL interface using ROS parameters");
61 }
62 
63 OMPLInterface::OMPLInterface(const moveit::core::RobotModelConstPtr& robot_model,
65  const rclcpp::Node::SharedPtr& node, const std::string& parameter_namespace)
66  : node_(node)
67  , parameter_namespace_(parameter_namespace)
68  , robot_model_(robot_model)
69  , constraint_sampler_manager_(std::make_shared<constraint_samplers::ConstraintSamplerManager>())
70  , context_manager_(robot_model, constraint_sampler_manager_)
71  , use_constraints_approximations_(true)
72 {
73  RCLCPP_DEBUG(LOGGER, "Initializing OMPL interface using specified configuration");
74  setPlannerConfigurations(pconfig);
76 }
77 
79 
81 {
83 
84  // construct default configurations for planning groups that don't have configs already passed in
85  for (const moveit::core::JointModelGroup* group : robot_model_->getJointModelGroups())
86  {
87  if (pconfig.find(group->getName()) == pconfig.end())
88  {
90  empty.name = empty.group = group->getName();
91  pconfig2[empty.name] = empty;
92  }
93  }
94 
96 }
97 
98 ModelBasedPlanningContextPtr
99 OMPLInterface::getPlanningContext(const planning_scene::PlanningSceneConstPtr& planning_scene,
100  const planning_interface::MotionPlanRequest& req) const
101 {
102  moveit_msgs::msg::MoveItErrorCodes dummy;
103  return getPlanningContext(planning_scene, req, dummy);
104 }
105 
106 ModelBasedPlanningContextPtr
107 OMPLInterface::getPlanningContext(const planning_scene::PlanningSceneConstPtr& planning_scene,
109  moveit_msgs::msg::MoveItErrorCodes& error_code) const
110 {
111  ModelBasedPlanningContextPtr ctx =
113  return ctx;
114 }
115 
117 {
118  constraint_sampler_manager_loader_ =
119  std::make_shared<constraint_sampler_manager_loader::ConstraintSamplerManagerLoader>(node_,
121 }
122 
123 bool OMPLInterface::loadPlannerConfiguration(const std::string& group_name, const std::string& planner_id,
124  const std::map<std::string, std::string>& group_params,
126 {
127  rcl_interfaces::msg::ListParametersResult planner_params_result =
128  node_->list_parameters({ parameter_namespace_ + ".planner_configs." + planner_id }, 2);
129 
130  if (planner_params_result.names.empty())
131  {
132  RCLCPP_ERROR(LOGGER, "Could not find the planner configuration '%s' on the param server", planner_id.c_str());
133  return false;
134  }
135 
136  planner_config.name = group_name + "[" + planner_id + "]";
137  planner_config.group = group_name;
138 
139  // default to specified parameters of the group (overridden by configuration specific parameters)
140  planner_config.config = group_params;
141 
142  // read parameters specific for this configuration
143  for (const auto& planner_param : planner_params_result.names)
144  {
145  const rclcpp::Parameter param = node_->get_parameter(planner_param);
146  auto param_name = planner_param.substr(planner_param.find(planner_id) + planner_id.size() + 1);
147  planner_config.config[param_name] = param.value_to_string();
148  }
149 
150  return true;
151 }
152 
154 {
155  // read the planning configuration for each group
157  pconfig.clear();
158 
159  for (const std::string& group_name : robot_model_->getJointModelGroupNames())
160  {
161  // the set of planning parameters that can be specific for the group (inherited by configurations of that group)
162  // with their expected parameter type
163  static const std::pair<std::string, rclcpp::ParameterType> KNOWN_GROUP_PARAMS[] = {
164  { "projection_evaluator", rclcpp::ParameterType::PARAMETER_STRING },
165  { "longest_valid_segment_fraction", rclcpp::ParameterType::PARAMETER_DOUBLE },
166  { "enforce_joint_model_state_space", rclcpp::ParameterType::PARAMETER_BOOL },
167  { "enforce_constrained_state_space", rclcpp::ParameterType::PARAMETER_BOOL }
168  };
169 
170  const std::string group_name_param = parameter_namespace_ + "." + group_name;
171 
172  // get parameters specific for the robot planning group
173  std::map<std::string, std::string> specific_group_params;
174  for (const auto& [name, type] : KNOWN_GROUP_PARAMS)
175  {
176  std::string param_name{ group_name_param };
177  param_name += ".";
178  param_name += name;
179  if (node_->has_parameter(param_name))
180  {
181  const rclcpp::Parameter parameter = node_->get_parameter(param_name);
182  if (parameter.get_type() != type)
183  {
184  RCLCPP_ERROR_STREAM(LOGGER, "Invalid type for parameter '" << name << "' expected ["
185  << rclcpp::to_string(type) << "] got ["
186  << rclcpp::to_string(parameter.get_type()) << "]");
187  continue;
188  }
189  if (parameter.get_type() == rclcpp::ParameterType::PARAMETER_STRING)
190  specific_group_params[name] = parameter.as_string();
191  else if (parameter.get_type() == rclcpp::ParameterType::PARAMETER_DOUBLE)
192  specific_group_params[name] = moveit::core::toString(parameter.as_double());
193  else if (parameter.get_type() == rclcpp::ParameterType::PARAMETER_INTEGER)
194  specific_group_params[name] = std::to_string(parameter.as_int());
195  else if (parameter.get_type() == rclcpp::ParameterType::PARAMETER_BOOL)
196  specific_group_params[name] = std::to_string(parameter.as_bool());
197  }
198  }
199 
200  // add default planner configuration
202  std::string default_planner_id;
203  if (node_->get_parameter(group_name_param + ".default_planner_config", default_planner_id))
204  {
205  if (!loadPlannerConfiguration(group_name, default_planner_id, specific_group_params, default_pc))
206  {
207  default_planner_id = "";
208  }
209  }
210 
211  if (default_planner_id.empty())
212  {
213  default_pc.group = group_name;
214  default_pc.config = specific_group_params;
215  default_pc.config["type"] = "geometric::RRTConnect";
216  }
217 
218  default_pc.name = group_name; // this is the name of the default config
219  pconfig[default_pc.name] = default_pc;
220 
221  // get parameters specific to each planner type
222  std::vector<std::string> config_names;
223  if (node_->get_parameter(group_name_param + ".planner_configs", config_names))
224  {
225  for (const auto& planner_id : config_names)
226  {
228  if (loadPlannerConfiguration(group_name, planner_id, specific_group_params, pc))
229  {
230  pconfig[pc.name] = pc;
231  }
232  }
233  }
234  }
235 
236  for (const auto& [name, config_settings] : pconfig)
237  {
238  RCLCPP_DEBUG(LOGGER, "Parameters for configuration '%s'", name.c_str());
239 
240  for (const auto& [param_name, param_value] : config_settings.config)
241  {
242  RCLCPP_DEBUG_STREAM(LOGGER, " - " << param_name << " = " << param_value);
243  }
244  }
245 
246  setPlannerConfigurations(pconfig);
247 }
248 
250 {
251  RCLCPP_INFO(LOGGER, "OMPL ROS interface is running.");
252 }
253 } // namespace ompl_interface
rclcpp::Node::SharedPtr node_
void printStatus()
Print the status of this node.
constraint_samplers::ConstraintSamplerManagerPtr constraint_sampler_manager_
void loadConstraintSamplers()
Load the additional plugins for sampling constraints.
void setPlannerConfigurations(const planning_interface::PlannerConfigurationMap &pconfig)
Specify configurations for the planners.
PlanningContextManager context_manager_
bool loadPlannerConfiguration(const std::string &group_name, const std::string &planner_id, const std::map< std::string, std::string > &group_params, planning_interface::PlannerConfigurationSettings &planner_config)
Load planner configurations for specified group into planner_config.
moveit::core::RobotModelConstPtr robot_model_
The kinematic model for which motion plans are computed.
const std::string parameter_namespace_
The ROS node.
ModelBasedPlanningContextPtr getPlanningContext(const planning_scene::PlanningSceneConstPtr &planning_scene, const planning_interface::MotionPlanRequest &req) const
void loadPlannerConfigurations()
Configure the planners.
OMPLInterface(const moveit::core::RobotModelConstPtr &robot_model, const rclcpp::Node::SharedPtr &node, const std::string &parameter_namespace)
Initialize OMPL-based planning for a particular robot model. ROS configuration is read from the speci...
ModelBasedPlanningContextPtr getPlanningContext(const planning_scene::PlanningSceneConstPtr &planning_scene, const planning_interface::MotionPlanRequest &req, moveit_msgs::msg::MoveItErrorCodes &error_code, const rclcpp::Node::SharedPtr &node, bool use_constraints_approximations) const
Returns a planning context to OMPLInterface, which in turn passes it to OMPLPlannerManager.
void setPlannerConfigurations(const planning_interface::PlannerConfigurationMap &pconfig)
Specify configurations for the planners.
locale-agnostic conversion functions from floating point numbers to strings
The constraint samplers namespace contains a number of methods for generating samples based on a cons...
std::string toString(double d)
Convert a double to std::string using the classic C locale.
The MoveIt interface to OMPL.
std::map< std::string, PlannerConfigurationSettings > PlannerConfigurationMap
Map from PlannerConfigurationSettings.name to PlannerConfigurationSettings.
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
This namespace includes the central class for representing planning contexts.
name
Definition: setup.py:7
Specify the settings for a particular planning algorithm, for a particular group. The Planner plugin ...
std::map< std::string, std::string > config
Key-value pairs of settings that get passed to the planning algorithm.
std::string group
The group (as defined in the SRDF) this configuration is meant for.