ODE Tutorial 10: CFM (Constraint Force Mixing) ODE Tutorial 11: Position and Orientation
12 月 06

ゲーム開発やロボットの研究者にも使われているオープンソースの物理計算エンジンODE(Open Dynamics  Engine、オープン ダイナミクスエンジン)を学ぶODE講座の第12回目です。

Jimmyさんからの御質問にあったように関節にかかるトルクや力を調べるコマンドはわかりづらくなっています.今回は関節にかかるトルクを取得する方法を学びましょう。

ODEでは関節に かかるトルクなどをすぐ取得できません.取得するためにはdJointSetFeedbackで関節を指定してからdJointGetFeedbackで 情報を取得します.これはパフォーマンスを向上させるためです.常に全ての関節にかかる力とトルクが必要なわけではありませんよね.

  • void dJointSetFeedback (dJointID, dJointFeedback *);
    力とトルクの情報を取得する関節をdJointIDで指定する.dJointFeedback構造体は次のとおりです.




    typedef struct dJointFeedback {
    dVector3 f1; // 関節がボディ1に及ぼしている力
    dVector3 t1; // 関節がボディ1に及ぼしているトルク
    dVector3 f2; // 関節がボディ2に及ぼしている力
    dVector3 t2; // 関節がボディ2に及ぼしているトルク
    } dJointFeedback;

  • dJointFeedback *dJointGetFeedback (dJointID);
    dJointIDで指定している関節の力とトルクの情報を取得します.

次 に,このAPIを使ったサンプルプログラムを紹介します.ボックスを固定ジョイント(Fixed Joint)で地面(静的オブジェクト)立て、そこにセンサとなる固定ジョイントで重りのついている棒とボックスを結合します.センサにかかる力を表示するプログラムです.棒の重さが0.0001kgでほぼ無視できます.重りの質量が1kgなのでx軸まわりのトルクは9.8Nmであれば良いわけです.私の環境では理論どおり9.8の値をたたき出していました.ソースファイルはここからダウンロードできます。


CODE:
  1. // torque.cpp  by Kosei Demura  2006-12-05
  2.  #include "ode/ode.h"
  3.  #include "drawstuff/drawstuff.h"
  4.  
  5.  
  6. #ifdef dDOUBLE
  7. #define dsDrawCylinder dsDrawCylinderD
  8. #define dsDrawSphere   dsDrawSphereD
  9. #endif
  10.  
  11. static dWorldID world;
  12. static dSpaceID space;
  13. static dGeomID  ground;
  14. static dJointID sensor,fixed[2];
  15. static dJointGroupID contactgroup;
  16. dJointFeedback *feedback = new dJointFeedback;
  17. dsFunctions fn;
  18.  
  19. typedef struct {
  20.    dBodyID body;
  21.    dGeomID geom;
  22.    dReal   radius,length,width,height,mass;
  23.  } myLink;
  24. myLink stick, ball, box;
  25.  
  26. static void nearCallback (void *data, dGeomID o1, dGeomID o2)
  27.  {
  28.  static int MAX_CONTACTS = 10;
  29.  int i;
  30.  
  31. // exit without doing anything if the two bodies are connected by a joint
  32.  dBodyID b1 = dGeomGetBody(o1);
  33.  dBodyID b2 = dGeomGetBody(o2);
  34.  if (b1 && b2 && dAreConnected(b1,b2)) return;
  35.  
  36.  dContact contact[MAX_CONTACTS];   // up to MAX_CONTACTS contacts per box-box
  37.  int numc = dCollide(o1,o2,MAX_CONTACTS,&contact[0].geom,
  38.  sizeof(dContact));
  39.  if (numc> 0) {
  40.    for (i=0; i <numc; i++) {
  41.      contact[i].surface.mode  =  dContactSoftCFM | dContactSoftERP;
  42.      contact[i].surface.mu       = dInfinity;
  43.      contact[i].surface.soft_cfm = 1e-8;
  44.      contact[i].surface.soft_erp = 1.0;
  45.      dJointID c = dJointCreateContact(world,contactgroup,&contact[i]);
  46.  
  47.      dJointAttach (c,dGeomGetBody(contact[i].geom.g1),
  48.      dGeomGetBody(contact[i].geom.g2));
  49.    }
  50.  }
  51. }
  52.  
  53. static void simLoop (int pause)
  54. {
  55.  static int steps = 0;
  56.  
  57.  dSpaceCollide(space,0,&nearCallback);
  58.  dWorldStep(world,0.01);
  59.  dJointGroupEmpty(contactgroup);
  60.  
  61.  feedback = dJointGetFeedback(sensor);
  62.  printf("%5d Torque Tx=%6.2f ",steps++,feedback->t1[0]);
  63.  printf("Ty=%6.2f ",feedback->t1[1]);
  64.  printf("Tz=%6.2f \n",feedback->t1[2]);
  65.  
  66. // draw a box
  67.  dsSetColor(1.3,1.3,0.0);
  68.  dReal sides1[] = {box.length,box.width,box.height};
  69.  dsDrawBoxD(dBodyGetPosition(box.body),
  70.  dBodyGetRotation(box.body),sides1);
  71.  
  72. // draw a ball
  73.  dsSetColor(1.3,0.0,0.0);
  74.  dsDrawSphere(dBodyGetPosition(ball.body),
  75.  dBodyGetRotation(ball.body),ball.radius);
  76.  
  77. // draw a stick
  78.  dsSetColor(0.0,0.0,1.3);
  79.  dsDrawCylinder(dBodyGetPosition(stick.body),
  80.  dBodyGetRotation(stick.body),stick.length, stick.radius);
  81.  }
  82.  
  83. void start()
  84.  {
  85.  static float xyz[3] = {3.0,0.0,1.0};
  86.  static float hpr[3] = {180.0,0.0,0.0};
  87.  dsSetViewpoint (xyz,hpr);
  88.  dsSetSphereQuality(3);
  89.  }
  90.  
  91. void  setDrawStuff() {
  92.  fn.version = DS_VERSION;
  93.  fn.start   = &start;
  94.  fn.step    = &simLoop;
  95.  fn.command = NULL;
  96.  fn.stop    = NULL;
  97.  fn.path_to_textures = "../../drawstuff/textures";
  98.  }
  99.  
  100. int main(int argc, char **argv)
  101. {
  102.  setDrawStuff();
  103.  
  104.  world = dWorldCreate();
  105.  space = dHashSpaceCreate(0);
  106.  contactgroup = dJointGroupCreate(0);
  107.  dWorldSetGravity(world,0,0,-9.8);
  108.  dWorldSetERP(world,1.0);
  109.  
  110. // Create a ground
  111.  ground = dCreatePlane(space,0,0,1,0);
  112.  
  113.  dMass m1;
  114.  dReal x0 = 0.0, y0 = 0.0, z0 = 0.5;
  115.  dReal x1 = 0.0, y1 = 0.5, z1 = 1.0;
  116.  dReal x2 = 0.0, y2 = 1.0, z2 = 1.0;
  117.  dMatrix3 R;
  118.  
  119. // box
  120.  box.length = 0.1;  box.width  = 0.1;
  121.  box.height = 1.0;  box.mass   = 1.0;
  122.  box.body   = dBodyCreate(world);
  123.  dMassSetZero(&m1);
  124.  dMassSetBoxTotal(&m1,box.mass,box.length,box.width,box.height);
  125.  dBodySetMass(box.body,&m1);
  126.  dBodySetPosition(box.body, x0, y0, z0);
  127.  box.geom = dCreateBox(space,box.length,box.width,box.height);
  128.  dGeomSetBody(box.geom,box.body);
  129.  
  130. // stick
  131.  stick.length = 1.0;  stick.radius = 0.01;
  132.  stick.mass   = 0.0001;
  133.  stick.body   = dBodyCreate(world);
  134.  dMassSetZero(&m1);
  135.  dMassSetCylinderTotal(&m1,stick.mass,3, stick.radius, stick.length);
  136.  dBodySetMass(stick.body,&m1);
  137.  dBodySetPosition(stick.body, x1, y1, z1);
  138.  dRFromAxisAndAngle(R, 1, 0, 0, M_PI/2);
  139.  dBodySetRotation(stick.body, R);
  140.  stick.geom = dCreateCylinder(space,stick.radius,stick.length);
  141.  dGeomSetBody(stick.geom,stick.body);
  142.  
  143. // ball
  144.  ball.radius = 0.1;
  145.  ball.mass   = 1.0;
  146.  ball.body   = dBodyCreate(world);
  147.  dMassSetZero(&m1);
  148.  dMassSetSphereTotal(&m1,ball.mass,ball.radius);
  149.  dBodySetMass(ball.body,&m1);
  150.  dBodySetPosition(ball.body, x2, y2, z2);
  151.  ball.geom = dCreateSphere(space,ball.radius);
  152.  dGeomSetBody(ball.geom,ball.body);
  153.  
  154. // fixed joint
  155.  fixed[0] = dJointCreateFixed(world,0);
  156.  dJointAttach(fixed[0],0, box.body);
  157.  dJointSetFixed(fixed[0]);
  158.  
  159.  fixed[1] = dJointCreateFixed(world,0);
  160.  dJointAttach(fixed[1],stick.body,ball.body);
  161.  dJointSetFixed(fixed[1]);
  162.  
  163.  sensor = dJointCreateFixed(world,0);
  164.  dJointAttach(sensor,box.body, stick.body);
  165.  dJointSetFixed(sensor);
  166.  
  167. // set feed back
  168.  dJointSetFeedback(sensor,feedback);
  169.  
  170.  dsSimulationLoop(argc,argv,640, 480,&fn);
  171.  
  172.  dWorldDestroy(world);
  173.  dCloseODE();
  174.  return 0;
  175. }
投稿:06年12月06日

8 Responses to “ODE講座12:トルクセンサを作ろう”

  1. demu MonsterID Icon demu Says at 2008-09-10 :

    shinさん,

    すみません。恐れ入りますが,何が原因か教えて頂けないでしょうか。
    同じような問題で悩まないためにお願いします。

    でむ

  2. shin MonsterID Icon shin Says at 2008-09-10 :

    成功しました。

    ありがとうございました。

  3. demu MonsterID Icon demu Says at 2008-09-06 :

    shinさん,

    本文と下にリンクのあるtorque.cppをダウンロード,makeして頂けませんか?同じ開発環境で試したところエラーはでませんでした.

    http://demura.net/wordpress/wp-content/uploads/2008/09/torque.cpp

    でむ

  4. shin MonsterID Icon shin Says at 2008-09-05 :

    MinGWです。

  5. demu MonsterID Icon demu Says at 2008-09-05 :

    shinさん,

    度々すみません.
    Visual C++ですか? MinGWですか?

    でむ

  6. shin MonsterID Icon shin Says at 2008-09-05 :

    odeのバージョンは0.9
    開発環境はWindows XPです。

  7. demu MonsterID Icon demu Says at 2008-09-04 :

    shinさん,

    すみませんが,開発環境とODEのバージョンを教えてください.

    でむ

  8. shin MonsterID Icon shin Says at 2008-09-04 :

    dsDrawBox(dBodyGetPosition(box.body),
    dBodyGetRotation(box.body),sides);
    の部分で次のようなエラーが出ます。
    どうしたらよいのでしょうか?

    error: cannot convert `const dReal*' to `const float*' for argument `1' to `void dsDrawBox(const float*, const float*, const float*)'

Leave a Reply

カウンタ (since 2008-1-11)
Copyright © 1998-2008    Kosei Demura