[ODE] value passed to dAddTorque isn't actually torque?

Martin C. Martin martin at metahuman.org
Mon Jun 23 09:41:01 2003


Hi,

The picture at:

http://www.ai.mit.edu/~mcm/BlockAndHinge.jpg

shows a block in mid air, free to fall except for a
hinge on one end (the red line).  If you do the math, you can show that
gravity produces a torque about the hinge's axis of:

g M l/2

where l is the length of the box.  Therefore, if I apply an equal torque
in the opposite direction, it should perfectly balance and the thing
shouldn't move.  However, that's not what happens.  Instead, to balance
it, I need the following torque:

g 1/2

That is, same as you'd expect, but without the mass.  That formula works
for changes in:

- acceleration from gravity
- box density
- box length
- box width
- box height

Is this a bug in ODE?  It says that the torque needed to support a rod at
one end is the same whether its made from lead or Styrofoam.  That seems
wrong.  The source I used is below.  What can be done to fix/work around
this?

Thanks,
Martin

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

// select correct drawing functions

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

#define box_length (1.0f)
#define box_width (0.5f)
#define box_height (0.5f)
#define DENSITY (5.0f)
#define box_z (1.5f)

#define grav (9.8f)

static dWorldID world;
static dSpaceID space;
static dJointGroupID contactgroup;

static dGeomID box_geom;
static dBodyID box_body;
static dJointID box_hinge;

// This torque will be applied every timestep.
dReal torque;

static void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
}

static void start()
{
  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
  dsSetViewpoint (xyz,hpr);
}


static void simLoop (int pause)
{
  const dReal *pos;
  const dReal *R;
  dVector3 sides, hinge_pos, hinge_axis;
  dMatrix3 hinge_R;

  dsSetColor (0,0,2);
  dSpaceCollide (space,0,&nearCallback);
  if (!pause) {
	  dBodyAddTorque(box_body, 0, - torque, 0);
	  dWorldStep (world,0.01);
  }

  // remove all contact joints
  dJointGroupEmpty (contactgroup);

  // Draw the box
  dsSetColor (0,0,0.5);
  dsSetTexture (DS_NONE);

  pos = dGeomGetPosition(box_geom);
  R = dGeomGetRotation(box_geom);
  dGeomBoxGetLengths(box_geom, sides);
  dsDrawBox(pos, R, sides);

  // Draw the hinge
  dsSetColor(1, 0, 0);
  dJointGetHingeAnchor(box_hinge, hinge_pos);
  dJointGetHingeAxis(box_hinge, hinge_axis);
  dRFromZAxis(hinge_R, hinge_axis[0], hinge_axis[1], hinge_axis[2]);
  dsDrawCylinder(hinge_pos, hinge_R, 1.0, 0.02);
}


int main (int argc, char **argv)
{
  dMass mass;
  dReal moment;

  // setup pointers to drawstuff callback functions
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start = &start;
  fn.step = &simLoop;
  fn.command = NULL;
  fn.stop = 0;
  fn.path_to_textures = "textures";

  // create world

  world = dWorldCreate();
  space = dHashSpaceCreate (0);
  contactgroup = dJointGroupCreate (0);
  dWorldSetGravity (world,0,0,-grav);
  dWorldSetCFM (world,1e-5);

  box_geom = dCreateBox(space, box_length, box_width, box_height);

  box_body = dBodyCreate(world);
  dGeomSetBody(box_geom, box_body);
  dBodySetPosition(box_body, box_length/2, 0, box_z);
  dMassSetBox(&mass, DENSITY, box_length, box_width, box_height);

  box_hinge = dJointCreateHinge(world, 0);
  dJointAttach(box_hinge, box_body, NULL);
  dJointSetHingeAnchor(box_hinge, 0, 0, box_z);
  dJointSetHingeAxis(box_hinge, 0, 1, 0);

  moment = mass.I[1*4+1] + mass.mass*box_length * box_length / 4;
  printf("Moment about COM: %f\n", moment);
 
//  torque = grav * mass.mass * box_length / 2;
  torque = grav * box_length / 2;

  // run simulation
  dsSimulationLoop (argc,argv,352,288,&fn);

  dJointGroupDestroy (contactgroup);
  dSpaceDestroy (space);
  dWorldDestroy (world);

  return 0;
}