37 #include <btBulletCollisionCommon.h>
61 inline bool acmCheck(
const std::string& body_1,
const std::string& body_2,
72 ROS_DEBUG_STREAM_NAMED(
"collision_detection.bullet",
"Not allowed entry in ACM found, collision check between "
73 << body_1 <<
" and " << body_2);
78 ROS_DEBUG_STREAM_NAMED(
"collision_detection.bullet",
"Entry in ACM found, skipping collision check as allowed "
79 << body_1 <<
" and " << body_2);
86 "No entry in ACM found, collision check between " << body_1 <<
" and " << body_2);
93 "No ACM, collision check between " << body_1 <<
" and " << body_2);
101 return btVector3(
static_cast<btScalar
>(v[0]),
static_cast<btScalar
>(v[1]),
static_cast<btScalar
>(v[2]));
107 return Eigen::Vector3d(
static_cast<double>(v.x()),
static_cast<double>(v.y()),
static_cast<double>(v.z()));
113 return btQuaternion(
static_cast<btScalar
>(q.x()),
static_cast<btScalar
>(q.y()),
static_cast<btScalar
>(q.z()),
114 static_cast<btScalar
>(q.w()));
120 return btMatrix3x3(
static_cast<btScalar
>(
r(0, 0)),
static_cast<btScalar
>(
r(0, 1)),
static_cast<btScalar
>(
r(0, 2)),
121 static_cast<btScalar
>(
r(1, 0)),
static_cast<btScalar
>(
r(1, 1)),
static_cast<btScalar
>(
r(1, 2)),
122 static_cast<btScalar
>(
r(2, 0)),
static_cast<btScalar
>(
r(2, 1)),
static_cast<btScalar
>(
r(2, 2)));
128 const Eigen::Matrix3d& rot =
t.matrix().block<3, 3>(0, 0);
134 return btTransform(mat, translation);
143 class CollisionObjectWrapper :
public btCollisionObject
146 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
152 const std::vector<shapes::ShapeConstPtr>&
shapes,
153 const AlignedVector<Eigen::Isometry3d>& shape_poses,
154 const std::vector<CollisionObjectType>& collision_object_types,
bool active =
true);
160 const std::vector<shapes::ShapeConstPtr>&
shapes,
161 const AlignedVector<Eigen::Isometry3d>& shape_poses,
162 const std::vector<CollisionObjectType>& collision_object_types,
163 const std::set<std::string>& touch_links);
178 const std::string&
getName()
const
197 [](
const Eigen::Isometry3d& t1,
const Eigen::Isometry3d& t2) { return t1.isApprox(t2); });
203 void getAABB(btVector3& aabb_min, btVector3& aabb_max)
const
205 getCollisionShape()->getAabb(getWorldTransform(), aabb_min, aabb_max);
206 const btScalar&
distance = getContactProcessingThreshold();
209 aabb_min -= contact_threshold;
210 aabb_max += contact_threshold;
215 std::shared_ptr<CollisionObjectWrapper>
clone()
217 std::shared_ptr<CollisionObjectWrapper> clone_cow(
219 clone_cow->setCollisionShape(getCollisionShape());
220 clone_cow->setWorldTransform(getWorldTransform());
224 clone_cow->setBroadphaseHandle(
nullptr);
226 clone_cow->setContactProcessingThreshold(this->getContactProcessingThreshold());
234 m_data.push_back(std::shared_ptr<T>(
t));
239 void manage(std::shared_ptr<T> t)
247 const std::vector<shapes::ShapeConstPtr>&
shapes,
248 const AlignedVector<Eigen::Isometry3d>& shape_poses,
249 const std::vector<CollisionObjectType>& collision_object_types,
250 const std::vector<std::shared_ptr<void>>& data);
258 std::vector<shapes::ShapeConstPtr>
m_shapes;
267 std::vector<std::shared_ptr<void>>
m_data;
285 m_shapeType = CUSTOM_CONVEX_SHAPE_TYPE;
296 btVector3 support_vector_0 =
m_shape->localGetSupportingVertex(vec);
297 btVector3 support_vector_1 =
299 return (vec.dot(support_vector_0) > vec.dot(support_vector_1)) ? support_vector_0 : support_vector_1;
306 throw std::runtime_error(
"not implemented");
312 void getAabb(
const btTransform& transform_world, btVector3& aabbMin, btVector3& aabbMax)
const override
314 m_shape->getAabb(transform_world, aabbMin, aabbMax);
315 btVector3 min1, max1;
317 aabbMin.setMin(min1);
318 aabbMax.setMax(max1);
321 void getAabbSlow(
const btTransform& , btVector3& , btVector3& )
const override
323 throw std::runtime_error(
"shouldn't happen");
332 static btVector3 out(1, 1, 1);
352 throw std::runtime_error(
"not implemented");
357 throw std::runtime_error(
"not implemented");
379 inline void getAverageSupport(
const btConvexShape* shape,
const btVector3& localNormal,
float& outsupport,
382 btVector3 pt_sum(0, 0, 0);
384 float max_support = -1000;
386 const btPolyhedralConvexShape* pshape =
dynamic_cast<const btPolyhedralConvexShape*
>(shape);
389 int n_pts = pshape->getNumVertices();
391 for (
int i = 0; i < n_pts; ++i)
394 pshape->getVertex(i, pt);
396 float sup = pt.dot(localNormal);
412 outsupport = max_support;
413 outpt = pt_sum / pt_count;
417 outpt = shape->localGetSupportingVertexWithoutMargin(localNormal);
418 outsupport = localNormal.dot(outpt);
424 const btCollisionObjectWrapper* colObj1Wrap, ContactTestData& collisions)
426 assert(
dynamic_cast<const CollisionObjectWrapper*
>(colObj0Wrap->getCollisionObject()) !=
nullptr);
427 assert(
dynamic_cast<const CollisionObjectWrapper*
>(colObj1Wrap->getCollisionObject()) !=
nullptr);
428 const CollisionObjectWrapper* cd0 =
static_cast<const CollisionObjectWrapper*
>(colObj0Wrap->getCollisionObject());
429 const CollisionObjectWrapper* cd1 =
static_cast<const CollisionObjectWrapper*
>(colObj1Wrap->getCollisionObject());
431 std::pair<std::string, std::string> pc =
getObjectPairKey(cd0->getName(), cd1->getName());
433 const auto& it = collisions.res.contacts.find(pc);
434 bool found = (it != collisions.res.contacts.end());
439 contact.
depth =
static_cast<double>(cp.m_distance1);
456 inline btScalar
addCastSingleResult(btManifoldPoint& cp,
const btCollisionObjectWrapper* colObj0Wrap,
int ,
457 const btCollisionObjectWrapper* colObj1Wrap,
int ,
458 ContactTestData& collisions)
460 assert(
dynamic_cast<const CollisionObjectWrapper*
>(colObj0Wrap->getCollisionObject()) !=
nullptr);
461 assert(
dynamic_cast<const CollisionObjectWrapper*
>(colObj1Wrap->getCollisionObject()) !=
nullptr);
463 const CollisionObjectWrapper* cd0 =
static_cast<const CollisionObjectWrapper*
>(colObj0Wrap->getCollisionObject());
464 const CollisionObjectWrapper* cd1 =
static_cast<const CollisionObjectWrapper*
>(colObj1Wrap->getCollisionObject());
466 std::pair<std::string, std::string> pc =
getObjectPairKey(cd0->getName(), cd1->getName());
468 const auto& it = collisions.res.contacts.find(pc);
469 bool found = (it != collisions.res.contacts.end());
474 contact.
depth =
static_cast<double>(cp.m_distance1);
488 assert(!((cd0->m_collisionFilterGroup == btBroadphaseProxy::KinematicFilter) &&
489 (cd1->m_collisionFilterGroup == btBroadphaseProxy::KinematicFilter)));
491 bool cast_shape_is_first = cd0->m_collisionFilterGroup == btBroadphaseProxy::KinematicFilter;
493 btVector3 normal_world_from_cast = (cast_shape_is_first ? -1 : 1) * cp.m_normalWorldOnB;
494 const btCollisionObjectWrapper* first_col_obj_wrap = (cast_shape_is_first ? colObj0Wrap : colObj1Wrap);
497 if (cast_shape_is_first)
506 btTransform tf_world0, tf_world1;
507 const CastHullShape* shape =
static_cast<const CastHullShape*
>(first_col_obj_wrap->getCollisionShape());
509 tf_world0 = first_col_obj_wrap->getWorldTransform();
510 tf_world1 = first_col_obj_wrap->getWorldTransform() * shape->m_shape_transform;
513 btVector3 normal_local0 = normal_world_from_cast * tf_world0.getBasis();
514 btVector3 normal_local1 = normal_world_from_cast * tf_world1.getBasis();
519 btVector3 pt_world0 = tf_world0 * pt_local0;
523 btVector3 pt_world1 = tf_world1 * pt_local1;
525 float sup0 = normal_world_from_cast.dot(pt_world0);
526 float sup1 = normal_world_from_cast.dot(pt_world1);
539 const btVector3& pt_on_cast = cast_shape_is_first ? cp.m_positionWorldOnA : cp.m_positionWorldOnB;
540 float l0c = (pt_on_cast - pt_world0).
length();
541 float l1c = (pt_on_cast - pt_world1).
length();
557 inline bool isOnlyKinematic(
const CollisionObjectWrapper* cow0,
const CollisionObjectWrapper* cow1)
559 return cow0->m_collisionFilterGroup == btBroadphaseProxy::KinematicFilter &&
560 cow1->m_collisionFilterGroup == btBroadphaseProxy::KinematicFilter;
567 struct BroadphaseContactResultCallback
590 bool needsCollision(
const CollisionObjectWrapper* cow0,
const CollisionObjectWrapper* cow1)
const
604 btScalar
addSingleResult(btManifoldPoint& cp,
const btCollisionObjectWrapper* colObj0Wrap,
int ,
605 int index0,
const btCollisionObjectWrapper* colObj1Wrap,
int ,
int index1)
624 struct TesseractBroadphaseBridgedManifoldResult :
public btManifoldResult
629 const btCollisionObjectWrapper* obj1Wrap,
630 BroadphaseContactResultCallback& result_callback)
635 void addContactPoint(
const btVector3& normalOnBInWorld,
const btVector3& pointInWorld, btScalar depth)
override
643 bool is_swapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
644 btVector3 point_a = pointInWorld + normalOnBInWorld * depth;
649 local_a = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(point_a);
650 local_b = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
654 local_a = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(point_a);
655 local_b = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
658 btManifoldPoint new_pt(local_a, local_b, normalOnBInWorld, depth);
659 new_pt.m_positionWorldOnA = point_a;
660 new_pt.m_positionWorldOnB = pointInWorld;
665 new_pt.m_partId0 = m_partId1;
666 new_pt.m_partId1 = m_partId0;
667 new_pt.m_index0 = m_index1;
668 new_pt.m_index1 = m_index0;
672 new_pt.m_partId0 = m_partId0;
673 new_pt.m_partId1 = m_partId1;
674 new_pt.m_index0 = m_index0;
675 new_pt.m_index1 = m_index1;
679 const btCollisionObjectWrapper* obj0_wrap = is_swapped ? m_body1Wrap : m_body0Wrap;
680 const btCollisionObjectWrapper* obj1_wrap = is_swapped ? m_body0Wrap : m_body1Wrap;
690 class TesseractCollisionPairCallback :
public btOverlapCallback
700 BroadphaseContactResultCallback& results_callback)
716 const CollisionObjectWrapper* cow0 =
static_cast<const CollisionObjectWrapper*
>(pair.m_pProxy0->m_clientObject);
717 const CollisionObjectWrapper* cow1 =
static_cast<const CollisionObjectWrapper*
>(pair.m_pProxy1->m_clientObject);
719 std::pair<std::string, std::string> pair_names{ cow0->getName(), cow1->getName() };
723 "Processing " << cow0->getName() <<
" vs " << cow1->getName());
724 btCollisionObjectWrapper obj0_wrap(
nullptr, cow0->getCollisionShape(), cow0, cow0->getWorldTransform(), -1, -1);
725 btCollisionObjectWrapper obj1_wrap(
nullptr, cow1->getCollisionShape(), cow1, cow1->getWorldTransform(), -1, -1);
728 if (!pair.m_algorithm)
730 pair.m_algorithm =
dispatcher_->findAlgorithm(&obj0_wrap, &obj1_wrap,
nullptr, BT_CLOSEST_POINT_ALGORITHMS);
733 if (pair.m_algorithm)
736 contact_point_result.m_closestPointDistanceThreshold =
740 pair.m_algorithm->processCollision(&obj0_wrap, &obj1_wrap,
dispatch_info_, &contact_point_result);
746 "Not processing " << cow0->getName() <<
" vs " << cow1->getName());
769 cow.m_collisionFilterGroup = btBroadphaseProxy::StaticFilter;
770 cow.m_collisionFilterMask = btBroadphaseProxy::KinematicFilter;
774 cow.m_collisionFilterGroup = btBroadphaseProxy::KinematicFilter;
775 cow.m_collisionFilterMask = btBroadphaseProxy::KinematicFilter | btBroadphaseProxy::StaticFilter;
778 if (cow.getBroadphaseHandle())
780 cow.getBroadphaseHandle()->m_collisionFilterGroup = cow.m_collisionFilterGroup;
781 cow.getBroadphaseHandle()->m_collisionFilterMask = cow.m_collisionFilterMask;
784 << cow.m_collisionFilterGroup <<
" mask "
785 << cow.m_collisionFilterMask);
790 CollisionObjectWrapperPtr new_cow = cow->clone();
795 if (btBroadphaseProxy::isConvex(new_cow->getCollisionShape()->getShapeType()))
797 assert(
dynamic_cast<btConvexShape*
>(new_cow->getCollisionShape()) !=
nullptr);
798 btConvexShape* convex =
static_cast<btConvexShape*
>(new_cow->getCollisionShape());
801 assert(convex->getShapeType() != CUSTOM_CONVEX_SHAPE_TYPE);
805 new_cow->manage(shape);
806 new_cow->setCollisionShape(shape);
808 else if (btBroadphaseProxy::isCompound(new_cow->getCollisionShape()->getShapeType()))
810 btCompoundShape* compound =
static_cast<btCompoundShape*
>(new_cow->getCollisionShape());
811 btCompoundShape* new_compound =
814 for (
int i = 0; i < compound->getNumChildShapes(); ++i)
816 if (btBroadphaseProxy::isConvex(compound->getChildShape(i)->getShapeType()))
818 btConvexShape* convex =
static_cast<btConvexShape*
>(compound->getChildShape(i));
819 assert(convex->getShapeType() != CUSTOM_CONVEX_SHAPE_TYPE);
821 btTransform geom_trans = compound->getChildTransform(i);
825 new_cow->manage(subshape);
827 new_compound->addChildShape(geom_trans, subshape);
829 else if (btBroadphaseProxy::isCompound(compound->getChildShape(i)->getShapeType()))
831 btCompoundShape* second_compound =
static_cast<btCompoundShape*
>(compound->getChildShape(i));
832 btCompoundShape* new_second_compound =
834 for (
int j = 0; j < second_compound->getNumChildShapes(); ++j)
836 assert(!btBroadphaseProxy::isCompound(second_compound->getChildShape(j)->getShapeType()));
838 btConvexShape* convex =
static_cast<btConvexShape*
>(second_compound->getChildShape(j));
839 assert(convex->getShapeType() != CUSTOM_CONVEX_SHAPE_TYPE);
841 btTransform geom_trans = second_compound->getChildTransform(j);
843 btCollisionShape* subshape =
new CastHullShape(convex, tf);
845 new_cow->manage(subshape);
847 new_second_compound->addChildShape(geom_trans, subshape);
850 btTransform geom_trans = compound->getChildTransform(i);
852 new_cow->manage(new_second_compound);
856 new_compound->addChildShape(geom_trans, new_second_compound);
861 "I can only collision check convex shapes and compound shapes made of convex shapes");
862 throw std::runtime_error(
"I can only collision check convex shapes and compound shapes made of convex shapes");
868 new_cow->manage(new_compound);
869 new_cow->setCollisionShape(new_compound);
870 new_cow->setWorldTransform(cow->getWorldTransform());
875 "I can only collision check convex shapes and compound shapes made of convex shapes");
876 throw std::runtime_error(
"I can only collision check convex shapes and compound shapes made of convex shapes");
887 const std::unique_ptr<btBroadphaseInterface>& broadphase,
888 const std::unique_ptr<btCollisionDispatcher>& dispatcher)
890 btVector3 aabb_min, aabb_max;
891 cow->getAABB(aabb_min, aabb_max);
893 assert(cow->getBroadphaseHandle() !=
nullptr);
894 broadphase->setAabb(cow->getBroadphaseHandle(), aabb_min, aabb_max, dispatcher.get());
902 const std::unique_ptr<btBroadphaseInterface>& broadphase,
903 const std::unique_ptr<btCollisionDispatcher>& dispatcher)
905 btBroadphaseProxy* bp = cow->getBroadphaseHandle();
909 broadphase->getOverlappingPairCache()->cleanProxyFromPairs(bp, dispatcher.get());
910 broadphase->destroyProxy(bp, dispatcher.get());
911 cow->setBroadphaseHandle(
nullptr);
920 const std::unique_ptr<btBroadphaseInterface>& broadphase,
921 const std::unique_ptr<btCollisionDispatcher>& dispatcher)
924 btVector3 aabb_min, aabb_max;
925 cow->getAABB(aabb_min, aabb_max);
927 int type = cow->getCollisionShape()->getShapeType();
928 cow->setBroadphaseHandle(broadphase->createProxy(aabb_min, aabb_max, type, cow.get(), cow->m_collisionFilterGroup,
929 cow->m_collisionFilterMask, dispatcher.get()));
936 bool cull = !(proxy0->m_collisionFilterMask & proxy1->m_collisionFilterGroup);
937 cull = cull || !(proxy1->m_collisionFilterMask & proxy0->m_collisionFilterGroup);
945 if (!cow0->m_enabled)
948 if (!cow1->m_enabled)
953 if (cow0->m_touch_links.find(cow1->getName()) != cow0->m_touch_links.end())
958 if (cow1->m_touch_links.find(cow0->getName()) != cow1->m_touch_links.end())
963 if (cow0->m_touch_links == cow1->m_touch_links)
967 "Broadphase pass " << cow0->getName() <<
" vs " << cow1->getName());