I have the following situation: a cube (btBoxShape) is sitting on a plane (btStaticPlaneShape). Gravity is disabled. A force is applied to the cube in the contact plane. In my understanding, this force should not cause the cube to move as long as the tangential component is smaller than mu times the normal component of the force. I have mu=1.
What I observe is that the cube picks up, essentially instantly, a small velocity tangential to the plane. The velocity is proportional to the tangential component of the force, independent of the normal component, independent of the cubes mass and roughly inversely proportional to the cubes moment of inertia. It is also proportional to the simulation time step, adding to my suspicion that it is some unphysical simulation artifact. The code I use to debug this is included below.
Does anyone know why this is happening and how I could get rid of it? I am trying to simulate a physical system, so changing the cubes mass or moment of inertia is not really an option. Making the time step smaller does work, but requires (for the actual simulation) a time step of around 0.1ms (1e-4 s) to work, so things become really slow.
Thanks for any answers,
Norbert
Code: Select all
#include <iostream>
#include <btBulletDynamicsCommon.h>
int main()
{
btBroadphaseInterface* broadphase = new btDbvtBroadphase();
btDefaultCollisionConfiguration* collisionConf = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConf);
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConf);
world->setGravity(btVector3(0., 0., 0.));
btStaticPlaneShape* floorS = new btStaticPlaneShape(btVector3(0., 0., 1.), 0.);
btRigidBody::btRigidBodyConstructionInfo floorInfo(0., new btDefaultMotionState(btTransform(btQuaternion(0., 0., 0., 1.), btVector3(0., 0., -.5))), floorS, btVector3(0., 0., 0.));
btRigidBody* floorB = new btRigidBody(floorInfo);
floorB->setFriction(1.);
world->addRigidBody(floorB);
btBoxShape* bodyS = new btBoxShape(btVector3(.5, .5, .5));
btRigidBody::btRigidBodyConstructionInfo info(1., new btDefaultMotionState(btTransform(btQuaternion(0., 0., 0., 1.), btVector3(0., 0., 0.))), bodyS, btVector3(1., 1., 1.));
info.m_linearDamping = btScalar(0.);
info.m_angularDamping = btScalar(0.);
info.m_linearSleepingThreshold = btScalar(0.);
info.m_angularSleepingThreshold = btScalar(0.);
info.m_additionalDamping = false;
btRigidBody* body = new btRigidBody(info);
body->setFriction(1.);
world->addRigidBody(body);
const double dt = 1e-3;
for(unsigned int t_step = 0; t_step < 10000; t_step++) {
const double t = t_step * dt;
btVector3 pos = body->getCenterOfMassPosition();
btVector3 vel = body->getLinearVelocity();
std::cout << t << " ";
std::cout << pos.x() << " " << pos.y() << " " << pos.z() << " ";
std::cout << vel.x() << " " << vel.y() << " " << vel.z() << " ";
std::cout << std::endl;
body->applyForce(btVector3(500., 0., -1000.), btVector3(0., 0., -.5));
world->stepSimulation(dt, 1, dt);
}
world->removeRigidBody(body);
delete body->getMotionState();
delete body;
delete bodyS;
delete world;
delete solver;
delete dispatcher;
delete collisionConf;
delete broadphase;
return 0;
}