coal-library / coal

An extension of the Flexible Collision Library
Other
328 stars 93 forks source link

Computing multiple contact points for Box-Box collision #616

Closed vastsoun closed 3 months ago

vastsoun commented 3 months ago

Hi there,

I've been trying to set up a box-on-box collision, one for a cube and another for a floor/ground, but have been getting only a single contact when performing collision checking. I used the unit test provided in test/box_box_collision.cpp as a sanity check against my own code, but it yields the same result:

Running 1 test case...
Num. Collisions: 1
Num. Collisions: 1
Num. Collisions: 0
Num. Collisions: 0

My question is: is it expected or intended to only issue a single contact for box-box or am I doing something wrong? What I wanted to get was four (4) contacts.

Here is the modified version of the code I used to verify:

BOOST_AUTO_TEST_CASE(box_box_collision) {
  // Define boxes
  Box shape1(1, 1, 1);
  Box shape2(10, 10, 1);

  // Define transforms
  Transform3f T1 = Transform3f::Identity();
  Transform3f T2 = Transform3f::Identity();

  // Compute collision
  CollisionRequest req;
  req.num_max_contacts = 4;
  req.enable_cached_gjk_guess = true;
  req.distance_upper_bound = 1e-6;
  CollisionResult res;
  ComputeCollision collide_functor(&shape1, &shape2);

  T1.setTranslation(Vec3f(0, 0, 0.49));
  T2.setTranslation(Vec3f(0, 0, -0.5));
  res.clear();
  BOOST_CHECK(collide(&shape1, T1, &shape2, T2, req, res) == true);
  std::cout << "Num. Collisions: " << res.numContacts() << std::endl;
  res.clear();
  BOOST_CHECK(collide_functor(T1, T2, req, res) == true);
  std::cout << "Num. Collisions: " << res.numContacts() << std::endl;

  T1.setTranslation(Vec3f(0, 0, 1));
  res.clear();
  BOOST_CHECK(collide(&shape1, T1, &shape2, T2, req, res) == false);
  std::cout << "Num. Collisions: " << res.numContacts() << std::endl;
  res.clear();
  BOOST_CHECK(collide_functor(T1, T2, req, res) == false);
  std::cout << "Num. Collisions: " << res.numContacts() << std::endl;
}

I compiled and built the current version on the devel branch.

lmontaut commented 3 months ago

Hi @vastsoun, You can check out https://github.com/humanoid-path-planner/hpp-fcl/pull/574 to see how to compute multiple contact points. More processing is required to go from collision detection (computing the contact normal and a pair of contact points) to contact surface computation (computing multiple pairs of contact points that all share the same contact normal). Therefore, the contact surface computation uses the computeContactPatch function.

The num_max_contacts parameter in the CollisionRequest is the maximum number of contact normals that collide can compute. Since primitives are convex in hpp-fcl (box, sphere, ellipsoid, cones, convex meshes etc.), there is only one normal per call to collide. The num_max_contacts is therefore only useful for non-convex objects such as BVHModel shapes.