moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
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.hpp"
39#include <pybind11/operators.h>
40
41#include <fstream>
42
43namespace
44{
45bool saveGeometryToFile(std::shared_ptr<planning_scene::PlanningScene>& planning_scene,
46 const std::string& file_path_and_name)
47{
48 std::ofstream file(file_path_and_name);
49 if (!file.is_open())
50 {
51 return false;
52 }
53 planning_scene->saveGeometryToStream(file);
54 file.close();
55 return true;
56}
57
58bool loadGeometryFromFile(std::shared_ptr<planning_scene::PlanningScene>& planning_scene,
59 const std::string& file_path_and_name)
60{
61 std::ifstream file(file_path_and_name);
62 planning_scene->loadGeometryFromStream(file);
63 file.close();
64 return true;
65}
66} // namespace
67
68namespace moveit_py
69{
70namespace bind_planning_scene
71{
72void applyCollisionObject(std::shared_ptr<planning_scene::PlanningScene>& planning_scene,
73 moveit_msgs::msg::CollisionObject& collision_object_msg,
74 std::optional<moveit_msgs::msg::ObjectColor> color_msg)
75{
76 // apply collision object
77 planning_scene->processCollisionObjectMsg(collision_object_msg);
78
79 // check if color message is provided
80 if (color_msg.has_value())
81 {
82 // set object color
83 planning_scene->setObjectColor(color_msg.value().id, color_msg.value().color);
84 }
85}
86
87Eigen::MatrixXd getFrameTransform(std::shared_ptr<planning_scene::PlanningScene>& planning_scene, const std::string& id)
88{
89 auto transformation = planning_scene->getFrameTransform(id);
90 return transformation.matrix();
91}
92
93moveit_msgs::msg::PlanningScene getPlanningSceneMsg(std::shared_ptr<planning_scene::PlanningScene>& planning_scene)
94{
95 moveit_msgs::msg::PlanningScene planning_scene_msg;
96 planning_scene->getPlanningSceneMsg(planning_scene_msg);
97 return planning_scene_msg;
98}
99
100void initPlanningScene(py::module& m)
101{
102 py::module planning_scene = m.def_submodule("planning_scene");
103
104// Remove once checkCollisionUnpadded is removed
105#pragma GCC diagnostic push
106#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
107 py::class_<planning_scene::PlanningScene, std::shared_ptr<planning_scene::PlanningScene>>(planning_scene,
108 "PlanningScene",
109 R"(
110 Representation of the environment as seen by a planning instance. The environment geometry, the robot geometry and state are maintained.
111 )")
112
113 .def(py::init<const moveit::core::RobotModelConstPtr&, const collision_detection::WorldPtr&>(),
114 py::arg("robot_model"), py::arg("world") = std::make_shared<collision_detection::World>())
115 // properties
117 R"(
118 str: The name of the planning scene.
119 )")
120
121 .def_property("robot_model", &planning_scene::PlanningScene::getRobotModel, nullptr,
122 py::return_value_policy::move,
123 R"(
124 :py:class:`moveit_py.core.RobotModel`: The robot model associated to this planning scene.
125 )")
126
127 .def_property("planning_frame", &planning_scene::PlanningScene::getPlanningFrame, nullptr,
128 py::return_value_policy::move,
129 R"(
130 str: The frame in which planning is performed.
131 )")
132
133 .def_property("current_state", &planning_scene::PlanningScene::getCurrentState,
134 py::overload_cast<const moveit::core::RobotState&>(&planning_scene::PlanningScene::setCurrentState),
135 py::return_value_policy::reference_internal,
136 R"(
137 :py:class:`moveit_py.core.RobotState`: The current state of the robot.
138 )")
139
140 .def_property("planning_scene_message", &moveit_py::bind_planning_scene::getPlanningSceneMsg, nullptr,
141 py::return_value_policy::move)
142
143 .def_property("transforms", py::overload_cast<>(&planning_scene::PlanningScene::getTransforms), nullptr)
144 .def_property("allowed_collision_matrix", &planning_scene::PlanningScene::getAllowedCollisionMatrix,
146 py::return_value_policy::reference_internal)
147 // methods
148 .def("__copy__",
149 [](const planning_scene::PlanningScene* self) {
150 return planning_scene::PlanningScene::clone(self->shared_from_this());
151 })
152 .def("__deepcopy__",
153 [](const planning_scene::PlanningScene* self, py::dict /* memo */) { // NOLINT
154 return planning_scene::PlanningScene::clone(self->shared_from_this());
155 })
156 .def("knows_frame_transform",
157 py::overload_cast<const moveit::core::RobotState&, const std::string&>(
159 py::arg("robot_state"), py::arg("frame_id"),
160 R"(
161 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.
162
163 Args:
164 robot_state (:py:class:`moveit_py.core.RobotState`): The robot state to check.
165 frame_id (str): The frame id to check.
166
167 Returns:
168 bool: True if the transform is known, false otherwise.
169 )")
170
171 .def("knows_frame_transform",
172 py::overload_cast<const std::string&>(&planning_scene::PlanningScene::knowsFrameTransform, py::const_),
173 py::arg("frame_id"),
174 R"(
175 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.
176
177 Args:
178 frame_id (str): The frame id to check.
179
180 Returns:
181 bool: True if the transform is known, false otherwise.
182 )")
183
184 .def("get_frame_transform", &moveit_py::bind_planning_scene::getFrameTransform, py::arg("frame_id"),
185 R"(
186 Get the transform corresponding to the frame id.
187 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.
188
189 Args:
190 frame_id (str): The frame id to get the transform for.
191
192 Returns:
193 :py:class:`numpy.ndarray`: The transform corresponding to the frame id.
194 )")
195
196 // writing to the planning scene
197 .def("process_planning_scene_world", &planning_scene::PlanningScene::processPlanningSceneWorldMsg, py::arg("msg"),
198 R"(
199 Process a planning scene world message.
200
201 Args:
202 msg (:py:class:`moveit_msgs.msg.PlanningSceneWorld`): The planning scene world message.
203 )")
204
205 .def("apply_collision_object", &moveit_py::bind_planning_scene::applyCollisionObject,
206 py::arg("collision_object_msg"), py::arg("color_msg") = nullptr,
207 R"(
208 Apply a collision object to the planning scene.
209
210 Args:
211 object (moveit_msgs.msg.CollisionObject): The collision object to apply to the planning scene.
212 color (moveit_msgs.msg.ObjectColor, optional): The color of the collision object. Defaults to None if not specified.
213 )")
214
215 .def("set_object_color", &planning_scene::PlanningScene::setObjectColor, py::arg("object_id"),
216 py::arg("color_msg"),
217 R"(
218 Set the color of a collision object.
219
220 Args:
221 object_id (str): The id of the collision object to set the color of.
222 color (std_msgs.msg.ObjectColor): The color of the collision object.
223 )")
224
225 .def("process_attached_collision_object", &planning_scene::PlanningScene::processAttachedCollisionObjectMsg,
226 py::arg("object"),
227 R"(
228 Apply an attached collision object to the planning scene.
229
230 Args:
231 object (moveit_msgs.msg.AttachedCollisionObject): The attached collision object to apply to the planning scene.
232 )")
233
234 .def("process_octomap",
235 py::overload_cast<const octomap_msgs::msg::Octomap&>(&planning_scene::PlanningScene::processOctomapMsg),
236 py::arg("msg"),
237 R"(
238 Apply an octomap to the planning scene.
239
240 Args:
241 octomap (moveit_msgs.msg.Octomap): The octomap to apply to the planning scene.
242 )")
243
244 .def("remove_all_collision_objects", &planning_scene::PlanningScene::removeAllCollisionObjects,
245 R"(
246 Removes collision objects from the planning scene.
247 This method will remove all collision object from the scene except for attached collision objects.
248 )")
249
250 .def("set_current_state",
251 py::overload_cast<const moveit_msgs::msg::RobotState&>(&planning_scene::PlanningScene::setCurrentState),
252 py::arg("robot_state"),
253 R"(
254 Set the current state using a moveit_msgs::msg::RobotState message.
255
256 Args:
257 robot_state (moveit_msgs.msg.RobotState): The robot state message to set as current state.
258 )")
259
260 .def("set_current_state",
261 py::overload_cast<const moveit::core::RobotState&>(&planning_scene::PlanningScene::setCurrentState),
262 py::arg("robot_state"),
263 R"(
264 Set the current state using a moveit::core::RobotState object.
265
266 Args:
267 robot_state (moveit_py.core.RobotState): The robot state object to set as current state.
268 )")
269
270 // checking state validity
271 .def("is_state_valid",
272 py::overload_cast<const moveit::core::RobotState&, const std::string&, bool>(
274 py::arg("robot_state"), py::arg("joint_model_group_name"), py::arg("verbose") = false)
275 .def("is_state_colliding",
276 py::overload_cast<const std::string&, bool>(&planning_scene::PlanningScene::isStateColliding),
277 py::arg("joint_model_group_name"), py::arg("verbose") = false,
278 R"(
279 Check if the robot state is in collision.
280
281 Args:
282 joint_model_group_name (str): The name of the group to check collision for.
283 verbose (bool): If true, print the link names of the links in collision.
284 Returns:
285 bool: True if the robot state is in collision, false otherwise.
286 )")
287
288 .def("is_state_colliding",
289 py::overload_cast<const moveit::core::RobotState&, const std::string&, bool>(
291 py::arg("robot_state"), py::arg("joint_model_group_name"), py::arg("verbose") = false,
292 R"(
293 Check if the robot state is in collision.
294
295 Args:
296 robot_state (:py:class:`moveit_py.core.RobotState`): The robot state to check collision for.
297 joint_model_group_name (str): The name of the group to check collision for.
298 verbose (bool): If true, print the link names of the links in collision.
299 Returns:
300 bool: True if the robot state is in collision, false otherwise.
301 )")
302
303 .def("is_state_constrained",
304 py::overload_cast<const moveit::core::RobotState&, const moveit_msgs::msg::Constraints&, bool>(
306 py::arg("state"), py::arg("constraints"), py::arg("verbose") = false,
307 R"(
308 Check if the robot state fulfills the passed constraints
309
310 Args:
311 state (moveit_py.core.RobotState): The robot state to check constraints for.
312 constraints (moveit_msgs.msg.Constraints): The constraints to check.
313 verbose (bool):
314 Returns:
315 bool: true if state is constrained otherwise false.
316 )")
317
318 .def("is_path_valid",
319 py::overload_cast<const robot_trajectory::RobotTrajectory&, const std::string&, bool,
320 std::vector<std::size_t>*>(&planning_scene::PlanningScene::isPathValid, py::const_),
321 py::arg("trajectory"), py::arg("joint_model_group_name"), py::arg("verbose") = false,
322 py::arg("invalid_index") = nullptr,
323 R"(
324 Check if a given path is valid. Each state is checked for validity (collision avoidance and feasibility)
325
326 Args:
327 trajectory (:py:class:`moveit_py.core.RobotTrajectory`): The trajectory to check.
328 joint_model_group_name (str): The joint model group to check the path against.
329 verbose (bool):
330 invalid_index (list):
331
332 Returns:
333 bool: true if the path is valid otherwise false.
334 )")
335
336 // TODO (peterdavidfagan): remove collision result from input parameters and write separate binding code.
337 // TODO (peterdavidfagan): consider merging check_collision and check_collision_unpadded into one function with unpadded_param
338 .def("check_collision",
339 py::overload_cast<const collision_detection::CollisionRequest&, collision_detection::CollisionResult&>(
341 py::arg("collision_request"), py::arg("collision_result"),
342 R"(
343 Check whether the current state is in collision, and if needed, updates the collision transforms of the current state before the computation.
344
345 Args:
346 collision_request (:py:class:`moveit_py.core.CollisionRequest`): The collision request to use.
347 collision_result (:py:class:`moveit_py.core.CollisionResult`): The collision result to update
348
349 Returns:
350 bool: true if state is in collision otherwise false.
351 )")
352
353 .def("check_collision",
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",
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 // DEPRECATED! Use check_collision instead
387 .def("check_collision_unpadded",
388 py::overload_cast<const collision_detection::CollisionRequest&, collision_detection::CollisionResult&>(
390 py::arg("req"), py::arg("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 // DEPRECATED! Use check_collision instead
402 .def("check_collision_unpadded",
405 py::const_),
406 py::arg("collision_request"), py::arg("collision_result"), py::arg("state"),
407 R"(
408 Check if the robot state is in collision.
409
410 Args:
411 collision_request ():
412 collision_result ():
413 state ():
414
415 Returns:
416 bool: true if state is in collision otherwise false.
417 )")
418 // DEPRECATED! Use check_collision instead
419 .def("check_collision_unpadded",
423 py::arg("collision_request"), py::arg("collision_result"), py::arg("state"), py::arg("acm"),
424 R"(
425 Check if the robot state is in collision.
426
427 Args:
428 collision_request ():
429 collision_result ():
430 state ():
431 acm ():
432
433 Returns:
434 bool: true if state is in collision otherwise false.
435 )")
436 .def("check_self_collision",
437 py::overload_cast<const collision_detection::CollisionRequest&, collision_detection::CollisionResult&>(
439 py::arg("collision_request"), py::arg("collision_result"),
440 R"(
441 Check if the robot state is in collision.
442
443 Args:
444 collision_request ():
445 collision_result ():
446
447 Returns:
448 bool: true if state is in collision otherwise false.
449 )")
450
451 .def("check_self_collision",
454 py::arg("collision_request"), py::arg("collision_result"), py::arg("state"),
455 R"(
456 Check if the robot state is in collision.
457
458 Args:
459 collision request ():
460 collision_result ():
461 state ():
462
463 Returns:
464 bool: true if state is in self collision otherwise false.
465 )")
466
467 .def("check_self_collision",
471 py::arg("collision_request"), py::arg("collision_result"), py::arg("state"), py::arg("acm"),
472 R"(
473 Check if the robot state is in collision.
474
475 Args:
476 collision request ():
477 collision_result ():
478 state ():
479 acm():
480
481 Returns:
482 bool: true if state is in self collision otherwise false.
483 )")
484
485 .def("save_geometry_to_file", &saveGeometryToFile, py::arg("file_path_and_name"),
486 R"(
487 Save the CollisionObjects in the PlanningScene to a file
488
489 Args:
490 file_path_and_name (str): The file to save the CollisionObjects to.
491
492 Returns:
493 bool: true if save to file was successful otherwise false.
494 )")
495
496 .def("load_geometry_from_file", &loadGeometryFromFile, py::arg("file_path_and_name"),
497 R"(
498 Load the CollisionObjects from a file to the PlanningScene
499
500 Args:
501 file_path_and_name (str): The file to load the CollisionObjects from.
502
503 Returns:
504 bool: true if load from file was successful otherwise false.
505 )");
506#pragma GCC diagnostic pop // TODO remove once checkCollisionUnpadded is removed
507}
508} // namespace bind_planning_scene
509} // 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.
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.
const moveit::core::RobotModelConstPtr & getRobotModel() const
Get the kinematic model for which the planning scene is maintained.
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...
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)
const moveit::core::RobotState & getCurrentState() const
Get the state at which the robot is assumed to be.
bool processPlanningSceneWorldMsg(const moveit_msgs::msg::PlanningSceneWorld &world)
void setObjectColor(const std::string &id, const std_msgs::msg::ColorRGBA &color)
const std::string & getPlanningFrame() const
Get the frame in which planning is performed.
const moveit::core::Transforms & getTransforms() const
Get the set of fixed transforms from known frames to the planning frame.
void removeAllCollisionObjects()
Clear all collision objects in planning scene.
const std::string & getName() const
Get the name of the planning scene. This is empty by default.
bool isStateColliding(const std::string &group="", bool verbose=false)
Check if the current state is in collision (with the environment or self collision)....
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.
void checkSelfCollision(const collision_detection::CollisionRequest &req, collision_detection::CollisionResult &res)
Check whether the current state is in self collision.
const collision_detection::AllowedCollisionMatrix & getAllowedCollisionMatrix() const
Get the allowed collision matrix.
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.