Search code examples
game-physicsphysics-enginebulletphysics

How physics engine calcute the rigid body motion? And why different engine give me different result


I want to simulate an object imposed by a torque T={1,1,1} with reference to the world frame. The mass of the object is 1Kg, and its diagonal elements of inertia tensor is {2, 1, 1}. However bullet2.7 and bullet2.8 give me totally different results

#include <btBulletDynamicsCommon.h>  
#include <stdio.h>
#include <iostream>
#include <fstream> 
using namespace std;

/// This is a Hello World program for running a basic Bullet physics simulation

int main(int argc, char** argv)
{

btBroadphaseInterface* broadphase = new btDbvtBroadphase();

///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();

///use the default collision dispatcher. For parallel processing you can use a differnt dispatcher
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);

///the default constraint solver. For parallel processing you can use a different solver
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;

///instantiate the dynamics world
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);

///sets the gravity
dynamicsWorld->setGravity(btVector3(0, 0, 0));


btCollisionShape* Shape = new btSphereShape(1);


//The btTransform class supports rigid transforms with only translation and rotation 
btDefaultMotionState* MotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, 50, 0)));

btScalar mass = 1;
btVector3 Inertia(2, 1, 1);
btVector3 torque(1, 1, 1);
btVector3 angularVelocity(0, 0, 0);

///when bodies are constructed, they are passed certain parameters. This is done through a special structure Bullet provides for this.
///rigid body is dynamic if and only if mass is non zero, otherwise static  
btRigidBody::btRigidBodyConstructionInfo RigidBodyCI(mass, MotionState, Shape, Inertia);
btRigidBody* RigidBody = new btRigidBody(RigidBodyCI);
dynamicsWorld->addRigidBody(RigidBody);

ofstream outfile("data.csv", ios::out);
for (int i = 0; i < 300; i++) {

    RigidBody->applyTorque(torque);

    dynamicsWorld->stepSimulation(1 / 60.f, 10);

    angularVelocity = RigidBody->getAngularVelocity();

    outfile << angularVelocity.getX() << "," << angularVelocity.getY() << "," << angularVelocity.getZ() << endl;
}

outfile.close();

delete Shape;


delete dynamicsWorld;
delete solver;
delete dispatcher;
delete collisionConfiguration;
delete broadphase;

printf("Press a key to exit\n");
getchar();
}

Bullet 2.78: result of bullet 2.78

Bullet 2.83: result of bullet 2.83


Solution

  • Physics engines will give different results of course when how they're calculating them is different between them. And that's what you're noticing.

    Physics engines that are interactive or "real-time" (like Box2D and Bullet), typically aren't meant to give 100% accurate results. They're meant to provide results that are "good enough". That usually means good enough to provide a sense of physics in say a video game context. This is because they can then use short cuts in order to calculate results faster.

    From the Box2D FAQ:

    Box2D uses approximate methods for a few reasons.

    • Performance
    • Some differential equations don't have known solutions
    • Some constraints cannot be determined uniquely

    Things like these approximations and the trade-offs, in terms of realism, that different engines make, can and do vary between engines. If the engine uses an iterative solver, then any differences can magnify variances. Engines will also make different choices for things like collision margin making apples-to-apples comparisons of engines harder.

    Even how physics engines go about calculating velocity due to forces like gravity can be different between them because of these approximations. For insight into the differences you can expect between say Box2D and Newtonian physics of a trajectory, take a look at what iforce2d has explained in his Projected trajectories tutorial.

    There are things that can be done that can increase the accuracy of these kinds of engines. These are at the expense of performance however. Things like using smaller time steps, higher iteration counts, or higher precision numeric types (like switching from using float to using double).

    A resource I've found that compares ODE 0.11, PhysX and Newton 3.11 which may give you more insight is: A comparison between 3 physics engines. This doesn't discuss the why of the differences as I've explained them however. There's also a discussion on increasing realism in Bulletphysics at: How can I increase the physical realism of my simulation?

    Hope this helps!