Bullet Dynamics CollisionShapes giving null pointer in CollisionObject

Post Reply
vibratingbird
Posts: 1
Joined: Mon Aug 03, 2020 8:34 am

Bullet Dynamics CollisionShapes giving null pointer in CollisionObject

Post by vibratingbird »

Greetings and thanks in advance for your advice!

I have been (trying) to work with Bullet to do collision detection only.

I inherited some code which supposedly worked at some point. I have only slightly modified it to use different collision shapes.

Unfortunately, when I add a collision shape to a collision object, and then attempt to access information about the shape using collisionObject->getCollisionShape() (for example, to do collision detection or even just see what shape type it is), I receive a null pointer.

This is less than ideal and suggests a deeper problem. I therefore did some digging, and found that the revision counter for the collision shape is not incrementing - suggesting that there is an issue when setting the collisionShape in the collisionObject. Further digging reveals that when creating, say, a box shape, the correct shape type is made and I can see that the shape related information is fine, but that the Aabb and overbounding sphere information is completely random.

For example, if I make a Broadphase using AxisSweep with worldAabbMin (-10, -10, -10) and worldAabbMax (10,10,10) and a box shape of half extents 0.25, the overbounding sphere has a radius of almost 0 and Aabb showing something like (0, -1e-365, -10) and (0,5e-320, 10). If I query the broadphase what it thinks the Aabb should be, it returns an expect min and max.

There must therefore be some deeper issue. I hope that I'm just making a silly mistake with some setting.

I have tried a variety of shape combinations. Before I pass the shape to setCollisionShape, I can still access the name, type and if the shape is convex. But, as I said, the bounds and the margin appear to be nonsense. Once I set the shape, I cannot access any shape info through the collisionObject->getCollisionShape() - when I do try I get 0. I can add the collisionObject to the collisionWorld, but again, it is as if I just passed it a null pointer. After the shape is created and added to the world, I can successfully update the position and orientation of the shape, but the Aabb, etc info remains random, I get random broadphase activations, and 0 or large negative number collision points in narrow phase. I have scoured the forums for anyone facing the same issues.

Some other issues my colleagues and I have faced which may help deduce the problem:
  • Capsule shapes do not work. Linking always fails.
  • A floating point exception can occur when creating the Broadphase.
  • When attempting to compile in Release mode, there is a segmentation fault when adding the collisionShape to the collisionWorld.
If there's any more information that might be helpful, please let me know. Thanks again!



I provide a reduced code of what I am doing below. My header file declares the variables and includes bullet/btBulletCollisionCommon.h. My source file looks something like this:

//------------------------------------------------------------------------------
// constructor

bt_collision_detector::bt_collision_detector(const double& leftbound, const double& rightbound, const std::string& collision_type) :
safety_margin(0.04),
collision_poly_type(0),
chaserbusDims(0.,0.,0.),
targetbusDims(0.,0.,0.),
temp_static_rotation(0.,0.,0., 0.,0.,0., 0.,0.,0.)
{
// Create Bullet World and Collision Objects
// Use default collision configuration and dispatcher...
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
collisionConfiguration->setConvexConvexMultipointIterations(3,3);
collisionConfiguration->setPlaneConvexMultipointIterations(3,3);

btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration);

// Init broadphase
btVector3 worldAabbMin(leftbound,leftbound,leftbound);
btVector3 worldAabbMax(rightbound,rightbound,rightbound);
btBroadphaseInterface *broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax);//,10,0,false);

// Create world and load all instantiated objects into it...
collisionWorld = new btCollisionWorld(dispatcher, broadphase, collisionConfiguration);

// Instantiate Object Dimesions
chaserbusDims = btVector3(0.5,0.5,0.5);//(0.3175,0.3175,0.3175);
targetbusDims = btVector3(0.5,0.5,0.5);//(0.3175,0.3175,0.3175);

// Instantiate Object Dimesions
set_polytopes();
}


//------------------------------------------------------------------------------
void bt_collision_detector::set_polytopes()
{
//Setting polytopes
chaserbusShape = new btBoxShape(0.5*chaserbusDims);//new btSphereShape(0.25);//
targetbusShape = new btSphereShape(0.25);

//Setting collision groups
//group, mask mask must match group of other obj

// servicer
objectChaserBus = new btCollisionObject;
objectChaserBus->setCollisionShape(chaserbusShape);
std::cout<<"OBJ BUS "<<objectChaserBus->getCollisionShape()<<std::endl; // Prints 0 to screen!!
collisionWorld->addCollisionObject(objectChaserBus, COL_OBST, COL_TARG); //COL_OBST and COL_TARG are bit set in header
std::cout<<"WORLD "<<collisionWorld->getNumCollisionObjects()<<std::endl; // Says there are 0 objects

// bus
objectTargetBus= new btCollisionObject;
objectTargetBus->setCollisionShape(targetbusShape);
std::cout<<"TAR BUS "<<objectTargetBus->getCollisionShape()<<std::endl; // See above
collisionWorld->addCollisionObject(objectTargetBus, COL_TARG, COL_OBST);
std::cout<<"WORLD "<<collisionWorld->getNumCollisionObjects()<<std::endl;

}




//------------------------------------------------------------------------------
// destructor

bt_collision_detector::~bt_collision_detector()
{
// remove collision objects and free memory

delete targetbusShape;
delete chaserbusShape;

delete collisionWorld;
delete dispatcher;
delete collisionConfiguration;
delete broadphase;
}




//------------------------------------------------------------------------------
//! update object world transform
void bt_collision_detector::get_pose(const Matrix44& trafo, btCollisionObject* obj_in)
{
temp_static_rotation.setValue(trafo(0,0), trafo(0,1), trafo(0,2),
trafo(1,0), trafo(1,1), trafo(1,2),
trafo(2,0), trafo(2,1), trafo(2,2));

obj_in->setWorldTransform(btTransform(temp_static_rotation,
btVector3(trafo(0,3),trafo(1,3),trafo(2,3))));


//std::cout<<""<<std::flush;
}





//------------------------------------------------------------------------------
double bt_collision_detector::check_collision_constraint( Matrix44& tChaser_Bus, const Matrix44& tTarget_Bus, const Matrix44& tTarget_Pan1, const Matrix44 tTarget_Pan2, const Matrix44 tTarget_Ant)
{

//std::cout<<"-- -- -- Checking collision constraint"<<std::endl;
//std::cout<<"-- -- -- -- updating chaser pose"<<std::endl;


get_pose(tChaser_Bus, objectChaserBus);
get_pose(tTarget_Bus, objectTargetBus);

// DISCRETE COLLISION DETECTION
btScalar penetration = 0.;
btScalar lastpenetration = 0.;
collision_data::stdvScalar depths;

collisionWorld->getDispatcher();

//std::cout<<"-- -- -- -- collision detection "<<std::endl;
collisionWorld->performDiscreteCollisionDetection();
collisionWorld->computeOverlappingPairs();
//broadphase->calculateOverlappingPairs();

int numManifolds=collisionWorld->getDispatcher()->getNumManifolds();
std::cout<<"-- -- -- -- Number of manifolds "<<numManifolds<<std::endl;
// number of persistent manifolds (collisions between collision pairs)
for (int i=0; i<collisionWorld->getDispatcher()->getNumManifolds(); i++) {


// Find collision pairs
btPersistentManifold* contactManifold = collisionWorld->getDispatcher()->getManifoldByIndexInternal(i);
const btCollisionObject* obA = contactManifold->getBody0();
const btCollisionObject* obB = contactManifold->getBody1();
//std::cout<<"body A "<<obA->getWorldTransform().getOrigin().getX()<<std::endl;//<<" body B "<<obB->getUserIndex()<<std::endl;
//btScalar obax = obA->getWorldTransform().getOrigin().getX();

int numContacts=contactManifold->getNumContacts();
std::cout<<"-- -- -- -- -- Number of contacts "<<numContacts<<std::endl;
if (numContacts>10000) numContacts = 10000;
for (int j=0; j<numContacts; j++) {

//std::cout<<"-- -- -- -- -- looping!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11"<<std::endl;

// detailed info about one contact point within a collision pair
//std::cout << "contact manifold " << j << " of " << contactManifold->getNumContacts() << std::endl;
// std::cerr << "lastpenetration = " << lastpenetration << std::endl;
// std::cerr << "tS:\n";
// std::cerr << tS << std::endl;
lastpenetration = contactManifold->getContactPoint(j).getDistance();

if (j==0) { penetration = lastpenetration; }
/*
if (penetration<(-1.*safety_margin)) {
if (lastpenetration > penetration) {
penetration = lastpenetration;
}
}*/

}

depths.push_back(-1.*penetration);
}
// return max pen depth for all collision pairs
int mindex = 0;
for (uint k=1; k<depths.size(); ++k) {
if (depths[k]>depths[mindex]) {
mindex = k;
}
}
if (depths.size() < 1) {
return (0.);
}
else {
return (depths[mindex]);
}
}
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Bullet Dynamics CollisionShapes giving null pointer in CollisionObject

Post by drleviathan »

Your problems are mysterious but they don't sound like problems with Bullet per-se. For example consider this bit of code:

Code: Select all

objectChaserBus = new btCollisionObject;
objectChaserBus->setCollisionShape(chaserbusShape);
std::cout<<"OBJ BUS "<<objectChaserBus->getCollisionShape()<<std::endl; // Prints 0 to screen!!
If your comment about getting zero (nullptr) shape right after setting the shape is true... then something very fundamental (deeper than Bullet itself) is going wrong. I don't know what it is, but it is terrible and you probably won't get any valid data until you figure out what it is.

To verify the above conclusion I took your bt_collision_detector class and pasted it into Bullet's own HelloWorld.cpp example, commented out the unused stuff, stubbed out the class declaration, and compiled the examples. In the main() method I instantiated one bt_collision_detector. When I ran the App_HelloWorld the relevant code in bt_collision_detector::set_polytopes() printed out the following on my system:

Code: Select all

    OBJ BUS 0x5603ce5388c0
    WORLD 1
    TAR BUS 0x5603ce538930
    WORLD 2
In short: you need to do sanity checking. My advice: grab a fresh copy of Bullet source code, build it yourself, copy your own custom source code off to the side and write fresh CMake (or whatever build script system you're using) config files and prove to yourself that properly written, compiled, and linked C++ code does what you tell it to.
Post Reply