Numerical precision of getClosestPoints calculation

physicist
Posts: 4
Joined: Tue Nov 01, 2011 5:20 pm

Numerical precision of getClosestPoints calculation

Post by physicist »

I am trying to check for the overlap of convex hulls using bullet. If I run the following example that has two cubes of side length one that would have a separation distance of 0 in exact arithmetic,

Code: Select all

#include <BulletCollision/CollisionShapes/btConvexHullShape.h>

#include <BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h>
#include <BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h>
#include <BulletCollision/NarrowPhaseCollision/btPointCollector.h>
#include <BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h>
#include <BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h>
#include <LinearMath/btIDebugDraw.h>
#include <LinearMath/btConvexHullComputer.h>

#include <iostream>

int main(int argc, char** argv)
{
  const unsigned int CubeVtxCount = 8;
  const int maxNumObjects = 4;
  const int numObjects = 2;

  btConvexShape* shapePtr[maxNumObjects];

  btScalar CubeVtx[] = {
    0.f, 0.f, 0.f,
    1.f, 0.f, 0.f,
    0.f, 1.f, 0.f,
    0.f, 0.f, 1.f,
    1.f, 1.f, 0.f,
    1.f, 0.f, 1.f,
    0.f, 1.f, 1.f,
    1.f, 1.f, 1.f
  };

  btTransform tr[numObjects];

  btConvexHullShape hullA(CubeVtx,CubeVtxCount,3*sizeof(btScalar));
  btConvexHullShape hullB(CubeVtx,CubeVtxCount,3*sizeof(btScalar));

  shapePtr[0] = &hullA;
  shapePtr[1] = &hullB;

  btMatrix3x3 basisA;
  basisA.setIdentity();

  btMatrix3x3 basisB;
  basisB.setIdentity();

  tr[0].setBasis(basisA);
  tr[1].setBasis(basisB);
  tr[0].setOrigin(btVector3(0.0f,0.f,0.f));
  tr[1].setOrigin(btVector3(0.0f,1.f,0.f));

  btVoronoiSimplexSolver sGjkSimplexSolver;
  btSimplexSolverInterface& gGjkSimplexSolver = sGjkSimplexSolver;

  btGjkEpaPenetrationDepthSolver epa;
  btGjkPairDetector cpd(shapePtr[0],shapePtr[1],&sGjkSimplexSolver,&epa);

  btPointCollector gjkOutput;
  btGjkPairDetector::ClosestPointInput input;

  input.m_transformA = tr[0];
  input.m_transformB = tr[1];

  cpd.getClosestPoints(input,gjkOutput,0);
  std::cout << gjkOutput.m_distance << std::endl;

  return 0;
}
I get the result -0.08. If I run in other configurations, I typically get an answer that deviates from the exact answer by about 0.08.

Is it possible to set precision of the solver to a smaller value?

It appears as an alternative I could achieve this by scaling the whole problem by some large factor, but I worry this might introduce some other numerical issue.

Any information about the best way to achieve this would be very appreciated.

Many thanks in advance!
User avatar
jarno
Posts: 57
Joined: Tue Mar 16, 2010 1:42 am

Re: Numerical precision of getClosestPoints calculation

Post by jarno »

There is a default collision margin of 0.04. So your shapes are actually 1.08 metres in size (spanning -0.04 to 1.04), giving an overlap of 0.08. Reduce the collision margin with the btCollisionShape->setMargin() method.

For convex-convex collisions I've found that a collision margin of 0 generally works quite nicely.

---JvdL---
physicist
Posts: 4
Joined: Tue Nov 01, 2011 5:20 pm

Re: Numerical precision of getClosestPoints calculation

Post by physicist »

Thanks so much jarno! It worked quite nicely as you suggested.