[ODE] Speeding up a chain simulation
Shree Kumar
shree at procsys.com
Fri Jan 3 05:00:02 2003
Hi,
I am new to ODE & physics simulation.
I was trying to simulate a chain with ODE (using release 0.03).
Since there is no torus primitive, I modelled a link
in the chain using 4 boxes as below:
+----------+
/ /|
+----------+ |
| | |
| +------+ | |
| | | | | |
| | | | | |
height | | | | | |
| | +----| | |
| |/ | | |
| +------+ | |
| +/
+----------+
length <-> thichness
Excerpts from the code I used to create the chains are included
at the end of the message - please refer to it if the
diagram is found wanting [I am sure it is!]
Any number of these links can be positioned one below the other,
rotated by 90 degrees successively, resulting in a chain.
There is no need to use any joints. Only contact joints
created for collision resolution are enough.
I had 4 chains, each with 25 links. One end of each of the 4
chains was fixed and the other end was attached to a box. The
final effect conceived was a box supported by 4 chains.
After fixing a few problems due to the step-size, I was able
to get a good simulation. There was only one hitch - it was
terribly slow! [The simulation itself took more than a few
secs on my P4]
On close examination, I found that at each step, approximately
240 contact joints were being generated and this was the chief
cause of the slowdown.
Can anyone give me some hints on what I can do to improve
the simulation speed?
Please note:
1. I am already using single precision
2. I need 4 chains with 25 links & the box [can't relax the
requirement]
BTW, I tried to add a torus class. I have implemented torus-
sphere collisions but am yet to implement torus-torus
collisions
Thanks in advance for any info.
- Shree Kumar
Code follows:
---------------------------------------------
ChainLink::ChainLink(float length, float height, float thickness,
dSpaceID space, dWorldID world)
{
// create the 4 boxes & the rigid body for them
int i;
dGeomID b[4];
// save the world & space info
m_world = world;
m_space = space;
m_jointid = 0;
m_length = length;
m_height = height;
m_thickness = thickness;
dMass m, m2;
dMassSetZero(&m);
m_body = dBodyCreate(world);
dReal dimensions[4][3] = {
// top segment
{ length, thickness, thickness },
// bottom segment
{ length, thickness, thickness },
// left segment
{ thickness, height - 2* thickness, thickness },
// right segment
{ thickness, height - 2* thickness, thickness }
};
dReal position[4][3] = {
// top seg
{ 0, height/2 -thickness/2, 0 },
// bottom seg
{ 0, -height/2 + thickness/2, 0 },
// left seg
{-length/2+thickness/2,0,0},
// right seg
{length/2-thickness/2,0,0}
};
// for each part of the link
for(i=0;i<4;i++)
{
// Create a geom transform
m_box[i]=dCreateGeomTransform(space);
// and add a box to it
b[i]=dCreateBox(0,dimensions[i][0],dimensions[i][1],dimensions[i][2]);
// set the mass properties of the box
dMassSetBox(&m2,1,dimensions[i][0],dimensions[i][1],dimensions[i][2]);
dGeomTransformSetGeom(m_box[i], b[i]);
dGeomSetPosition(b[i],position[i][0],position[i][1],position[i][2]);
dMassTranslate(&m2,position[i][0],position[i][1],position[i][2]);
dMassAdd(&m,&m2);
}
// move all objects so that center of mass is (0,0,0)
for(i=0;i<4;i++)
{
dGeomSetPosition(b[i],position[i][0]-m.c[0],position[i][1]-m.c[1],position[i][2]-m.c[2]);
}
dMassTranslate(&m,-m.c[0],-m.c[1],-m.c[2]);
for(i=0;i<4;i++)
{
dGeomSetBody(m_box[i],m_body);
}
// Set the final mass of the entire link
dBodySetMass(m_body,&m);
}
Chain::Chain(float sx, float sy, float sz, // start position of first
link
float length, float height, float thickness, // dimensions
int nLinks,
dSpaceID space, dWorldID world,
float st_angle, float end_angle) // rotation angles
// for the first link &
last link
{
int i;
m_nLinks = nLinks;
// convert degrees to radians
st_angle = st_angle*M_PI/180.0;
end_angle = end_angle*M_PI/180.0;
float cur_angle = st_angle;
float incr_angle = (end_angle-st_angle)/((float)nLinks-1);
float link_angle = 0.0;
// create links & position them
for(i=0;i<nLinks;i++)
{
ChainLink * link = new ChainLink(length, height, thickness, space,
world);
// rotate even links by 90 degrees
if ((i%2)==1)
{
link_angle = 0.5*M_PI;
}
else
{
link_angle = 0.0;
}
// set the rotation of the chain link
dQuaternion q;
dQFromAxisAndAngle(q,0,1,0,cur_angle+link_angle);
dBodySetQuaternion(link->GetBodyID(),q);
// update rotation for next link
cur_angle = cur_angle + incr_angle;
dBodySetPosition(link->GetBodyID(),sx,sy,sz);
// save the ptr to this link
m_link.push_back(link);
// next link will be below this one
// links are positioned so they touch
// this avoids needless oscillation
// in the simulation
sy = sy-height-thickness;
}
}