I dont understand what happens with stepSimulation

jagh
Posts: 4
Joined: Wed Feb 12, 2014 4:39 pm

I dont understand what happens with stepSimulation

Post by jagh »

Assume there is a physics world(btDiscreteDynamicsWorld) which contains a bunch of CollisionObjects and a vehicle(btRigidBody with a btActionInterface object controlling it).
And i don't understand why this system behaves extremely unpredictable. What do i mean by that: Every so often, say every 20ms, stepSimulation() is called:

Code: Select all

    m_physicsWorld->stepSimulation(msDelta / 1000.f, 30, 1. / 180.);
where msDelta is time passed since last call to this function(so roughly msDelta=20).
In this case, i can more or less smoothly control the vehicle, and he gains nice speed easy and reliably.
Now if i call stepSimulation() (exactly as above) more often, say every 2 ms, i can't control vehicle at all - it just stays still, and even if it moves, than it is so slow that i can't even see. Bear in mind, the only thing that changed is how often stepSimulation() is called.
What the hell is happening here?

Some more code,
excerpt from a btActionInterface class

Code: Select all

void ShipPhysicsActor::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep)
{
    if (m_forceVec.fuzzyZero() && m_torqueVec.fuzzyZero())
        return;
    // if m_forceVector is not zero, than its length is roughly 60.0 units
    static int a = 0;
    btTransform trans;
    m_slaveBody->getMotionState()->getWorldTransform(trans);
    btQuaternion worldRot, worldRotInv, force(m_forceVec.x(), m_forceVec.y(), m_forceVec.z(), 0);
    worldRot = trans.getRotation();
    worldRotInv = worldRot.inverse();
    force = worldRot * force * worldRotInv;
    btVector3 myForce(force.x(), force.y(), force.z());
    assert(std::abs(myForce.length2() - m_forceVec.length2()) < 0.01f);

    // rotate torque vector as well
    btQuaternion torque(m_torqueVec.x(), m_torqueVec.y(), m_torqueVec.z(), 0);
    torque = worldRot * torque * worldRotInv;
    btVector3 myTorque(torque.x(), torque.y(), torque.z());
    assert(std::abs(myTorque.length2() - m_torqueVec.length2()) < 0.01f);

    if ((++a) % 50 == 0)
    {
        std::cerr << "Body at " << trans.getOrigin().x() << ", " << trans.getOrigin().y() << ", " << trans.getOrigin().z() << "\n";
        std::cerr << "Apply force " << myForce.x() << ", " << myForce.y() << ", " << myForce.z() <<  "\n";
    }

    if (!m_forceVec.fuzzyZero())
    {
        m_slaveBody->applyCentralForce(myForce);
    }
    if (!m_torqueVec.fuzzyZero())
    {
        m_slaveBody->applyTorque(myTorque);
    }
    m_slaveBody->activate(true);
}
Physics engine init

Code: Select all

PhysicsEngine::PhysicsEngine() :
m_collisionConfig(new btDefaultCollisionConfiguration),
m_collisionDispatcher(new btCollisionDispatcher(m_collisionConfig)),
m_broadphase(new btDbvtBroadphase),
m_constraintSolver(new btSequentialImpulseConstraintSolver)
{
    m_physicsWorld = new btDiscreteDynamicsWorld(m_collisionDispatcher, m_broadphase, m_constraintSolver, m_collisionConfig);
    m_physicsWorld->setGravity(btVector3(0, 0, 0));
    [...]
}
Vehicle creation

Code: Select all

    if (! m_vehicleShape)
    // size is (0.1, 0.1, 0.3), mass is 10.0
        m_vehicleShape = new btBoxShape(btVector3(sizes.x() / 2, sizes.y() / 2, sizes.z() / 2));

    btTransform startTransform;
    startTransform.setIdentity();
    startTransform.setRotation(btQuaternion(orient.x(), orient.y(), orient.z(), orient.w()));
    startTransform.setOrigin(btVector3(pos.x(), pos.y(), pos.z()));

    VehicleMotionState* motionState = new VehicleMotionState(this, m_nextUsedId, startTransform);
    btVector3 inertia;
    m_vehicleShape->calculateLocalInertia(mass, inertia);

    btRigidBody* body = new btRigidBody(mass, motionState, m_vehicleShape, inertia);
    m_vehicles[m_nextUsedId] = body;
    ++m_nextUsedId;

    body->setDamping(0.5f, 0.7f);
    m_physicsWorld->addRigidBody(body, COLLISION_SHIPGROUP, COLLISION_SHIPGROUP | COLLISION_ASTEROIDGROUP);
jagh
Posts: 4
Joined: Wed Feb 12, 2014 4:39 pm

Re: I dont understand what happens with stepSimulation

Post by jagh »

And to avoid an obvious question: Physics engine(which is working in a separate thread) is keeping up with realtime in both cases. In fact, the thread only uses about 5% of the CPU core it runs on, at most.
Basroil
Posts: 463
Joined: Fri Nov 30, 2012 4:50 am

Re: I dont understand what happens with stepSimulation

Post by Basroil »

jagh wrote: Now if i call stepSimulation() (exactly as above) more often, say every 2 ms, i can't control vehicle at all - it just stays still, and even if it moves, than it is so slow that i can't even see. Bear in mind, the only thing that changed is how often stepSimulation() is called.
You didn't just change your call count, you changed how many of your calls actually matter. For 1/180, you need at least 5.5ms between the calls to actually get bullet to update, since the step size is just 5.5ms. It must be an issue in your m_forceVec variable calculation in code not shown, because the code as-is will do nothing when both forceVec and torqueVec go to zero. Perhaps you are using some sort of difference between internal states somewhere?
jagh
Posts: 4
Joined: Wed Feb 12, 2014 4:39 pm

Re: I dont understand what happens with stepSimulation

Post by jagh »

Basroil wrote: You didn't just change your call count, you changed how many of your calls actually matter. For 1/180, you need at least 5.5ms between the calls to actually get bullet to update, since the step size is just 5.5ms.
Isn't stepSimulation supposed to accumulate time differences until it reaches fixedTimeStep value? In both cases, i expect bullet to perform ~180 internal substeps pro second, it shouldn't matter, if the time interval between individual calls is 2 or 20 ms.
Basroil wrote: It must be an issue in your m_forceVec variable calculation in code not shown, because the code as-is will do nothing when both forceVec and torqueVec go to zero.
Nothing? I thought there is something called inertia, or Newton's first law, if there is no force applied to an object, it shall continue to move with constant velocity or stand still.
m_forceVec calculation is fine(its length is either 0 or 60 units, depending on whether the user choses to accelerate or not, the user input works reliably in this case). The problem is with Bullet behaving unreliably, and not with the forces applied in actioninterface.
Basroil wrote: Perhaps you are using some sort of difference between internal states somewhere?
What do you mean by that?
Basroil
Posts: 463
Joined: Fri Nov 30, 2012 4:50 am

Re: I dont understand what happens with stepSimulation

Post by Basroil »

jagh wrote: In both cases, i expect bullet to perform ~180 internal substeps pro second, it shouldn't matter, if the time interval between individual calls is 2 or 20 ms.
Problem comes down to how you are using those interpolated states. If you are feeding back the states into how you calculate your forces, then you'll have odd behavior depending on that controller.
jagh wrote: Nothing? I thought there is something called inertia, or Newton's first law, if there is no force applied to an object, it shall continue to move with constant velocity or stand still.
And it's doing just that :wink: If your code short circuits (triggers the return), then the vehicle just stays there because nothing pushes it!
jagh wrote: m_forceVec calculation is fine(its length is either 0 or 60 units, depending on whether the user choses to accelerate or not, the user input works reliably in this case). The problem is with Bullet behaving unreliably, and not with the forces applied in actioninterface.
Just keep in mid this case:
Your code checks for input every frame it can, then clears the input. You user holds down the button to accelerate, but the keyboard only sends one update command per ogl frame. The code recognizes the input on the first frame, then resets it until a new value is provided.

In that case, you would end up with about 1/8th the inputs actually doing something, the 7/8 remaining would be zero. Are you certain that m_forceVec is non-zero at all times the key is pressed? (i.e. checked through debug)