Bullet 2.78 Restitution Bug

youcancallmeAl
Posts: 5
Joined: Thu Jul 21, 2011 5:18 pm

Bullet 2.78 Restitution Bug

Post by youcancallmeAl »

Hello,

I am a new bullet user, just getting my head around Hello World. I am using ver 2.78, and I have found a rather troubling bug (or at least what seems to be a bug) in the restitution behavior. In the hello world demo, I have been playing with the simulation timestep, and have found that the collision restitution decreases to 0 as the timestep decreases in size. I've attached a plot comparing two cases of timestep. Also, using Blender and a separate copy (I don't know the version number) of Bullet, I was able to replicate the results, which seems to suggest that it is indeed a bug. Has anyone else seen this? Is it a known problem? Thanks!

Al
You do not have the required permissions to view the files attached to this post.
bullphy
Posts: 4
Joined: Sat Jul 09, 2011 7:42 am

Re: Bullet 2.78 Restitution Bug

Post by bullphy »

Hi youcancallmeAl,

I've found same restitution problem with SDK 2.78, and after serveral day's study i've found the reason : somehow SDK 2.78 changed its restitution calculation method, the detailed change you can find in btSequentialImpulseConstraintSolver.cpp, around Line 559. you can compare it with 2.77 version's btSequentialImpulseConstraintSolver.cpp to see how it is changed. with new method in SDK 2.78, small gravity changes will result in different bounce effect (which is bad), for example G=-10 and G=-9.8.

Personally i am not sure if its a bug or not, but the new method does give bad bounce effect, so i'm already changed back to stick with 2.77 which is more reasonable on this issue.

bullphy
Best
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Bullet 2.78 Restitution Bug

Post by Erwin Coumans »

Hi,

It could be a bug.
Can you create a simple reproduction case out of one of the Bullet demos that shows the difference (when using Bullet 2.78 versus 2.77)?

Thanks a lot,
Erwin
bullphy
Posts: 4
Joined: Sat Jul 09, 2011 7:42 am

Re: Bullet 2.78 Restitution Bug

Post by bullphy »

Hi Erwin,

Thanks for your reply, here is the test code to drop three balls from different height, just copy and paste to replace the 'basicDemo::initPhysics()' section in both SDK 2.77 and 2.78 to see the difference.

By the way, can you explain a little more about why add penetrateImpulse is necessary when solving restitution? With this penetrate impulse it becomes a little difficult to predict ball future position after bounce which sometimes is necessary for AI player to decide next move, my guess is this penentrateImpulse helps penetration recovery and improve stability?

And here is a humble suggestion, if it is convenient, can you add a restitution demo (for example drop 3 balls (same physic material properties) from different height) as official demo, this way restitution problems (if any) will be easier to be detected before future official release?

Thanks for your time and thanks a lot for your brilliant job.

Best Regards,
Bullphy

Code: Select all

void   BasicDemo::initPhysics()
{
   setTexturing(true);
   setShadows(true);

   //setCameraDistance(btScalar(SCALING*50.));
   setCameraDistance(btScalar(0.3f * 50.));

   ///collision configuration contains default setup for memory, collision setup
   m_collisionConfiguration = new btDefaultCollisionConfiguration();
   //m_collisionConfiguration->setConvexConvexMultipointIterations();

   ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
   m_dispatcher = new   btCollisionDispatcher(m_collisionConfiguration);

   m_broadphase = new btDbvtBroadphase();

   ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
   btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
   m_solver = sol;

   m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
   
   m_dynamicsWorld->setGravity(btVector3(0, -10, 0));

   ///create a few basic rigid bodies
   btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));   
   m_collisionShapes.push_back(groundShape);

   btTransform groundTransform;
   groundTransform.setIdentity();
   groundTransform.setOrigin(btVector3(0,-50,0));

   //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
   {
      btScalar mass(0.);

      //rigidbody is dynamic if and only if mass is non zero, otherwise static
      bool isDynamic = (mass != 0.f);

      btVector3 localInertia(0,0,0);
      if (isDynamic)
         groundShape->calculateLocalInertia(mass,localInertia);

      //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
      btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
      btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);

      rbInfo.m_linearDamping = 0.0f;
      rbInfo.m_angularDamping = 0.0f;
      rbInfo.m_friction = 0.0f;
      rbInfo.m_restitution = 1.0f;

      btRigidBody* body = new btRigidBody(rbInfo);
      body->updateInertiaTensor();

      //add the body to the dynamics world
      m_dynamicsWorld->addRigidBody(body);
   }

   {
      btCollisionShape *sp = new btSphereShape(1.0f);
      sp->setLocalScaling(btVector3(0.3f, 0.3f, 0.3f));
      m_collisionShapes.push_back(sp);

      const float mass = 1;

      for (int i = 0; i < 3; ++i)
      {
         btVector3 localInertia(0, 0, 0);
         sp->calculateLocalInertia(mass, localInertia);

         btDefaultMotionState *mp = new btDefaultMotionState;

         btTransform tm;
         tm.setIdentity();
         tm.setOrigin(btVector3(-3 + i * 3.0f, 3 + i * 4.0f, 0));
         mp->setWorldTransform(tm);

         btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, mp, sp, localInertia);
         rbInfo.m_linearDamping = 0.0f;
         rbInfo.m_angularDamping = 0.0f;
         rbInfo.m_friction = 0.0f;
         rbInfo.m_restitution = 0.9f;

         btRigidBody* body = new btRigidBody(rbInfo);

         m_dynamicsWorld->addRigidBody(body);
      }
   }
}
youcancallmeAl
Posts: 5
Joined: Thu Jul 21, 2011 5:18 pm

Re: Bullet 2.78 Restitution Bug

Post by youcancallmeAl »

Hello all,

Unfortunately, I have not found 2.77 to fix my problem regarding small timesteps. Bullphy, it does seem that different gravity acceleration constants do influence the restitution between versions, but have you tried using different timesteps as well? The issues might be related, but I'm concerned that the latter might be specific to my machine, so if you could test it out as well, that would be wonderful.

Below is a copy of the HelloWorld demo/introductory app; I think the only line that must be changed to show the error will be the "for" statement for the step simulation loop as suggested in the comment I have inserted on that line.

Another note: in my build, I've enabled BT_USE_DOUBLE_PRECISION in btScalar.h, and I'm using a Mac with Snow Leopard and the x86_64 architecture, if it's of any consequence.

Code: Select all

#include <iostream>
 
#include <btBulletDynamicsCommon.h>
 
int main (void)
{
 
        btBroadphaseInterface* broadphase = new btDbvtBroadphase();
 
        btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
        btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
 
        btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
 
        btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
 
        dynamicsWorld->setGravity(btVector3(0,-10,0));
 
 
        btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),btScalar(1));
 
        btCollisionShape* fallShape = new btSphereShape(1);
 
 
        btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0)));
        btRigidBody::btRigidBodyConstructionInfo
                groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));
        btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);
groundRigidBody->setRestitution(0.9);     //added line to original
        dynamicsWorld->addRigidBody(groundRigidBody);
 
 
        btDefaultMotionState* fallMotionState =
                new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,50,0)));
        btScalar mass = 1;
        btVector3 fallInertia(0,0,0);
        fallShape->calculateLocalInertia(mass,fallInertia);
        btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);
        btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);
fallRigidBody->setRestitution(0.9);     //added line to original

        dynamicsWorld->addRigidBody(fallRigidBody);
 
 
        for (int i=0 ; i<3000 ; i++) {
                dynamicsWorld->stepSimulation(1/60.f,1,1/60.f); //change from 60Hz to 600Hz to see problem
 
                btTransform trans;
                fallRigidBody->getMotionState()->getWorldTransform(trans);
 
                std::cout << "sphere height: " << trans.getOrigin().getY() << std::endl;
        }
 
        dynamicsWorld->removeRigidBody(fallRigidBody);
        delete fallRigidBody->getMotionState();
        delete fallRigidBody;
 
        dynamicsWorld->removeRigidBody(groundRigidBody);
        delete groundRigidBody->getMotionState();
        delete groundRigidBody;
 
 
        delete fallShape;
 
        delete groundShape;
 
 
        delete dynamicsWorld;
        delete solver;
        delete collisionConfiguration;
        delete dispatcher;
        delete broadphase;
 
        return 0;
}
Thank you very much, Erwin, for your attention on this; the more I dive into Bullet the more impressed I am by it, and it's rather exciting to get to talk with the author. Hopefully whatever issue there is with this restitution thing can be ironed out soon, let me know if there is any more information I can provide.

-Al