[ODE] Mismatching results / non-deterministic behaviour

Jan Tinkhof boost at tinkhof.de
Wed Sep 13 12:26:24 MST 2006


Hi,

I'm currently trying to implement a scheme to save and restore ODEs
world state. The results are very promising so far, but I have come
across a problem that is unconnected to any serialization I'm attempting.

I have noticed that I get different results each time I setup and run a
simple simulation using ODEs public interface. This test uses ODE 0.7
ONLY, no other library or 3D graphics are involved.

This is the code I use:




#include "ode/ode.h"
#include <iostream>

void runtest()
{
    dWorldID myworld = dWorldCreate();

    dBodyID mybody1 = dBodyCreate(myworld);
    dBodyID mybody2 = dBodyCreate(myworld);

    dBodySetPosition(mybody1, 0.f, 1.f, 2.f);
    dBodySetPosition(mybody2, 1.f, 2.f, 3.f);

    dGeomID mygeom1 = dCreateBox(NULL, 1.0f, 1.0f, 1.0f); // NO
collision points are calculated
    dGeomID mygeom2 = dCreateSphere(NULL, 1.0f);  // NO collision points
are calculated

    dGeomSetPosition(mygeom1, 0.f, 1.f, 2.f);
    dGeomSetPosition(mygeom2, 1.f, 2.f, 3.f);

    dGeomSetBody(mygeom1, mybody1);
    dGeomSetBody(mygeom2, mybody2);

    dJointID myjoint = dJointCreateHinge(myworld,0);
    dJointAttach(myjoint, mybody1, mybody2);
    dJointSetHingeAnchor(myjoint, 1.f, 1.f, 1.f);
    dJointSetHingeAxis(myjoint, 1.f, 0.f, 0.f);

    dBodyAddForce(mybody1, 0.1f, 0.1f, 0.1f);

    for (int s = 0; s < 10000; ++s)
    {
        dWorldQuickStep(myworld, 0.01f);
        dBodyAddForce(mybody1, 0.1f, 0.1f, 0.1f);
    }

    const float* pos1 = dBodyGetPosition(mybody1);
    const float* pos2 = dBodyGetPosition(mybody2);

    std::cout.precision(12);
    std::cout << "runtest:" << std::endl;
    std::cout << "Body1 x: " << pos1[0] << " y: " << pos1[1] << " z: "
<< pos1[2] << std::endl;
    std::cout << "Body2 x: " << pos2[0] << " y: " << pos2[1] << " z: "
<< pos2[2] << std::endl;
    std::cout << std::endl;

    dWorldDestroy(myworld);
}

int main( int argc, char* argv[], char* envp[] )
{
    runtest();
    runtest();
    runtest();
    runtest();
    runtest();
}


... and these are the results I get:


runtest:
Body1 x: 250.228286743 y: 252.350143433 z: 252.396209717
Body2 x: 250.816452026 y: 250.691482544 z: 252.647384644

runtest:
Body1 x: 250.22694397 y: 252.35005188 z: 252.395523071
Body2 x: 250.817779541 y: 250.691711426 z: 252.647949219

runtest:
Body1 x: 250.226898193 y: 252.350341797 z: 252.395523071
Body2 x: 250.817581177 y: 250.691757202 z: 252.647979736

runtest:
Body1 x: 250.229873657 y: 252.350143433 z: 252.39680481
Body2 x: 250.815002441 y: 250.691375732 z: 252.646453857

runtest:
Body1 x: 250.22706604 y: 252.34967041 z: 252.395294189
Body2 x: 250.817337036 y: 250.692123413 z: 252.648086548




I get the same set of results when I restart the program, but I would
also expect the same result for every iteration of the test.

Obviously, there is some hidden variable/influence that doesn't get
reset between iterations, only termination and a restart of the app
seems to clear it. I figured it might have to do something with the
floating point processor, so tried to reset it with an __asm {finit}
between calls to runtest, but that made no difference.

I am using VC 8.0, single precision, and have tried both the precise and
strict floating point model.

I'm currently at my wits end, there has to be something I'm overlooking,
but I just can't see it.

I'd appreciate any help offered.



Jan






More information about the ODE mailing list