Making Bullet Deterministic

Post Reply
shahinRab
Posts: 1
Joined: Wed Oct 18, 2017 8:44 pm

Making Bullet Deterministic

Post by shahinRab »

I am working on a stochastic optimization project for humanoid locomotion where I need to be able to snapshot the simulation and restore the simulation state many times during sampling. The initial tests on the character showed the roll-backs and roll-forwards are not suggesting a deterministic behavior. Even for a simple test case of tossing a bunch of boxes around and computing the collective center of mass I see it is slightly different each time.

I have read the other posts about making Bullet deterministic. While there were great suggestions, still I can not make it work.

So far I have avoided destroying and recreating the world, due to its high computational cost and the complexity of the code. Instead, I have tried the following and got slightly better deterministic behavior, but not fully there. The following is mostly taken from Bullet own reset function.

Code: Select all

void PhysicsMediator::reset()
{
	if (m_dynamicsWorld)
	{
		numObjects = m_dynamicsWorld->getNumCollisionObjects();

		///create a copy of the array, not a reference!
		btCollisionObjectArray copyArray = m_dynamicsWorld->getCollisionObjectArray();

		for (i = 0;i < numObjects;i++)
		{
			btCollisionObject* colObj = copyArray[i];
			btRigidBody* body = btRigidBody::upcast(colObj);
			if (body)
			{
				if (body->getMotionState())
				{
					btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState();
					myMotionState->m_graphicsWorldTrans = myMotionState->m_startWorldTrans;
					body->setCenterOfMassTransform(myMotionState->m_graphicsWorldTrans);
					colObj->setInterpolationWorldTransform(myMotionState->m_startWorldTrans);
					colObj->forceActivationState(ACTIVE_TAG);
					colObj->activate();
					colObj->setActivationState(DISABLE_DEACTIVATION);	
					colObj->setDeactivationTime(btScalar(2e7));
				}
				//removed cached contact points (this is not necessary if all objects have been removed from the dynamics world)
				m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(colObj->getBroadphaseHandle(),m_dynamicsWorld->getDispatcher());

				btRigidBody* body = btRigidBody::upcast(colObj);
				if (body && !body->isStaticObject())
				{
					btRigidBody::upcast(colObj)->setLinearVelocity(btVector3(0, 0, 0));
					btRigidBody::upcast(colObj)->setAngularVelocity(btVector3(0, 0, 0));

					btRigidBody::upcast(colObj)->clearForces();
				}
			}
		}

		///reset some internal cached data in the broad phase
		m_dynamicsWorld->getBroadphase()->resetPool(m_dynamicsWorld->getDispatcher());
		m_dynamicsWorld->getConstraintSolver()->reset();
	}
}
In addition to the reset function you see, I have turned off the warm start in the solver, and made sure the btSequentialImpulseConstraintSolver is not randomized. What else? Am I missing anything? I am mostly suspecting the constraint solver and the collision handling stuff are the culprits. Is there any randomness involved in any of them that I am not aware of?

Thanks
Shahin
User avatar
xissburg
Posts: 46
Joined: Sat May 19, 2007 9:28 pm

Re: Making Bullet Deterministic

Post by xissburg »

You could also try disabling islands:

mDynamicsWorld->getSimulationIslandManager()->setSplitIslands(false);

SOLVER_RANDMIZE_ORDER should be disabled by default so the order of the constraints in the solver shouldn't be randomized, though, they can be indirectly randomized when contact points are not persisted and end up being recreated and the order of contact points in a manifold is changed.
Post Reply