[ODE] Problem with rotating spheres

Bjoern Mahn bjoern.mahn at ais.fraunhofer.de
Tue Mar 25 05:56:02 2003


Hi all,

okay, it seems that I'm not that good in describing my problem :-). So here 
is a small demo program which shows you what I mean.

Thanks for your help!

Bjoern Mahn.

/*
 * This is a small demonstration program which should show a strange 
 * behavior of ODE with rotating spheres.
 *
 * There are two Spheres which are connected with a "fixed" hinge joint, which
 * means that the joint stop parameters are both 0. The first sphere lies on 
 * the ground, which is in the same space as the Sphere1 (space1). The 
 * second sphere is put into a seperate space (space2) so that it doesn't 
 * collide neither with the ground nor with the sphere1.
 *
 * Now if you start the simulation, you will see that the sphere2's pendular
 * behavior is not physically correct. It gains more and more energy and
 * oscillates higher and higher. After the system has "exploded", ODE gives 
 * the following Message:
 * 
 * "ODE Message 2: vector has zero size in dNormalize4()"
 *
 * ... so why?
 */

#include <ode/ode.h>
#include <drawstuff/drawstuff.h>

#ifdef dDOUBLE
#define dsDrawBox dsDrawBoxD
#define dsDrawSphere dsDrawSphereD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCappedCylinder dsDrawCappedCylinderD
#endif

#define  RADIUS_SPHERE1 1.0
#define  MASS_SPHERE1   1.0
#define  RADIUS_SPHERE2 0.2
#define  MASS_SPHERE2   0.5

dWorldID       world;
dSpaceID       space1, space2;
dJointGroupID  contactgroup;
dGeomID        ground;

dBodyID        bSphere1, bSphere2;
dGeomID        gSphere1, gSphere2;
dMass          mSphere1, mSphere2;
dJointID       jFix;

void init()
{
  world  = dWorldCreate(0);
  space1 = dSimpleSpaceCreate(0);
  space2 = dSimpleSpaceCreate(0);
  contactgroup = dJointGroupCreate (0);
  dWorldSetGravity (world, 0, 0, -9.81);
  ground = dCreatePlane (space1, 0, 0, 1, 0);
}

void deinit()
{
  dJointGroupDestroy (contactgroup);
  dBodyDestroy  (bSphere1);
  dBodyDestroy  (bSphere2);
  dGeomDestroy  (gSphere1);
  dGeomDestroy  (gSphere2);
  dJointDestroy (jFix);
  dSpaceDestroy (space1);
  dSpaceDestroy (space2);
  dWorldDestroy (world);
}

void createSpheres(int x, int y, int z)
{
  bSphere1 = dBodyCreate(world);
  bSphere2 = dBodyCreate(world);

  // sphere1 body + geom
  dMassSetSphere (&mSphere1, 1, RADIUS_SPHERE1);
  dMassAdjust    (&mSphere1, MASS_SPHERE1);
  dBodySetMass   (bSphere1, &mSphere1);
  gSphere1 = dCreateSphere (space1, RADIUS_SPHERE1);
  dGeomSetBody       (gSphere1, bSphere1);
  dBodySetPosition   (bSphere1, x, y, z + RADIUS_SPHERE1);

  // sphere2 body + geom
  dMassSetSphere (&mSphere2, 1, RADIUS_SPHERE2);
  dMassAdjust    (&mSphere2, MASS_SPHERE2);
  dBodySetMass   (bSphere2, &mSphere2);
  gSphere2 = dCreateSphere (space2, RADIUS_SPHERE2);
  dGeomSetBody       (gSphere2, bSphere2);
  dBodySetPosition   (bSphere2, 
                      x + RADIUS_SPHERE1 + 0.1 + RADIUS_SPHERE2, 
                      y, 
                      z + RADIUS_SPHERE1);
  
  // fix them with a hinge
  jFix = dJointCreateSlider(world, 0);
  dJointAttach (jFix, bSphere1, bSphere2);
  dJointSetSliderAxis  (jFix, 1, 0, 0);
  dJointSetSliderParam (jFix, dParamVel, 0);
  dJointSetSliderParam (jFix, dParamFMax, 100);
  dJointSetSliderParam (jFix, dParamVel, 0);
  dJointSetSliderParam (jFix, dParamLoStop, 0);
  dJointSetSliderParam (jFix, dParamHiStop, 0); 
  
}

void step(dReal delta)
{
  dWorldStep (world,delta);
  dJointGroupEmpty (contactgroup);
}

void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
  int i,n;

  const int N = 10;
  dContact contact[N];
  n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
  if (n > 0) {
    for (i=0; i<n ; i++) {

      contact[i].surface.mu = dInfinity;
      
      dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
      dJointAttach (c,
          dGeomGetBody(contact[i].geom.g1),
          dGeomGetBody(contact[i].geom.g2));
    }
  }
}

void draw()
{
  dsDrawSphere(dGeomGetPosition(gSphere1),
      dGeomGetRotation(gSphere1),
      RADIUS_SPHERE1);
  dsDrawSphere(dGeomGetPosition(gSphere2),
      dGeomGetRotation(gSphere2),
      RADIUS_SPHERE2);
}

static void start()
{
  static float xyz[3] = {0.4369,4.0176,0.170};
  static float hpr[3] = {-90.0000,6.5000,0.000};
  dsSetViewpoint (xyz,hpr);
}

static void command (int cmd)
{
  switch (cmd)
  {
    case 'q': case 'Q': exit(0);
  }
}
static void simLoop (int pause)
{
  if (!pause)
  {
    step(0.01);
    dSpaceCollide (space1, 0, &nearCallback);
  }
  draw();
}

int main(int argc, char **argv)
{
  char *path = new char[1024];
  sprintf(path,"%s/simulators/ode/drawstuff/textures",getenv("HOME"));
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start = &start;
  fn.step = &simLoop;
  fn.command = &command;
  fn.stop = 0;
  fn.path_to_textures = path;
  
  init();
  
  createSpheres(0, 0, 0);
  dsSimulationLoop (argc, argv, 300, 300, &fn);

  deinit();
  dCloseODE();  
  return 0;
}