moveit2
The MoveIt Motion Planning Framework for ROS 2.
planning_scene.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2022, Peter David Fagan
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 PickNik Inc. 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: Peter David Fagan */
36 
37 #include "planning_scene.h"
39 #include <pybind11/operators.h>
40 
41 namespace moveit_py
42 {
43 namespace bind_planning_scene
44 {
45 void applyCollisionObject(std::shared_ptr<planning_scene::PlanningScene>& planning_scene,
46  moveit_msgs::msg::CollisionObject& collision_object_msg,
47  std::optional<moveit_msgs::msg::ObjectColor> color_msg)
48 {
49  // apply collision object
50  planning_scene->processCollisionObjectMsg(collision_object_msg);
51 
52  // check if color message is provided
53  if (color_msg.has_value())
54  {
55  // set object color
56  planning_scene->setObjectColor(color_msg.value().id, color_msg.value().color);
57  }
58 }
59 
60 Eigen::MatrixXd getFrameTransform(std::shared_ptr<planning_scene::PlanningScene>& planning_scene, const std::string& id)
61 {
62  auto transformation = planning_scene->getFrameTransform(id);
63  return transformation.matrix();
64 }
65 
66 moveit_msgs::msg::PlanningScene getPlanningSceneMsg(std::shared_ptr<planning_scene::PlanningScene>& planning_scene)
67 {
68  moveit_msgs::msg::PlanningScene planning_scene_msg;
69  planning_scene->getPlanningSceneMsg(planning_scene_msg);
70  return planning_scene_msg;
71 }
72 
73 void initPlanningScene(py::module& m)
74 {
75  py::module planning_scene = m.def_submodule("planning_scene");
76 
77  py::class_<planning_scene::PlanningScene, std::shared_ptr<planning_scene::PlanningScene>>(planning_scene,
78  "PlanningScene",
79  R"(
80  Representation of the environment as seen by a planning instance. The environment geometry, the robot geometry and state are maintained.
81  )")
82 
83  .def(py::init<const moveit::core::RobotModelConstPtr&, const collision_detection::WorldPtr&>(),
84  py::arg("robot_model"), py::arg("world") = std::make_shared<collision_detection::World>())
85  // properties
87  R"(
88  str: The name of the planning scene.
89  )")
90 
91  .def_property("robot_model", &planning_scene::PlanningScene::getRobotModel, nullptr,
92  py::return_value_policy::move,
93  R"(
94  :py:class:`moveit_py.core.RobotModel`: The robot model associated to this planning scene.
95  )")
96 
97  .def_property("planning_frame", &planning_scene::PlanningScene::getPlanningFrame, nullptr,
98  py::return_value_policy::move,
99  R"(
100  str: The frame in which planning is performed.
101  )")
102 
103  .def_property("current_state", &planning_scene::PlanningScene::getCurrentState,
104  py::overload_cast<const moveit::core::RobotState&>(&planning_scene::PlanningScene::setCurrentState),
105  py::return_value_policy::reference_internal,
106  R"(
107  :py:class:`moveit_py.core.RobotState`: The current state of the robot.
108  )")
109 
110  .def_property("planning_scene_message", &moveit_py::bind_planning_scene::getPlanningSceneMsg, nullptr,
111  py::return_value_policy::move)
112 
113  .def_property("transforms", py::overload_cast<>(&planning_scene::PlanningScene::getTransforms), nullptr)
114  .def_property("allowed_collision_matrix", &planning_scene::PlanningScene::getAllowedCollisionMatrix,
116  py::return_value_policy::reference_internal)
117  // methods
118  .def("__copy__",
119  [](const planning_scene::PlanningScene* self) {
120  return planning_scene::PlanningScene::clone(self->shared_from_this());
121  })
122  .def("__deepcopy__",
123  [](const planning_scene::PlanningScene* self, py::dict /* memo */) { // NOLINT
124  return planning_scene::PlanningScene::clone(self->shared_from_this());
125  })
126  .def("knows_frame_transform",
127  py::overload_cast<const moveit::core::RobotState&, const std::string&>(
129  py::arg("robot_state"), py::arg("frame_id"),
130  R"(
131  Check if a transform to the frame id is known. This will be known if id is a link name, an attached body id or a collision object.
132 
133  Args:
134  robot_state (:py:class:`moveit_py.core.RobotState`): The robot state to check.
135  frame_id (str): The frame id to check.
136 
137  Returns:
138  bool: True if the transform is known, false otherwise.
139  )")
140 
141  .def("knows_frame_transform",
142  py::overload_cast<const std::string&>(&planning_scene::PlanningScene::knowsFrameTransform, py::const_),
143  py::arg("frame_id"),
144  R"(
145  Check if a transform to the frame id is known. This will be known if id is a link name, an attached body id or a collision object.
146 
147  Args:
148  frame_id (str): The frame id to check.
149 
150  Returns:
151  bool: True if the transform is known, false otherwise.
152  )")
153 
154  .def("get_frame_transform", &moveit_py::bind_planning_scene::getFrameTransform, py::arg("frame_id"),
155  R"(
156  Get the transform corresponding to the frame id.
157  This will be known if id is a link name, an attached body id or a collision object. Return identity when no transform is available.
158 
159  Args:
160  frame_id (str): The frame id to get the transform for.
161 
162  Returns:
163  :py:class:`numpy.ndarray`: The transform corresponding to the frame id.
164  )")
165 
166  // writing to the planning scene
167  .def("process_planning_scene_world", &planning_scene::PlanningScene::processPlanningSceneWorldMsg, py::arg("msg"),
168  R"(
169  Process a planning scene world message.
170 
171  Args:
172  msg (:py:class:`moveit_msgs.msg.PlanningSceneWorld`): The planning scene world message.
173  )")
174 
175  .def("apply_collision_object", &moveit_py::bind_planning_scene::applyCollisionObject,
176  py::arg("collision_object_msg"), py::arg("color_msg") = nullptr,
177  R"(
178  Apply a collision object to the planning scene.
179 
180  Args:
181  object (moveit_msgs.msg.CollisionObject): The collision object to apply to the planning scene.
182  color (moveit_msgs.msg.ObjectColor, optional): The color of the collision object. Defaults to None if not specified.
183  )")
184 
185  .def("set_object_color", &planning_scene::PlanningScene::setObjectColor, py::arg("object_id"),
186  py::arg("color_msg"),
187  R"(
188  Set the color of a collision object.
189 
190  Args:
191  object_id (str): The id of the collision object to set the color of.
192  color (std_msgs.msg.ObjectColor): The color of the collision object.
193  )")
194 
195  .def("process_attached_collision_object", &planning_scene::PlanningScene::processAttachedCollisionObjectMsg,
196  py::arg("object"),
197  R"(
198  Apply an attached collision object to the planning scene.
199 
200  Args:
201  object (moveit_msgs.msg.AttachedCollisionObject): The attached collision object to apply to the planning scene.
202  )")
203 
204  .def("process_octomap",
205  py::overload_cast<const octomap_msgs::msg::Octomap&>(&planning_scene::PlanningScene::processOctomapMsg),
206  py::arg("msg"),
207  R"(
208  Apply an octomap to the planning scene.
209 
210  Args:
211  octomap (moveit_msgs.msg.Octomap): The octomap to apply to the planning scene.
212  )")
213 
214  .def("remove_all_collision_objects", &planning_scene::PlanningScene::removeAllCollisionObjects,
215  R"(
216  Removes collision objects from the planning scene.
217  This method will remove all collision object from the scene except for attached collision objects.
218  )")
219 
220  // checking state validity
221  .def("is_state_valid",
222  py::overload_cast<const moveit::core::RobotState&, const std::string&, bool>(
224  py::arg("robot_state"), py::arg("joint_model_group_name"), py::arg("verbose") = false)
225  .def("is_state_colliding",
226  py::overload_cast<const std::string&, bool>(&planning_scene::PlanningScene::isStateColliding),
227  py::arg("joint_model_group_name"), py::arg("verbose") = false,
228  R"(
229  Check if the robot state is in collision.
230 
231  Args:
232  joint_model_group_name (str): The name of the group to check collision for.
233  verbose (bool): If true, print the link names of the links in collision.
234  Returns:
235  bool: True if the robot state is in collision, false otherwise.
236  )")
237 
238  .def("is_state_colliding",
239  py::overload_cast<const moveit::core::RobotState&, const std::string&, bool>(
241  py::arg("robot_state"), py::arg("joint_model_group_name"), py::arg("verbose") = false,
242  R"(
243  Check if the robot state is in collision.
244 
245  Args:
246  robot_state (:py:class:`moveit_py.core.RobotState`): The robot state to check collision for.
247  joint_model_group_name (str): The name of the group to check collision for.
248  verbose (bool): If true, print the link names of the links in collision.
249  Returns:
250  bool: True if the robot state is in collision, false otherwise.
251  )")
252 
253  .def("is_state_constrained",
254  py::overload_cast<const moveit::core::RobotState&, const moveit_msgs::msg::Constraints&, bool>(
256  py::arg("state"), py::arg("constraints"), py::arg("verbose") = false,
257  R"(
258  Check if the robot state fulfills the passed constraints
259 
260  Args:
261  state (moveit_py.core.RobotState): The robot state to check constraints for.
262  constraints (moveit_msgs.msg.Constraints): The constraints to check.
263  verbose (bool):
264  Returns:
265  bool: true if state is constrained otherwise false.
266  )")
267 
268  .def("is_path_valid",
269  py::overload_cast<const robot_trajectory::RobotTrajectory&, const std::string&, bool,
270  std::vector<std::size_t>*>(&planning_scene::PlanningScene::isPathValid, py::const_),
271  py::arg("trajectory"), py::arg("joint_model_group_name"), py::arg("verbose") = false,
272  py::arg("invalid_index") = nullptr,
273  R"(
274  Check if a given path is valid. Each state is checked for validity (collision avoidance and feasibility)
275 
276  Args:
277  trajectory (:py:class:`moveit_py.core.RobotTrajectory`): The trajectory to check.
278  joint_model_group_name (str): The joint model group to check the path against.
279  verbose (bool):
280  invalid_index (list):
281 
282  Returns:
283  bool: true if the path is valid otherwise false.
284  )")
285 
286  // TODO (peterdavidfagan): remove collision result from input parameters and write separate binding code.
287  // TODO (peterdavidfagan): consider merging check_collision and check_collision_unpadded into one function with unpadded_param
288  .def("check_collision",
289  py::overload_cast<const collision_detection::CollisionRequest&, collision_detection::CollisionResult&>(
291  py::arg("collision_request"), py::arg("collision_result"),
292  R"(
293  Check whether the current state is in collision, and if needed, updates the collision transforms of the current state before the computation.
294 
295  Args:
296  collision_request (:py:class:`moveit_py.core.CollisionRequest`): The collision request to use.
297  collision_result (:py:class:`moveit_py.core.CollisionResult`): The collision result to update
298 
299  Returns:
300  bool: true if state is in collision otherwise false.
301  )")
302 
303  .def("check_collision",
306  py::arg("collision_request"), py::arg("collision_result"), py::arg("state"),
307  R"(
308  Check if the robot state is in collision.
309 
310  Args:
311  collision_request ():
312  collision_result ():
313  state ():
314 
315  Returns:
316  bool: true if state is in collision otherwise false.
317  )")
318 
319  .def("check_collision",
323  py::arg("collision_request"), py::arg("collision_result"), py::arg("state"), py::arg("acm"),
324  R"(
325  Check if the robot state is in collision.
326 
327  Args:
328  collision_request ():
329  collision_result ():
330  state ():
331  acm ():
332 
333  Returns:
334  bool: true if state is in collision otherwise false.
335  )")
336 
337  .def("check_collision_unpadded",
338  py::overload_cast<const collision_detection::CollisionRequest&, collision_detection::CollisionResult&>(
340  py::arg("req"), py::arg("result"),
341  R"(
342  Check if the robot state is in collision.
343 
344  Args:
345  collision_request ():
346  collision_result ():
347 
348  Returns:
349  bool: true if state is in collision otherwise false.
350  )")
351 
352  .def("check_collision_unpadded",
355  py::const_),
356  py::arg("collision_request"), py::arg("collision_result"), py::arg("state"),
357  R"(
358  Check if the robot state is in collision.
359 
360  Args:
361  collision_request ():
362  collision_result ():
363  state ():
364 
365  Returns:
366  bool: true if state is in collision otherwise false.
367  )")
368 
369  .def("check_collision_unpadded",
373  py::arg("collision_request"), py::arg("collision_result"), py::arg("state"), py::arg("acm"),
374  R"(
375  Check if the robot state is in collision.
376 
377  Args:
378  collision_request ():
379  collision_result ():
380  state ():
381  acm ():
382 
383  Returns:
384  bool: true if state is in collision otherwise false.
385  )")
386 
387  .def("check_self_collision",
388  py::overload_cast<const collision_detection::CollisionRequest&, collision_detection::CollisionResult&>(
390  py::arg("collision_request"), py::arg("collision_result"),
391  R"(
392  Check if the robot state is in collision.
393 
394  Args:
395  collision_request ():
396  collision_result ():
397 
398  Returns:
399  bool: true if state is in collision otherwise false.
400  )")
401 
402  .def("check_self_collision",
405  py::arg("collision_request"), py::arg("collision_result"), py::arg("state"),
406  R"(
407  Check if the robot state is in collision.
408 
409  Args:
410  collision request ():
411  collision_result ():
412  state ():
413 
414  Returns:
415  bool: true if state is in self collision otherwise false.
416  )")
417 
418  .def("check_self_collision",
422  py::arg("collision_request"), py::arg("collision_result"), py::arg("state"), py::arg("acm"),
423  R"(
424  Check if the robot state is in collision.
425 
426  Args:
427  collision request ():
428  collision_result ():
429  state ():
430  acm():
431 
432  Returns:
433  bool: true if state is in self collision otherwise false.
434  )");
435 }
436 } // namespace bind_planning_scene
437 } // namespace moveit_py
Definition of a structure for the allowed collision matrix. All elements in the collision world are r...
Representation of a robot's state. This includes position, velocity, acceleration and effort.
Definition: robot_state.h:90
This class maintains the representation of the environment as seen by a planning instance....
void setName(const std::string &name)
Set the name of the planning scene.
void setAllowedCollisionMatrix(const collision_detection::AllowedCollisionMatrix &acm)
Set the allowed collision matrix.
static PlanningScenePtr clone(const PlanningSceneConstPtr &scene)
Clone a planning scene. Even if the scene scene depends on a parent, the cloned scene will not.
void setCurrentState(const moveit_msgs::msg::RobotState &state)
Set the current robot state to be state. If not all joint values are specified, the previously mainta...
const std::string & getName() const
Get the name of the planning scene. This is empty by default.
const std::string & getPlanningFrame() const
Get the frame in which planning is performed.
bool isPathValid(const moveit_msgs::msg::RobotState &start_state, const moveit_msgs::msg::RobotTrajectory &trajectory, const std::string &group="", bool verbose=false, std::vector< std::size_t > *invalid_index=nullptr) const
Check if a given path is valid. Each state is checked for validity (collision avoidance and feasibili...
void checkCollision(const collision_detection::CollisionRequest &req, collision_detection::CollisionResult &res)
Check whether the current state is in collision, and if needed, updates the collision transforms of t...
bool knowsFrameTransform(const std::string &id) const
Check if a transform to the frame id is known. This will be known if id is a link name,...
bool isStateValid(const moveit_msgs::msg::RobotState &state, const std::string &group="", bool verbose=false) const
Check if a given state is valid. This means checking for collisions and feasibility....
void checkCollisionUnpadded(const collision_detection::CollisionRequest &req, collision_detection::CollisionResult &res)
Check whether the current state is in collision, but use a collision_detection::CollisionRobot instan...
void processOctomapMsg(const octomap_msgs::msg::OctomapWithPose &map)
bool processAttachedCollisionObjectMsg(const moveit_msgs::msg::AttachedCollisionObject &object)
bool processPlanningSceneWorldMsg(const moveit_msgs::msg::PlanningSceneWorld &world)
void setObjectColor(const std::string &id, const std_msgs::msg::ColorRGBA &color)
const collision_detection::AllowedCollisionMatrix & getAllowedCollisionMatrix() const
Get the allowed collision matrix.
const moveit::core::RobotState & getCurrentState() const
Get the state at which the robot is assumed to be.
void removeAllCollisionObjects()
Clear all collision objects in planning scene.
bool isStateColliding(const std::string &group="", bool verbose=false)
Check if the current state is in collision (with the environment or self collision)....
const moveit::core::Transforms & getTransforms() const
Get the set of fixed transforms from known frames to the planning frame.
bool isStateConstrained(const moveit_msgs::msg::RobotState &state, const moveit_msgs::msg::Constraints &constr, bool verbose=false) const
Check if a given state satisfies a set of constraints.
const moveit::core::RobotModelConstPtr & getRobotModel() const
Get the kinematic model for which the planning scene is maintained.
void checkSelfCollision(const collision_detection::CollisionRequest &req, collision_detection::CollisionResult &res)
Check whether the current state is in self collision.
Maintain a sequence of waypoints and the time durations between these waypoints.
void initPlanningScene(py::module &m)
Eigen::MatrixXd getFrameTransform(std::shared_ptr< planning_scene::PlanningScene > &planning_scene, const std::string &id)
moveit_msgs::msg::PlanningScene getPlanningSceneMsg(std::shared_ptr< planning_scene::PlanningScene > &planning_scene)
void applyCollisionObject(std::shared_ptr< planning_scene::PlanningScene > &planning_scene, moveit_msgs::msg::CollisionObject &collision_object_msg, std::optional< moveit_msgs::msg::ObjectColor > color_msg)
This namespace includes the central class for representing planning contexts.
Representation of a collision checking request.
Representation of a collision checking result.