11. Force and Torque

This is the 11th ODE (Open Dynamics Engine) tutorial. Let's study force and torque.

1. Force and torque of a body

dBodyGetForce() and dBodyGetTorqueForce() get force and torque on a body. dBodySetForce() and dBodySetTorque() set force and torque on the body. The coordinate system is the absolute coordinate system.

  • const dReal * dBodyGetForce (dBodyID body);
  • const dReal * dBodyGetTorque (dBodyID body);
    Get force and torque vector of a body. Return a pointer to the array of 3 elements.
  • void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z);
  • void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z);
    Set force and torque vector.

2. Force and torque of a joint

(1) Get force and torque

For the next, let's study how to get force and torque  of a joint. In order to get force and torque, firstly, dJointSetFeedback() must be called to specify a joint, secondly, call dJointGetFeedback() to get the information. This is to improve performance. You do not always needs force and torque information of all joints.

  • void dJointSetFeedback(dJointID, dJointFeedback *);
    Set the joint to get force and torque. The dJointFeedback structure is defined as follows.



    typedef struct dJointFeedback (
    dVector3 f1;  //  joints in the body influence the power of one
    dVector3 t1;  //  joints in the body influence the torque 1
    dVector3 f2;  //  joints in the body influence the power of 2
    dVector3 t2;  //  joints in the body influence the torque 2
    ) dJointFeedback;

  • dJointFeedback *dJointGetFeedback(dJointID);
    Get the information about force and torque of the joint

(2) Set power and torque

Depending on the type of joints,  force or torque will be set. In other words, such as a rotary joint,  a hinge joint, torque must be applied.  For a slider joint, force must be applied.

  • dJointAddHingeTorque (dJointID joint, dReal torque)
    Add torque to the hinge joint.
  • dJointAddSliderForce (dJointID joint, dReal force)
    Add force to the slider joint.

Next, a sample program using these APIs are introduced. Two boxes are connected by a fixed joint. Weight of each box is 1kg. So, the force along z-axis should be 9.8 [N] in thoretically. In my environment, the simulated value is about 9.8 [N].

You can easily make pressure sensors for a humanoid robot using this sample program.

The sample program, sample11.cpp,  can be downloaded from here.

C++:
  1. // sample11.cpp  by Kosei Demura  2006-2008
  2. #include "ode/ode.h"
  3. #include "drawstuff/drawstuff.h"
  4.  
  5. static dWorldID world;
  6. static dSpaceID space;
  7. static dGeomID  ground;
  8. static dJointID fixed;
  9. static dJointGroupID contactgroup;
  10. dJointFeedback *feedback = new dJointFeedback;
  11. dsFunctions fn;
  12.  
  13. typedef struct {
  14.   dBodyID body;
  15.   dGeomID geom;
  16.   dReal   radius,length,width,height,mass;
  17. } myLink;
  18. myLink box,sensor;
  19.  
  20. static void nearCallback (void *data, dGeomID o1, dGeomID o2)
  21. {
  22.   static int MAX_CONTACTS = 10;
  23.   int i;
  24.  
  25.   dBodyID b1 = dGeomGetBody(o1);
  26.   dBodyID b2 = dGeomGetBody(o2);
  27.   if (b1 && b2 && dAreConnected (b1,b2)) return;
  28.  
  29.   dContact contact[MAX_CONTACTS];   //
  30.   int numc = dCollide(o1,o2,MAX_CONTACTS,&contact[0].geom,
  31.   sizeof(dContact));
  32.   if (numc> 0) {
  33.     for (i=0; i <numc; i++) {
  34.        contact[i].surface.mode  =  dContactSoftCFM | dContactSoftERP;
  35.        contact[i].surface.mu       = dInfinity;  
  36.        contact[i].surface.soft_cfm = 1e-8;
  37.        contact[i].surface.soft_erp = 1.0;
  38.        dJointID c = dJointCreateContact(world,contactgroup,&contact[i]);
  39.        dJointAttach (c,dGeomGetBody(contact[i].geom.g1),
  40.        dGeomGetBody(contact[i].geom.g2));
  41.     }
  42.   }
  43. }
  44.  
  45. static void simLoop (int pause)
  46. {
  47.   static int steps = 0;
  48.  
  49.   dSpaceCollide(space,0,&nearCallback);
  50.   dWorldStep(world,0.01);
  51.   dJointGroupEmpty(contactgroup);
  52.  
  53.   feedback = dJointGetFeedback(fixed); // Get force and torque of the joint
  54.   printf("%5d Force fx=%6.2f ",steps++,feedback->f1[0]); // x axis
  55.   printf("fy=%6.2f ",feedback->f1[1]);           // y axis
  56.   printf("fz=%6.2f \n",feedback->f1[2]);          // z axis
  57.  
  58.   // Draw a box
  59.   dsSetColor(1.0,0.0,0.0);
  60.   dReal sides1[] = {box.length,box.width,box.height};
  61.   dsDrawBoxD(dBodyGetPosition(box.body),
  62.   dBodyGetRotation(box.body),sides1);
  63.  
  64.   // Draw a sensor
  65.   dsSetColor(0.0,0.0,1.0);
  66.   dReal sides2[] = {sensor.length,sensor.width,sensor.height};
  67.   dsDrawBoxD(dBodyGetPosition(sensor.body),
  68.   dBodyGetRotation(sensor.body),sides2);
  69. }
  70.  
  71. void start()
  72. {
  73.   static float xyz[3] = {0.0,-3.0,1.0};
  74.   static float hpr[3] = {90.0,0.0,0.0};
  75.   dsSetViewpoint (xyz,hpr);
  76. }
  77.  
  78. void  setDrawStuff()
  79. {
  80.   fn.version = DS_VERSION;
  81.   fn.start   = &start;
  82.   fn.step    = &simLoop;
  83.   fn.command = NULL;
  84.   fn.stop    = NULL;
  85.   fn.path_to_textures = "../../drawstuff/textures";
  86. }
  87.  
  88. int main (int argc, char **argv)
  89. {
  90.   setDrawStuff();
  91.   dInitODE();
  92.   world = dWorldCreate();
  93.   space = dHashSpaceCreate(0);
  94.   contactgroup = dJointGroupCreate(0);
  95.   dWorldSetGravity(world,0,0,-9.8);
  96.  
  97.   ground = dCreatePlane(space,0,0,1,0);
  98.  
  99.   dMass m1;
  100.   dReal x0 = 0.0, y0 = 0.0, z0 = 0.0;
  101.  
  102.   // A sensor (lower box)
  103.   sensor.length = 0.2;  sensor.width  = 0.2;
  104.   sensor.height = 0.2;  sensor.mass   = 1.0;
  105.   sensor.body   = dBodyCreate(world);
  106.   dMassSetZero(&m1);
  107.   dMassSetBoxTotal(&m1,sensor.mass,sensor.length,sensor.width,sensor.height);
  108.   dBodySetMass(sensor.body,&m1);
  109.   dBodySetPosition(sensor.body, x0, y0, 0.5 * sensor.height + z0);
  110.  
  111.   sensor.geom = dCreateBox(space,sensor.length,sensor.width,sensor.height);
  112.   dGeomSetBody(sensor.geom,sensor.body);
  113.  
  114.   // The upper box
  115.   box.length = 0.2;  box.width  = 0.2;
  116.   box.height = 0.2;  box.mass   = 1.0;
  117.   box.body   = dBodyCreate(world);
  118.   dMassSetZero(&m1);
  119.   dMassSetBoxTotal(&m1,box.mass,box.length,box.width,box.height);
  120.   dBodySetMass(box.body,&m1);
  121.   dBodySetPosition(box.body, x0, y0, sensor.height + 0.5 * box.height + z0);
  122.  
  123.   box.geom = dCreateBox(space,box.length,box.width,box.height);
  124.   dGeomSetBody(box.geom,box.body);
  125.  
  126.   // A fixed joint
  127.   fixed = dJointCreateFixed(world,0);
  128.   dJointAttach(fixed,box.body,sensor.body);
  129.   dJointSetFixed(fixed);
  130.  
  131.   // Set a joint to get information about force and torque
  132.   dJointSetFeedback(fixed,feedback);
  133.  
  134.   dsSimulationLoop(argc,argv,352,288,&fn);
  135.   dWorldDestroy(world);
  136.   dCloseODE();
  137.   return 0;
  138. }

That's all. See you ! demu

Leave a Reply

カウンタ (since 2008-3-15)
Copyright © 1998-2008    Kosei Demura