moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
collision_env_bullet.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2019, Jens Petit
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 the copyright holder 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: Jens Petit */
36
41#include <functional>
42#include <bullet/btBulletCollisionCommon.h>
43#include <rclcpp/logger.hpp>
44#include <rclcpp/logging.hpp>
45
46namespace collision_detection
47{
48const std::string CollisionDetectorAllocatorBullet::NAME("Bullet");
49const double MAX_DISTANCE_MARGIN = 99;
50
52
53CollisionEnvBullet::CollisionEnvBullet(const moveit::core::RobotModelConstPtr& model, double padding, double scale)
54 : CollisionEnv(model, padding, scale)
55{
56 // request notifications about changes to new world
57 observer_handle_ = getWorld()->addObserver(
58 [this](const World::ObjectConstPtr& object, World::Action action) { notifyObjectChange(object, action); });
59
60 for (const std::pair<const std::string, urdf::LinkSharedPtr>& link : robot_model_->getURDF()->links_)
61 {
62 addLinkAsCollisionObject(link.second);
63 }
64}
65
66CollisionEnvBullet::CollisionEnvBullet(const moveit::core::RobotModelConstPtr& model, const WorldPtr& world,
67 double padding, double scale)
68 : CollisionEnv(model, world, padding, scale)
69{
70 // request notifications about changes to new world
71 observer_handle_ = getWorld()->addObserver(
72 [this](const World::ObjectConstPtr& object, World::Action action) { notifyObjectChange(object, action); });
73
74 for (const std::pair<const std::string, urdf::LinkSharedPtr>& link : robot_model_->getURDF()->links_)
75 {
76 addLinkAsCollisionObject(link.second);
77 }
78
79 getWorld()->notifyObserverAllObjects(observer_handle_, World::CREATE);
80}
81
83 : CollisionEnv(other, world)
84{
85 // request notifications about changes to new world
86 observer_handle_ = getWorld()->addObserver(
87 [this](const World::ObjectConstPtr& object, World::Action action) { notifyObjectChange(object, action); });
88
89 for (const std::pair<const std::string, urdf::LinkSharedPtr>& link : other.robot_model_->getURDF()->links_)
90 {
91 addLinkAsCollisionObject(link.second);
92 }
93
94 // get notifications any objects already in the new world
95 getWorld()->notifyObserverAllObjects(observer_handle_, World::CREATE);
96}
97
99{
100 getWorld()->removeObserver(observer_handle_);
101}
102
104 const moveit::core::RobotState& state) const
105{
106 checkSelfCollisionHelper(req, res, state, nullptr);
107}
108
110 const moveit::core::RobotState& state,
111 const AllowedCollisionMatrix& acm) const
112{
113 checkSelfCollisionHelper(req, res, state, &acm);
114}
115
117 const moveit::core::RobotState& state,
118 const AllowedCollisionMatrix* acm) const
119{
120 std::lock_guard<std::mutex> guard(collision_env_mutex_);
121
122 std::vector<collision_detection_bullet::CollisionObjectWrapperPtr> cows;
123 addAttachedObjects(state, cows);
124
125 if (req.distance)
126 {
127 manager_->setContactDistanceThreshold(MAX_DISTANCE_MARGIN);
128 }
129
130 for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : cows)
131 {
132 manager_->addCollisionObject(cow);
133 manager_->setCollisionObjectsTransform(
134 cow->getName(), state.getAttachedBody(cow->getName())->getGlobalCollisionBodyTransforms()[0]);
135 }
136
137 // updating link positions with the current robot state
138 for (const std::string& link : active_)
139 {
140 manager_->setCollisionObjectsTransform(link, state.getCollisionBodyTransform(link, 0));
141 }
142
143 manager_->contactTest(res, req, acm, true);
144
145 for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : cows)
146 {
147 manager_->removeCollisionObject(cow->getName());
148 }
149}
150
152 const moveit::core::RobotState& state) const
153{
154 checkRobotCollisionHelper(req, res, state, nullptr);
155}
156
158 const moveit::core::RobotState& state,
159 const AllowedCollisionMatrix& acm) const
160{
161 checkRobotCollisionHelper(req, res, state, &acm);
162}
163
165 const moveit::core::RobotState& state1,
166 const moveit::core::RobotState& state2) const
167{
168 checkRobotCollisionHelperCCD(req, res, state1, state2, nullptr);
169}
170
172 const moveit::core::RobotState& state1,
173 const moveit::core::RobotState& state2,
174 const AllowedCollisionMatrix& acm) const
175{
176 checkRobotCollisionHelperCCD(req, res, state1, state2, &acm);
177}
178
180 const moveit::core::RobotState& state,
181 const AllowedCollisionMatrix* acm) const
182{
183 std::lock_guard<std::mutex> guard(collision_env_mutex_);
184
185 if (req.distance)
186 {
187 manager_->setContactDistanceThreshold(MAX_DISTANCE_MARGIN);
188 }
189
190 std::vector<collision_detection_bullet::CollisionObjectWrapperPtr> attached_cows;
191 addAttachedObjects(state, attached_cows);
193
194 for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : attached_cows)
195 {
196 manager_->addCollisionObject(cow);
197 manager_->setCollisionObjectsTransform(
198 cow->getName(), state.getAttachedBody(cow->getName())->getGlobalCollisionBodyTransforms()[0]);
199 }
200
201 manager_->contactTest(res, req, acm, false);
202
203 for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : attached_cows)
204 {
205 manager_->removeCollisionObject(cow->getName());
206 }
207}
208
210 const moveit::core::RobotState& state1,
211 const moveit::core::RobotState& state2,
212 const AllowedCollisionMatrix* acm) const
213{
214 std::lock_guard<std::mutex> guard(collision_env_mutex_);
215
216 std::vector<collision_detection_bullet::CollisionObjectWrapperPtr> attached_cows;
217 addAttachedObjects(state1, attached_cows);
218
219 for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : attached_cows)
220 {
221 manager_CCD_->addCollisionObject(cow);
222 manager_CCD_->setCastCollisionObjectsTransform(
223 cow->getName(), state1.getAttachedBody(cow->getName())->getGlobalCollisionBodyTransforms()[0],
224 state2.getAttachedBody(cow->getName())->getGlobalCollisionBodyTransforms()[0]);
225 }
226
227 for (const std::string& link : active_)
228 {
229 manager_CCD_->setCastCollisionObjectsTransform(link, state1.getCollisionBodyTransform(link, 0),
230 state2.getCollisionBodyTransform(link, 0));
231 }
232
233 manager_CCD_->contactTest(res, req, acm, false);
234
235 for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : attached_cows)
236 {
237 manager_CCD_->removeCollisionObject(cow->getName());
238 }
239}
240
242 const moveit::core::RobotState& /*state*/) const
243{
244 RCLCPP_INFO(getLogger(), "distanceSelf is not implemented for Bullet.");
245}
246
248 const moveit::core::RobotState& /*state*/) const
249{
250 RCLCPP_INFO(getLogger(), "distanceRobot is not implemented for Bullet.");
251}
252
254{
255 std::vector<collision_detection_bullet::CollisionObjectType> collision_object_types;
256
257 for (const shapes::ShapeConstPtr& shape : obj->shapes_)
258 {
259 if (shape->type == shapes::MESH)
260 {
261 collision_object_types.push_back(collision_detection_bullet::CollisionObjectType::CONVEX_HULL);
262 }
263 else
264 {
266 }
267 }
268
269 auto cow = std::make_shared<collision_detection_bullet::CollisionObjectWrapper>(
270 obj->id_, collision_detection::BodyType::WORLD_OBJECT, obj->shapes_, obj->global_shape_poses_,
271 collision_object_types, false);
272
273 manager_->addCollisionObject(cow);
274 manager_CCD_->addCollisionObject(cow->clone());
275}
276
278{
279 if (getWorld()->hasObject(id))
280 {
281 auto it = getWorld()->find(id);
282 if (manager_->hasCollisionObject(id))
283 {
284 manager_->removeCollisionObject(id);
285 manager_CCD_->removeCollisionObject(id);
286 addToManager(it->second.get());
287 }
288 else
289 {
290 addToManager(it->second.get());
291 }
292 }
293 else
294 {
295 if (manager_->hasCollisionObject(id))
296 {
297 manager_->removeCollisionObject(id);
298 manager_CCD_->removeCollisionObject(id);
299 }
300 }
301}
302
303void CollisionEnvBullet::setWorld(const WorldPtr& world)
304{
305 if (world == getWorld())
306 return;
307
308 // turn off notifications about old world
309 getWorld()->removeObserver(observer_handle_);
310
312
313 // request notifications about changes to new world
314 observer_handle_ = getWorld()->addObserver(
315 [this](const World::ObjectConstPtr& object, World::Action action) { notifyObjectChange(object, action); });
316
317 // get notifications any objects already in the new world
318 getWorld()->notifyObserverAllObjects(observer_handle_, World::CREATE);
319}
320
321void CollisionEnvBullet::notifyObjectChange(const ObjectConstPtr& obj, World::Action action)
322{
323 std::lock_guard<std::mutex> guard(collision_env_mutex_);
324 if (action == World::DESTROY)
325 {
326 manager_->removeCollisionObject(obj->id_);
327 manager_CCD_->removeCollisionObject(obj->id_);
328 }
329 else
330 {
331 updateManagedObject(obj->id_);
332 }
333}
334
336 std::vector<collision_detection_bullet::CollisionObjectWrapperPtr>& cows) const
337{
338 std::vector<const moveit::core::AttachedBody*> attached_bodies;
339 state.getAttachedBodies(attached_bodies);
340
341 for (const moveit::core::AttachedBody*& body : attached_bodies)
342 {
343 const EigenSTL::vector_Isometry3d& attached_body_transform = body->getGlobalCollisionBodyTransforms();
344
345 std::vector<collision_detection_bullet::CollisionObjectType> collision_object_types(
347
348 try
349 {
350 collision_detection_bullet::CollisionObjectWrapperPtr cow =
351 std::make_shared<collision_detection_bullet::CollisionObjectWrapper>(
352 body->getName(), collision_detection::BodyType::ROBOT_ATTACHED, body->getShapes(),
353 attached_body_transform, collision_object_types, body->getTouchLinks());
354 cows.push_back(cow);
355 }
356 catch (std::exception&)
357 {
358 RCLCPP_ERROR_STREAM(getLogger(), "Not adding " << body->getName() << " due to bad arguments.");
359 }
360 }
361}
362
363void CollisionEnvBullet::updatedPaddingOrScaling(const std::vector<std::string>& links)
364{
365 for (const std::string& link : links)
366 {
367 if (robot_model_->getURDF()->links_.find(link) != robot_model_->getURDF()->links_.end())
368 {
369 addLinkAsCollisionObject(robot_model_->getURDF()->links_[link]);
370 }
371 else
372 {
373 RCLCPP_ERROR(getLogger(), "Updating padding or scaling for unknown link: '%s'", link.c_str());
374 }
375 }
376}
377
379 const moveit::core::RobotState& state, const collision_detection_bullet::BulletDiscreteBVHManagerPtr& manager) const
380{
381 // updating link positions with the current robot state
382 for (const std::string& link : active_)
383 {
384 // select the first of the transformations for each link (composed of multiple shapes...)
385 manager->setCollisionObjectsTransform(link, state.getCollisionBodyTransform(link, 0));
386 }
387}
388
389void CollisionEnvBullet::addLinkAsCollisionObject(const urdf::LinkSharedPtr& link)
390{
391 if (!link->collision_array.empty())
392 {
393 const std::vector<urdf::CollisionSharedPtr>& col_array =
394 link->collision_array.empty() ? std::vector<urdf::CollisionSharedPtr>(1, link->collision) :
395 link->collision_array;
396
397 std::vector<shapes::ShapeConstPtr> shapes;
399 std::vector<collision_detection_bullet::CollisionObjectType> collision_object_types;
400
401 for (const auto& i : col_array)
402 {
403 if (i && i->geometry)
404 {
405 shapes::ShapePtr shape = collision_detection_bullet::constructShape(i->geometry.get());
406
407 if (shape)
408 {
409 if (fabs(getLinkScale(link->name) - 1.0) >= std::numeric_limits<double>::epsilon() ||
410 fabs(getLinkPadding(link->name)) >= std::numeric_limits<double>::epsilon())
411 {
412 shape->scaleAndPadd(getLinkScale(link->name), getLinkPadding(link->name));
413 }
414
415 shapes.push_back(shape);
416 shape_poses.push_back(collision_detection_bullet::urdfPose2Eigen(i->origin));
417
418 if (shape->type == shapes::MESH)
419 {
420 collision_object_types.push_back(collision_detection_bullet::CollisionObjectType::CONVEX_HULL);
421 }
422 else
423 {
425 }
426 }
427 }
428 }
429
430 if (manager_->hasCollisionObject(link->name))
431 {
432 manager_->removeCollisionObject(link->name);
433 manager_CCD_->removeCollisionObject(link->name);
434 }
435
436 try
437 {
438 collision_detection_bullet::CollisionObjectWrapperPtr cow =
439 std::make_shared<collision_detection_bullet::CollisionObjectWrapper>(
440 link->name, collision_detection::BodyType::ROBOT_LINK, shapes, shape_poses, collision_object_types, true);
441 manager_->addCollisionObject(cow);
442 manager_CCD_->addCollisionObject(cow->clone());
443 active_.push_back(cow->getName());
444 }
445 catch (std::exception&)
446 {
447 RCLCPP_ERROR_STREAM(getLogger(), "Not adding " << link->name << " due to bad arguments.");
448 }
449 }
450}
451
452} // end of namespace collision_detection
Definition of a structure for the allowed collision matrix. All elements in the collision world are r...
collision_detection_bullet::BulletCastBVHManagerPtr manager_CCD_
Handles continuous robot world collision checks.
void setWorld(const WorldPtr &world) override
void updateTransformsFromState(const moveit::core::RobotState &state, const collision_detection_bullet::BulletDiscreteBVHManagerPtr &manager) const
Updates the poses of the objects in the manager according to given robot state.
void distanceSelf(const DistanceRequest &req, DistanceResult &res, const moveit::core::RobotState &state) const override
The distance to self-collision given the robot is at state state.
void updatedPaddingOrScaling(const std::vector< std::string > &links) override
Updates the collision objects saved in the manager to reflect a new padding or scaling of the robot l...
std::vector< std::string > active_
The active links where active refers to the group which can collide with everything.
void checkRobotCollisionHelperCCD(const CollisionRequest &req, CollisionResult &res, const moveit::core::RobotState &state1, const moveit::core::RobotState &state2, const AllowedCollisionMatrix *acm) const
void addAttachedObjects(const moveit::core::RobotState &state, std::vector< collision_detection_bullet::CollisionObjectWrapperPtr > &cows) const
All of the attached objects in the robot state are wrapped into bullet collision objects.
void checkRobotCollisionHelper(const CollisionRequest &req, CollisionResult &res, const moveit::core::RobotState &state, const AllowedCollisionMatrix *acm) const
void checkRobotCollision(const CollisionRequest &req, CollisionResult &res, const moveit::core::RobotState &state) const override
Check whether the robot model is in collision with the world. Any collisions between a robot link and...
void checkSelfCollision(const CollisionRequest &req, CollisionResult &res, const moveit::core::RobotState &state) const override
Check for robot self collision. Any collision between any pair of links is checked for,...
void checkSelfCollisionHelper(const CollisionRequest &req, CollisionResult &res, const moveit::core::RobotState &state, const AllowedCollisionMatrix *acm) const
Bundles the different checkSelfCollision functions into a single function.
void distanceRobot(const DistanceRequest &req, DistanceResult &res, const moveit::core::RobotState &state) const override
Compute the distance between a robot and the world.
void addLinkAsCollisionObject(const urdf::LinkSharedPtr &link)
Construts a bullet collision object out of a robot link.
collision_detection_bullet::BulletDiscreteBVHManagerPtr manager_
Handles self collision checks.
void updateManagedObject(const std::string &id)
Updates a managed collision object with its world representation.
void addToManager(const World::Object *obj)
Adds a world object to the collision managers.
Provides the interface to the individual collision checking libraries.
virtual void setWorld(const WorldPtr &world)
moveit::core::RobotModelConstPtr robot_model_
The kinematic model corresponding to this collision model.
const std::map< std::string, double > & getLinkScale() const
Get the link scaling as a map (from link names to scale value)
const std::map< std::string, double > & getLinkPadding() const
Get the link paddings as a map (from link names to padding value)
Represents an action that occurred on an object in the world. Several bits may be set indicating seve...
Definition world.h:268
Object defining bodies that can be attached to robot links.
const EigenSTL::vector_Isometry3d & getGlobalCollisionBodyTransforms() const
Get the global transforms (in world frame) for the collision bodies. The returned transforms are guar...
Representation of a robot's state. This includes position, velocity, acceleration and effort.
Definition robot_state.h:90
void getAttachedBodies(std::vector< const AttachedBody * > &attached_bodies) const
Get all bodies attached to the model corresponding to this state.
const Eigen::Isometry3d & getCollisionBodyTransform(const std::string &link_name, std::size_t index)
Get the link transform w.r.t. the root link (model frame) of the RobotModel. This is typically the ro...
const AttachedBody * getAttachedBody(const std::string &name) const
Get the attached body named name. Return nullptr if not found.
Eigen::Isometry3d urdfPose2Eigen(const urdf::Pose &pose)
std::vector< T, Eigen::aligned_allocator< T > > AlignedVector
Definition basic_types.h:37
@ USE_SHAPE_TYPE
Infer the type from the type specified in the shapes::Shape class.
@ CONVEX_HULL
Use the mesh in shapes::Shape but make it a convex hulls collision object (if not convex it will be c...
shapes::ShapePtr constructShape(const urdf::Geometry *geom)
Definition world.h:49
Representation of a collision checking request.
bool distance
If true, compute proximity distance.
Representation of a collision checking result.
Representation of a distance-reporting request.
Result of a distance request.
A representation of an object.
Definition world.h:79
EigenSTL::vector_Isometry3d global_shape_poses_
The poses of the corresponding entries in shapes_, relative to the world frame.
Definition world.h:106
EIGEN_MAKE_ALIGNED_OPERATOR_NEW std::string id_
The id for this object.
Definition world.h:87
std::vector< shapes::ShapeConstPtr > shapes_
All the shapes making up this object.
Definition world.h:96