moveit2
The MoveIt Motion Planning Framework for ROS 2.
planning_request_adapter.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 
38 #include <rclcpp/logger.hpp>
39 #include <functional>
40 #include <algorithm>
41 
43 {
44 static const rclcpp::Logger LOGGER = rclcpp::get_logger("moveit.planning_request_adapter");
45 
46 namespace
47 {
48 bool callPlannerInterfaceSolve(const planning_interface::PlannerManager& planner,
49  const planning_scene::PlanningSceneConstPtr& planning_scene,
52 {
53  planning_interface::PlanningContextPtr context = planner.getPlanningContext(planning_scene, req, res.error_code_);
54  if (context)
55  return context->solve(res);
56  else
57  return false;
58 }
59 
60 bool callAdapter(const PlanningRequestAdapter& adapter, const PlanningRequestAdapter::PlannerFn& planner,
61  const planning_scene::PlanningSceneConstPtr& planning_scene,
63  std::vector<std::size_t>& added_path_index)
64 {
65  try
66  {
67  return adapter.adaptAndPlan(planner, planning_scene, req, res, added_path_index);
68  }
69  catch (std::exception& ex)
70  {
71  RCLCPP_ERROR(LOGGER, "Exception caught executing adapter '%s': %s\nSkipping adapter instead.",
72  adapter.getDescription().c_str(), ex.what());
73  added_path_index.clear();
74  return planner(planning_scene, req, res);
75  }
76 }
77 
78 } // namespace
79 
80 bool PlanningRequestAdapter::adaptAndPlan(const planning_interface::PlannerManagerPtr& planner,
81  const planning_scene::PlanningSceneConstPtr& planning_scene,
84  std::vector<std::size_t>& added_path_index) const
85 {
86  return adaptAndPlan(
87  [&planner](const planning_scene::PlanningSceneConstPtr& scene, const planning_interface::MotionPlanRequest& req,
89  return callPlannerInterfaceSolve(*planner, scene, req, res);
90  },
91  planning_scene, req, res, added_path_index);
92 }
93 
94 bool PlanningRequestAdapter::adaptAndPlan(const planning_interface::PlannerManagerPtr& planner,
95  const planning_scene::PlanningSceneConstPtr& planning_scene,
98 {
99  std::vector<std::size_t> dummy;
100  return adaptAndPlan(planner, planning_scene, req, res, dummy);
101 }
102 
103 bool PlanningRequestAdapterChain::adaptAndPlan(const planning_interface::PlannerManagerPtr& planner,
104  const planning_scene::PlanningSceneConstPtr& planning_scene,
107 {
108  std::vector<std::size_t> dummy;
109  return adaptAndPlan(planner, planning_scene, req, res, dummy);
110 }
111 
112 bool PlanningRequestAdapterChain::adaptAndPlan(const planning_interface::PlannerManagerPtr& planner,
113  const planning_scene::PlanningSceneConstPtr& planning_scene,
116  std::vector<std::size_t>& added_path_index) const
117 {
118  // if there are no adapters, run the planner directly
119  if (adapters_.empty())
120  {
121  added_path_index.clear();
122  return callPlannerInterfaceSolve(*planner, planning_scene, req, res);
123  }
124  else
125  {
126  // the index values added by each adapter
127  std::vector<std::vector<std::size_t> > added_path_index_each(adapters_.size());
128 
129  // if there are adapters, construct a function for each, in order,
130  // so that in the end we have a nested sequence of functions that calls all adapters
131  // and eventually the planner in the correct order.
132  PlanningRequestAdapter::PlannerFn fn = [&planner = *planner](const planning_scene::PlanningSceneConstPtr& scene,
135  return callPlannerInterfaceSolve(planner, scene, req, res);
136  };
137 
138  for (int i = adapters_.size() - 1; i >= 0; --i)
139  {
140  fn = [&adapter = *adapters_[i], fn, &added_path_index = added_path_index_each[i]](
141  const planning_scene::PlanningSceneConstPtr& scene, const planning_interface::MotionPlanRequest& req,
143  return callAdapter(adapter, fn, scene, req, res, added_path_index);
144  };
145  }
146 
147  bool result = fn(planning_scene, req, res);
148  added_path_index.clear();
149 
150  // merge the index values from each adapter
151  for (std::vector<std::size_t>& added_states_by_each_adapter : added_path_index_each)
152  for (std::size_t& added_index : added_states_by_each_adapter)
153  {
154  for (std::size_t& index_in_path : added_path_index)
155  if (added_index <= index_in_path)
156  index_in_path++;
157  added_path_index.push_back(added_index);
158  }
159  std::sort(added_path_index.begin(), added_path_index.end());
160  return result;
161  }
162 }
163 
164 } // end of namespace planning_request_adapter
Base class for a MoveIt planner.
virtual PlanningContextPtr getPlanningContext(const planning_scene::PlanningSceneConstPtr &planning_scene, const MotionPlanRequest &req, moveit_msgs::msg::MoveItErrorCodes &error_code) const =0
Construct a planning context given the current scene and a planning request. If a problem is encounte...
bool adaptAndPlan(const planning_interface::PlannerManagerPtr &planner, const planning_scene::PlanningSceneConstPtr &planning_scene, const planning_interface::MotionPlanRequest &req, planning_interface::MotionPlanResponse &res) const
bool adaptAndPlan(const planning_interface::PlannerManagerPtr &planner, const planning_scene::PlanningSceneConstPtr &planning_scene, const planning_interface::MotionPlanRequest &req, planning_interface::MotionPlanResponse &res) const
std::function< bool(const planning_scene::PlanningSceneConstPtr &, const planning_interface::MotionPlanRequest &, planning_interface::MotionPlanResponse &)> PlannerFn
scene
Definition: pick.py:52
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
Generic interface to adapting motion planning requests.
This namespace includes the central class for representing planning contexts.
moveit_msgs::msg::MoveItErrorCodes error_code_