[ODE] Re: center of mass

Guillaume Jouffroy oxymore at tele2.fr
Thu Oct 27 19:00:59 MST 2005


Hey my dear it seems you've sent your answer to ode but not to me, I 
didn't get it. Fortunately Geoff message made me discover your message :)
And my previous message is not already on the mailing list because of 
the file, which has to be moderated :/
But for those who want to read it, you have included it in your message ! ;)

I found difficult to put my code as it is a lot of different functions. 
I will try it now.

> having a 'standard' version would make life simpler for many people. 
Indeed. Sure lots of ppl are just stuck like me for a while, asking themself
"why my object does not move" ?
Getting body reference isnt that useful except in particular cases.

> I've also added a new flag to the geoms to show if it's inside a 
>geomtransform.

In your ode core ? Where ? How ?
I am particularly interested to provide a patch for that. Any code is 
welcome.
Geoff, can you give me sthg on cvs ?

>I used to use one of the geoms as a reference (the axis for example); it's 
>pretty straightforward to calculate the necessary pos and R for a new geom 
>or for the body, as we know that the pos and R of this reference geom is 
>relative to the body.

Sure but I meant concerning another object, with another rigidbody. Or with
respect to the floor.

Now the ugly part :oD

build of the object
***********************
void createWheel(MyObject *obj)
{	
	int k;
	dQuaternion q;dMatrix3 Rtx;
	dMass m;
	
	
	obj->body = dBodyCreate (world);
	dBodySetPosition (obj->body,0,0,0.1);
	dGeomID g2[GPB];		// encapsulated geometries
	
	// start accumulating masses for the encapsulated geometries
	dMass m2;
	dMassSetZero (&m);

	/*-- axe --*/
	k=0;
	obj->geom[k] = dCreateGeomTransform (space);
	dGeomTransformSetCleanup(obj->geom[k],1);
	g2[k] = dCreateCCylinder(0,WHEEL_AXE_RADIUS,WHEEL_AXE_LENGTH);
	dMassSetCappedCylinder(&m2,DENSITY,3,WHEEL_AXE_RADIUS,WHEEL_AXE_LENGTH);
	dGeomTransformSetGeom(obj->geom[k],g2[k]);
	// set the transformation (adjust the mass too)
	dGeomSetPosition(g2[k],0,0,WHEEL_RADIUS);
	dMassTranslate(&m2,0,0,WHEEL_RADIUS);
	dQFromAxisAndAngle(q,1,0,0,M_PI*0.5);
	dGeomSetQuaternion(g2[k], q);
	dQtoR(q, Rtx);
	dMassRotate(&m2,Rtx);
	// add to the total mass
	dMassAdd(&m,&m2);

	/*-- wheel --*/
	k=1;
	obj->geom[k] = dCreateGeomTransform (space);
	dGeomTransformSetCleanup(obj->geom[k],1);	
	g2[k] = dCreateSphere(0,WHEEL_RADIUS);
	dMassSetSphere(&m,1,WHEEL_RADIUS);
	dMassAdjust(&m,0.1);
	dGeomTransformSetGeom(obj->geom[k],g2[k]);
	// set the transformation (adjust the mass too)
	dGeomSetPosition(g2[k],0,-WHEEL_SPACING/2,WHEEL_RADIUS);
	dMassTranslate(&m2,0,-WHEEL_SPACING/2,WHEEL_RADIUS);
	dQFromAxisAndAngle(q,1,0,0,M_PI*0.5);
	dGeomSetQuaternion(g2[k],q);
	dQtoR(q, Rtx);
	dMassRotate(&m2,Rtx);
	// add to the total mass
	dMassAdd(&m,&m2);

	/*-- wheel 2 --*/
	k=2;
	obj->geom[k] = dCreateGeomTransform(space);
	dGeomTransformSetCleanup(obj->geom[k],1);
	g2[k] = dCreateSphere(0,WHEEL_RADIUS);
	dMassSetSphere(&m,1,WHEEL_RADIUS);
	dMassAdjust(&m,0.1);
	dGeomTransformSetGeom(obj->geom[k],g2[k]);
	// set the transformation (adjust the mass too)
	dGeomSetPosition(g2[k],0,WHEEL_SPACING/2,WHEEL_RADIUS);
	dMassTranslate(&m2,0,WHEEL_SPACING/2,WHEEL_RADIUS);
	dQFromAxisAndAngle(q,1,0,0,M_PI*0.5);
	dGeomSetQuaternion(g2[k],q);
	dQtoR(q, Rtx);
	dMassRotate (&m2,Rtx);
	// add to the total mass
	dMassAdd (&m,&m2);

	// move all encapsulated objects so that the center of mass is (0,0,0)
	dGeomSetPosition (g2[0],-m.c[0],-m.c[1],WHEEL_RADIUS-m.c[2]);
	dGeomSetPosition (g2[1],-m.c[0],-WHEEL_SPACING/2-m.c[1],WHEEL_RADIUS-m.c[2]);
	dGeomSetPosition (g2[2],-m.c[0],WHEEL_SPACING/2-m.c[1],WHEEL_RADIUS-m.c[2]);
	dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
    
	for (k=0; k < GPB; k++) 
        if (obj->geom[k]) dGeomSetBody (obj->geom[k],obj->body);
	dBodySetMass (obj->body,&m);

}


geomtransf world coordinates**************************
//worldPos & worldR must be ALREADY allocated dReal pointers
void getGeomTransfInWorld(dGeomID g, dReal *worldPos, dReal *worldR)
{
    if (!g) return;
    const dReal *pos = dGeomGetPosition (g);//pos of GeomTransform
    const dReal *R = dGeomGetRotation (g);

    dGeomID g2 = dGeomTransformGetGeom (g);//pos of Encasulated Geom
    const dReal *pos2 = dGeomGetPosition (g2);
    const dReal *R2 = dGeomGetRotation (g2);

    dVector3 actual_pos;
    dMatrix3 actual_R;
    dMULTIPLY0_331 (actual_pos,R,pos2);//convert to world Coordinates
    actual_pos[0] += pos[0];
    actual_pos[1] += pos[1];
    actual_pos[2] += pos[2];
    dMULTIPLY0_333 (actual_R,R,R2);   
    memcpy(worldPos, actual_pos,sizeof(dVector3));
    memcpy(worldR,actual_R,sizeof(dMatrix3));
}

Here its very ugly but I had serious problems getting the right 
coordinates if I did
a prototype like this
void getGeomTransfInWorld(dGeomID g, dVector3 *worldPos, dMatrix *worldR)
which should be better. I don't really like the dReal stuff, it makes 
things confusing

***********************************
Effective creation of the object + vertical axe creation + joint
    createWheel(&obj[0]);
   
    obj[1].body = dBodyCreate(world);
    k=0;
    
dMassSetCappedCylinderTotal(&m,DENSITY-4,3,WHEEL_AXE_RADIUS,WHEEL_AXE_LENGTH);
    dBodySetMass(obj[1].body,&m);
    dQuaternion q;
    dQFromAxisAndAngle(q,0,0,1,M_PI*-0.5);
    dBodySetQuaternion(obj[1].body,q);
    obj[1].geom[k] = dCreateCCylinder(0,WHEEL_AXE_RADIUS,WHEEL_AXE_LENGTH);
    dGeomSetBody(obj[1].geom[k],obj[1].body);
    dBodySetPosition(obj[1].body, 0,0,WHEEL_AXE_LENGTH/2+0.1);
    dSpaceAdd(space,obj[1].geom[0]);
   
    /* articulation wheel+joint */
    dReal* pos = (dReal*)dAlloc(4*sizeof(dReal));// this is ugly and 
even funny I know but if in the core...
    dReal *R = (dReal*)dAlloc(4*3*sizeof(dReal));// and I haven't the 
time to think about sthg better now
    getGeomTransfInWorld(obj[0].geom[0], pos, R);
    joint[0] = dJointCreateHinge(world,0);
    dJointAttach(joint[0],obj[0].body,obj[1].body);
    dJointSetHingeAnchor(joint[0], pos[0],pos[1],pos[2]);
    dJointSetHingeAxis(joint[0], 0, 1, 0);
    joint[1] = dJointCreateFixed(world,0);
    dJointAttach(joint[1],obj[1].body,0);
    dJointSetFixed(joint[1]);
    dJointSetHingeParam(joint[0], dParamVel, 10.0);
    dJointSetHingeParam (joint[0],dParamFMax,4);
    dJointSetHingeParam (joint[0],dParamLoStop, -dInfinity);
    dJointSetHingeParam (joint[0],dParamHiStop, dInfinity);
    dFree(R,3*3*sizeof(dReal));
    dFree(pos,3*sizeof(dReal));
   
Here the funny thing is I don't need to add geoms to space for the 
complex object to collide
but for a simple geom+rigidbody, I have. Next:

last thing: drawing***************************************
    dReal* pos = (dReal*)dAlloc(4*sizeof(dReal));
    dReal *R = (dReal*)dAlloc(4*3*sizeof(dReal));
    if(obj[0].geom[0])
    {
        dsSetColor (1,0,0);
        getGeomTransfInWorld(obj[0].geom[0], pos,R);
        dsDrawCylinder(pos,R,WHEEL_AXE_LENGTH,WHEEL_AXE_RADIUS);
        dsSetColor (1,1,0);
        for (int j=1; j < GPB; j++)
        {
            getGeomTransfInWorld(obj[0].geom[j], pos,R);
            dsDrawCylinder(pos,R,WHEEL_THICK,WHEEL_RADIUS);
         
        }
    }
    dFree(R,4*3*sizeof(dReal));
    dFree(pos,4*sizeof(dReal));
    if(obj[1].body != NULL)
        dsDrawCappedCylinder(dBodyGetPosition(obj[1].body),
                       
dBodyGetRotation(obj[1].body),WHEEL_AXE_LENGTH,WHEEL_AXE_RADIUS);


*************** If needed constants are
#define WHEEL_POSX 0
#define WHEEL_POSY 0
#define WHEEL_RADIUS 0.08   
#define WHEEL_THICK 0.02f
#define WHEEL_AXE_RADIUS WHEEL_RADIUS/4
#define WHEEL_SPACING 0.06
#define WHEEL_AXE_LENGTH (2*WHEEL_THICK)+WHEEL_SPACING+0.02


Don't get a headache please ;o)



More information about the ODE mailing list