Determine ground reaction force after collision

Post Reply
Marcell
Posts: 14
Joined: Fri Oct 19, 2012 8:58 am

Determine ground reaction force after collision

Post by Marcell »

Hello!

I'm using BT to simulate a humanoid robot and I am currently researching fall mitigation strategies. When the robot falls to the ground, I would like to determine the ground reaction force / torque acting on the rigid bodies in the moment of the impact, and the torque acting on the joints (motors) of the robot.

Concerning rigid bodies, I tried to access the forces and toques acting on the bodies like so:

Code: Select all

dynamicsWorld->stepSimulation(config.systemIterationTime, int(5.0 * config.systemIterationTime), 1.0);

foreach (btRigidBody* rb, rigidBodies)
{
        qDebug() << rb->getTotalForce().length();
        qDebug() << rb->getTotalTorque().length();
}
but the reported forces and torques are always zero. After browsing the btRigidBody object, I cannot see any other obvious way to access this data. Can anyone please help?


When it comes to joints (btGeneric6DofConstraint), I found the btGeneric6DofConstraint::getAppliedImpulse() to report some quantity that peaks when bodies collide. I have however no idea what exactly this quantity is nor can I resolve this to torques about the rotational axes of the joint. I found that joint->getRotationalLimitMotor(0)->m_accumulatedImpulse sounds like it could be something of interest, but this field is always zero. Again, can anyone please me point me to a way to retrieve the information I'm looking for?

Thank you,
Marcell
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Determine ground reaction force after collision

Post by drleviathan »

I don't think it is possible to get the forces between impacting bodies in Bullet. Contact between objects is treated as a constraint and is resolved using a Jacobian which solves for the position and velocity using implicit forces -- that is the forces are whatever it takes to ensure the constraint it satisfied. This provides a more efficient algorithm than using explicit forces.

The btRigidBody::getTotalForce() method is used internally by the btDynamicsWorld during the integration step to get the total external force on an object. External forces are cleared at the end of the step and new forces must be applied between steps by Actions or other custom game logic. In other words, Bullet allows users to apply per-frame external forces on objects and will accelerate them accordingly, but there is no way to query internal forces during the simulation.

Most real-time physics engines do not provide access to internal forces. You'll probably need a non-real-time physics engine.

You could manually measure the per-step velocity of an object and use previous_velocity and current_velocity to compute a total_acceleration which can be used to compute the total_force on the object (similarly for angular measurements), however the frame by frame value of acceleration will be quite noisy, and during complex interactions there won't be a way to determine how much of it can be attributed to a particular contact pair or constraint.
gdlk
Posts: 62
Joined: Fri Oct 24, 2014 7:01 pm

Re: Determine ground reaction force after collision

Post by gdlk »

Respect the joints, try with btJointFeedback.

Code: Select all

//when you set the joint
btJointFeedback* jf = new btJointFeedback();
joint.setJointFeedback(jf);

//then, in the simulation you can call
jf->m_appliedForceBodyB;

Respect the floor, I dont know (I have never need it xD )

Regards!
IresomPCH
Posts: 18
Joined: Tue Sep 24, 2013 12:29 pm

Re: Determine ground reaction force after collision

Post by IresomPCH »

Hello,

To get contact points between rigidBodies, you may refer to this link:
http://bulletphysics.org/mediawiki-1.5. ... d_Triggers

by using codes like this:
------------------------------------------------------------------------------
int numManifolds = world->getDispatcher()->getNumManifolds();
for (int i=0;i<numManifolds;i++)
{
btPersistentManifold* contactManifold = world->getDispatcher()->getManifoldByIndexInternal(i);
btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());


int numContacts = contactManifold->getNumContacts();
for (int j=0;j<numContacts;j++)
{
btManifoldPoint& pt = contactManifold->getContactPoint(j);// get contact point
if (pt.getDistance()<0.f)// see if obA and obB collide
{
float impulse = pt.m_appliedImpulse;// get impules
const btVector3& ptA = pt.getPositionWorldOnA();// global contact position
const btVector3& ptB = pt.getPositionWorldOnB();// global contact position
const btVector3& normalOnB = pt.m_normalWorldOnB;// global contact vector
}
}
}
------------------------------------------------------------------------------

If you set the userIndex (or userObject) property of those rigidBodies when setting up, it's easy to see if the obA or obB is the ridigBody you want.
Also, the impulse value can be scaled to force by simply multiplying a scaler depending on your parameters.
Post Reply