ODEã§å­¦ã¶C言語 [Step5: 構造体]

2009-07-16
By
物体ã®å±žæ€§ï¼š ボディã¨ã‚¸ã‚ªãƒ¡ãƒˆãƒª

物体ã®å±žæ€§ï¼šãƒœãƒ‡ã‚£ã¨ã‚¸ã‚ªãƒ¡ãƒˆãƒª

ODEã§å­¦ã¶C言語ã®Step5ã§ã™ï¼Žä»Šå›žã¯æ§‹é€ ä½“ã‚’ç·´ç¿’ã—ã¾ã—ょã†ï¼Žæ§‹é€ ä½“ã®æ¦‚è¦ã«ã¤ã„ã¦ã¯æ—¢ã«ã‚ã‹ã£ã¦ã„ã‚‹ã‚‚ã®ã¨ã—,サンプルコードを示ã™ã“ã¨ã«ã‚ˆã‚Šå…·ä½“çš„ãªä½¿ã„方を学ã³ã¾ã™ï¼Ž

ODEã§ã¯è¡çªæ¤œå‡ºæ©Ÿèƒ½ã‚’使用ã™ã‚‹ã«ã¯è¡çªæ¤œå‡ºç”¨ã®ã‚¹ãƒšãƒ¼ã‚¹(space)ã¨å‹•力学計算用ã®ãƒ¯ãƒ¼ãƒ«ãƒ‰(world)ã®ï¼’ã¤ã‚’生æˆã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ãれã«ä¼´ã„,物体ã«ï¼’ã¤ã®å±žæ€§ï¼Œã¤ã¾ã‚Šï¼Œå‹•力学計算ã®å¯¾è±¡ã¨ãªã‚‹ãƒœãƒ‡ã‚£(剛体,body)ã¨è¡çªæ¤œå‡ºè¨ˆç®—ã®å¯¾è±¡ã¨ãªã‚‹ã‚¸ã‚ªãƒ¡ãƒˆãƒª(geometry)ã‚’æŒãŸã›ã¦ã„ã¾ã™ã€‚ãªãŠï¼Œå‰›ä½“ã®ã“ã¨ã‚’英語ã§Rigid Bodyã¨ã„ã„,Geometryã¨ã¯å¹¾ä½•学的ãªå½¢çжã¨ã„ã†æ„味ã§ã™ã€‚

ボディã¨ã‚¸ã‚ªãƒ¡ãƒˆãƒªãŒåˆ¥ã€…ã«å®Ÿè£…ã•れ,別々ã®ãƒ¯ãƒ¼ãƒ«ãƒ‰ã‚„スペースã«å­˜åœ¨ã™ã‚‹ãŸã‚ã«ï¼Œä¸¡è€…を関連付ã‘ã‚‹å¿…è¦ãŒã‚りã¾ã™ï¼Žä»¥ä¸‹ï¼Œç‰©ä½“ã®ä½œã‚Šæ–¹ã‚’説明ã—ã¾ã™ï¼Ž

(1) ボディã®ä½œã‚Šæ–¹

ボディã¯ä»¥ä¸‹ã®é †ç•ªã«å¾“ã£ã¦ä½œã‚Šã¾ã™ï¼Ž

  1. ボディã®ç”Ÿæˆ dBodyID dBodyCreate(dWorldID world);
    ボディをワールドworld内ã«ç”Ÿæˆã—,ボディã®IDã‚’è¿”ã—ã¾ã™ï¼Ž
  2. 質é‡ãƒ‘ラメータã®åˆæœŸåŒ– void dMassSetZero(dMass *mass);
    質é‡ï¼Œé‡å¿ƒä½ç½®ï¼Œæ…£æ€§ãƒ¢ãƒ¼ãƒ¡ãƒ³ãƒˆãªã©ãŒå…¥ã£ã¦ã„る質é‡ãƒ‘ラメータmassã‚’åˆæœŸåŒ–ã—ã¾ã™ï¼Ž
  3. 質é‡ãƒ‘ラメータã®è¨ˆç®— void dMassSet***Total(dMass *mass, dReal total_mass, … );
    ***ã«ã¯ãƒœãƒ‡ã‚£ã®ç¨®é¡ž(Shpere, Box, Cylinder, Capsuleãªã©ï¼‰ãŒå…¥ã‚Šã¾ã™ï¼Žmassã¯è³ªé‡ãƒ‘ラメータ,total_massã¯ãƒœãƒ‡ã‚£ã®å…¨è³ªé‡ï¼ŽãªãŠï¼Œå¼•ãæ•°ã¯ãƒœãƒ‡ã‚£ã®ç¨®é¡žã«ã‚ˆã£ã¦é•ã†ã®ã§çœç•¥ã—ã¦ã„ã¾ã™ï¼Žè©³ç´°ã¯API集をã”覧ãã ã•ã„.
  4. ボディã«è³ªé‡ãƒ‘ラメータを設定 void dBodySetMass(dBodyID body, const dMass *mass);
    ボディbodyã«è³ªé‡ãƒ‘ラメータmassを設定ã—ã¾ã™ï¼Ž
  5. ボディã®ä½ç½®ã‚’設定 void dBodySetPosition(dBodyID body, dReal x, dReal y, dReal z);
    ボディbodyを絶対座標系(x,y,z)ã«è¨­å®šã—ã¾ã™ï¼Ž
  6. ボディã®å§¿å‹¢ã‚’設定 void dBodySetRotation(dBodyID, const dMatrix3 R);
    ボディbodyã®å§¿å‹¢ã‚’回転行列Rã«è¨­å®šã—ã¾ã™ï¼Ž

(2) ジオメトリã®ä½œã‚Šæ–¹

次ã«ã‚¸ã‚ªãƒ¡ãƒˆãƒªã®ä½œã‚Šæ–¹ã‚’紹介ã—ã¾ã™ï¼Žãƒœãƒ‡ã‚£ã¨æ¯”較ã™ã‚‹ã¨ç°¡å˜ã§ã™ï¼Žã‚¸ã‚ªãƒ¡ãƒˆãƒªã®ç¨®é¡žã«å¯¾å¿œã—ãŸä»¥ä¸‹ã®APIを呼ã³å‡ºã™ã ã‘ã§ã™ï¼Ž

  • dGeomID dCreateBox (dSpaceID space, dReal lx, dReal ly, dReal lz);

space ã§æŒ‡å®šã•れãŸã‚¹ãƒšãƒ¼ã‚¹ã«x,y,z è»¸ã«æ²¿ã£ãŸé•·ã•lx,ly,lz ã®ç›´æ–¹ä½“ジオメトリを生æˆã—,ãã®ID 番å·ã‚’è¿”ã™ï¼Žç›´æ–¹ä½“ジオメトリã®å‚照点ã¯ãã®é‡å¿ƒã§ã‚る.

  • dGeomID dCreateCapsule(dSpaceID space, dReal r, dReal l);

space ã§æŒ‡å®šã•れãŸã‚¹ãƒšãƒ¼ã‚¹ã«åŠå¾„r,長ã•l ã®ã‚«ãƒ—セルジオメトリを生æˆã—,ãã®ID 番å·ã‚’è¿”ã™ï¼Žã‚«ãƒ—ã‚»ãƒ«ã¯æ™®é€šã®å††æŸ±ã®ä¸¡ç«¯ã«åŠçƒã‚’被ã›ãŸã‚ˆã†ãªã‚‚ã®ã§ã‚る.ã“ã®ç‰¹å¾´ã¯è¡çªæ¤œå‡ºã®å†…部コードを拘æŸã‹ã¤æ­£ç¢ºã«ã™ã‚‹ã“ã¨ãŒã§ãる.引数ã®length ã«ã¯åŠçƒã®ã‚­ãƒ£ãƒƒãƒ—を入れãªã„.キャップã®åŠå¾„ã¯å††æŸ±ã®åŠå¾„radius ã¨åŒã˜ã§ã‚る.

  • dGeomID dCreateCylinder(dSpaceID space, dReal r, dReal l);

スペースspaceã«åŠå¾„r,長ã•l ã®å††æŸ±ã‚¸ã‚ªãƒ¡ãƒˆãƒªã‚’生æˆã—,ãã®ID 番å·ã‚’è¿”ã™ï¼Ž

  • dGeomID dCreateSphere(dSpaceID space, dReal r);

åŠå¾„rã®çƒã‚¸ã‚ªãƒ¡ãƒˆãƒªã‚’生æˆã—,ãã®ID 番å·ã‚’è¿”ã™ï¼Ž

  • dGeomID dCreatePlane(dSpaceID space, dReal a, dReal b, dReal c, dReal d);

å¹³é¢ã‚¸ã‚ªãƒ¡ãƒˆãƒªã‚’与ãˆã‚‰ã‚ŒãŸå¼•æ•°ã«ã‚ˆã‚Šç”Ÿæˆã—,ãã®ID 番å·ã‚’è¿”ã™ï¼Žå¼•æ•°space ãŒ0 ã§ãªã‘れã°ï¼Œãã®space ã«å¹³é¢ã‚¸ã‚ªãƒ¡ãƒˆãƒªã‚’挿入ã™ã‚‹ï¼Žå¼•æ•°a,b,c,d ã¯å¹³é¢ã®æ–¹ç¨‹å¼ã€€ax+by+cz = d ã®ãƒ‘ラメータã§ã‚る.平é¢ã®æ³•線ベクトルã¯(a,b,c) ã§ã‚り長ã•ã¯ï¼‘ã§ãªã‘れã°ãªã‚‰ãªã„.平é¢ã‚¸ã‚ªãƒ¡ãƒˆãƒªã¯è¨­ç½®ä¸å¯èƒ½(non-placeable),ã¤ã¾ã‚Šä½ç½®ã‚„姿勢を定義ã§ããªã„特別ãªã‚¸ã‚ªãƒ¡ãƒˆãƒªã§å¸¸ã«çµ¶å¯¾åº§æ¨™ç³»ã§å®šç¾©ã—ãªã‘れã°ãªã‚‰ãªã„.ã¤ã¾ã‚Šï¼Œå¹³é¢ã‚ªãƒ–ジェクトã¯å¸¸ã«é™çš„ãªç’°å¢ƒã®ä¸€éƒ¨ã¨ã—ã¦ä½¿ã‚れるã“ã¨ã‚’仮定ã—ã¦ã„る.

(3) ボディã¨ã‚¸ã‚ªãƒ¡ãƒˆãƒªã®å¯¾å¿œä»˜ã‘

  • void dGeomSetBody(dGeomID geom, dBodyID body);

    ジオメトリgeomをボディbodyã«é–¢é€£ä»˜ã‘ã¾ã™ï¼Ž

(4) è¡çªæ¤œå‡ºè¨ˆç®—

è¡çªæ¤œå‡ºè¨ˆç®—ã‚’ã™ã‚‹ãŸã‚ã«ã¯ã€ã‚¹ãƒšãƒ¼ã‚¹spaceã‚’dHashSpaceCreate()ã§ç”Ÿæˆã—ã€ãã®ä¸­ã«å‰›ä½“bodyã«å¯¾å¿œã™ã‚‹ã‚¸ã‚ªãƒ¡ãƒˆãƒª を生æˆã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。以下ã®ã‚µãƒ³ãƒ—ルプログラムã§ã¯ã€53行目ã§çƒã«å¯¾å¿œã™ã‚‹ã‚¸ã‚ªãƒ¡ãƒˆãƒªã‚’dCreateSphere()ã§ç”Ÿæˆ ã—ã¦ã„ã¾ã™ã€‚54行目ã§ã€å‹•力学計算ã®å¯¾è±¡ã¨ãªã‚‹ãƒœãƒ‡ã‚£obj->bodyã¨è¡çªæ¤œå‡ºè¨ˆç®—ã®å¯¾è±¡ã¨ãªã‚‹obj->geomã‚’çµã³ã¤ã‘ã¦ã„ã¾ã™ã€‚ã“れ㧠ODEã®ç‰©ä½“ãŒå®Œæˆã§ã™ã€‚

次ã«ã€simLoop関数ã®ä¸­ã§ã€dSpaceCollide()を呼ã³å‡ºã—ã¾ã™ã€‚ã“ã®APIã¯è¡çªã—ãã†ãªï¼’ã¤ã®ã‚¸ã‚ªãƒ¡ãƒˆãƒªãŒç™ºç”Ÿã—ãŸã‚‰ã€ãれらを nearCallbacké–¢æ•°ã«æ¸¡ã—ã¾ã™ã€‚ã“ã“ã§ã¯nearCallbacké–¢æ•°ã®æœ¬ä½“ã¯ç¤ºã—ã¾ã›ã‚“ãŒï¼Œã“ã®é–¢æ•°ã§ã€æŽ¥è§¦ç‚¹ã‚’算出ã—ãŸã‚Šã€æŽ¥è§¦ç‚¹ã®æ€§è³ªãªã©ã‚’設定ã—ã¾ã™ã€‚

ã¾ãŸã€69行目ã«ã‚るよã†ã«æŽ¥è§¦ç‚¹ã®é›†ã¾ã‚ŠãŒæ ¼ç´ã•れる入れ物をdJointGroupCreate()ã§ç”Ÿæˆã—ã€ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ«ãƒ¼ãƒ—ã§æ¯Žå›žã れを31行目ã®ã‚ˆã†ã«dJointGroupEmpty()を使ã£ã¦ç©ºã«ã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。

  • è¡çªæ¤œå‡ºã«é–¢ã™ã‚‹API
    • dSpaceID dHashSpaceCreate(0)
      è¡çªè¨ˆç®—用スペースを生æˆã—ã€ãã®ID(識別å­ï¼‰ã‚’è¿”ã™ã€‚
    • dGeomID dCreatePlane(dSpaceID space ,dReal a, dReal b, dReal c, dReal d)
      spaceã«ax+by+cz=dã®å¹³é¢ã‚¸ã‚ªãƒ¡ãƒˆãƒªã‚’生æˆã™ã‚‹ã€‚
    • dGeomID dCreateSphere(dSpaceID space, dReal r)
      spaceã«åŠå¾„rã®çƒã‚¸ã‚ªãƒ¡ãƒˆãƒªã‚’生æˆã™ã‚‹ã€‚
    • void dGeomSetBody(dGeomID geom, dBodyID body)
      物体ã®2ã¤ã®å±žæ€§ã§ã‚るジオメトリgeomã¨å‰›ä½“bodyを関連ã¥ã‘る。
    • dJointGroupID dJointGroupCreate(0)
      接触点ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’æ ¼ç´ã™ã‚‹ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã‚°ãƒ«ãƒ¼ãƒ—を生æˆã—ã€ãã®IDã‚’è¿”ã™ã€‚
    • void dJointGroupEmpty(dJointGroupID)
      æŽ¥è§¦ç‚¹ãŒæ ¼ç´ã•れã¦ã„るジョイントグループを空ã«ã™ã‚‹ã€‚

(5) ソースコード

ã§ã¯ï¼ŒStep4ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã«è¡çªæ¤œå‡ºã«é–¢ã™ã‚‹ã‚³ãƒ¼ãƒ‰ã‚’組ã¿è¾¼ã‚“ã ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’紹介ã—ã¾ã™ï¼Žã“ã®å‡¦ç†ã‚ˆã‚Šãƒœãƒ¼ãƒ«ãŒåœ°é¢ã‚’ã¤ã抜ã‘ãšï¼Œåœ°é¢ã§ã¯ãšã‚€ã‚ˆã†ã«ãªã‚Šã¾ã™ï¼Ž

#include "dm5.h"

dWorldID world;  // 動力学ã®ä¸–界
dSpaceID space;  // è¡çªæ¤œå‡ºç”¨ã‚¹ãƒšãƒ¼ã‚¹
dGeomID  ground; // 地é¢
dJointGroupID contactgroup; // コンタクトグループ

typedef struct {
  dBodyID body; // ボディã®ID
  dGeomID geom; // ジオメトリã®ID
  double *pos; // x, y, z [m]
  double *R;   // 回転行列 è¦ç´ æ•°4x3
  double r, m; // åŠå¾„ [r], è³ªé‡ [kg]
  float *color; // 色 r,g,b
} MyObject;

MyObject apple;

void dmDraw(MyObject obj) /*** ç‰©ä½“ã®æç”» ***/
{
 dsSetColor(obj.color[0],obj.color[1],obj.color[2]);  // 色ã®è¨­å®š(r,g,b)
  const double *pos = dBodyGetPosition(obj.body);  // ä½ç½®ã‚’å–å¾—
  const double *R   = dBodyGetRotation(obj.body);  // 姿勢をå–å¾—
  dsDrawSphere(pos,R,obj.r);                       // çƒã®æç”»
}

void simLoop(int pause)           /***  シミュレーションループ ***/
{
  dSpaceCollide(space,0,&nearCallback); // è¡çªæ¤œå‡ºé–¢æ•°
  dWorldStep(world,0.01); // シミュレーションを1ステップ進ã‚ã‚‹
  dJointGroupEmpty(contactgroup); // ジョイントグループを空ã«ã™ã‚‹

  dmDraw(apple); //  ç‰©ä½“ã®æç”»
}

void dmSphereCreate(MyObject *obj,double p[3], double R[12],
	double m, double r, float *color)
{
 obj->m = m;
 obj->r = r;
 obj->pos = p;
 obj->R   = R;
 obj->color = color;

 dRSetIdentity(obj->R);
 obj->body = dBodyCreate(world);           // ボールã®ç”Ÿæˆ
 dMass mass;                               // 構造体massã®å®£è¨€
  dMassSetZero(&mass);                      // 構造体massã®åˆæœŸåŒ–
  dMassSetSphereTotal(&mass,obj->m,obj->r); // 構造体massã«è³ªé‡ã‚’設定
  dBodySetMass(obj->body,&mass);            // ボールã«massを設定
  dBodySetPosition(obj->body,obj->pos[0],obj->pos[1],obj->pos[2]); // ボールã®ä½ç½®(x,y,z)を設定

  obj->geom = dCreateSphere(space,obj->r); // çƒã‚¸ã‚ªãƒ¡ãƒˆãƒªã®ç”Ÿæˆ
  dGeomSetBody(obj->geom, obj->body);      // ボディã¨ã‚¸ã‚ªãƒ¡ãƒˆãƒªã®é–¢é€£ä»˜ã‘
}

int main()         /*** main関数 ***/
{
  // リンゴã®å¤‰æ•°
 double p[3] = {0.0, 0.0, 2.0}; // ä½ç½®
 double R[12];   // 回転行列
 double m = 1.0; // 質é‡
 double r = 0.2; // åŠå¾„
  float  color[3] = {1.0, 0.0, 0.0}; // 色

  dInitODE(); // ODEã®åˆæœŸåŒ–
  world = dWorldCreate();               // 動力学用世界ã®å‰µé€ 
  space        = dHashSpaceCreate(0);   // è¡çªç”¨ç©ºé–“ã®å‰µé€ 
  contactgroup = dJointGroupCreate(0);  // ジョイントグループã®ç”Ÿæˆ
  ground = dCreatePlane(space,0,0,1,0); // 地é¢ï¼ˆå¹³é¢ã‚¸ã‚ªãƒ¡ãƒˆãƒªï¼‰ã®ç”Ÿæˆ
  dWorldSetGravity(world,0,0,-0.2);     // é‡åŠ›è¨­å®š

  dRSetIdentity(R);  //回転行列をå˜ä½è¡Œåˆ—ã§åˆæœŸåŒ–
  dmSphereCreate(&apple,p,R,m,r,color); // リンゴã®ç”Ÿæˆ

  dmLoop(800, 600);  // シミュレーションループ ウインドウã®å¹…,高

  dSpaceDestroy(space); // è¡çªç”¨ç©ºé–“ã®ç ´å£Š
  dWorldDestroy(world); // 動力学用世界ã®ç ´å£Š
  dCloseODE();          // ODEã®çµ‚了
  return 0;
}

(6) ホームワーク

  1. サンプルコードstep5-090714.zipã‚’ã“ã“ã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¦å®Ÿè¡Œã—よã†ï¼
  2. step5.cppã¨åŒã˜ãƒ•ォルダã«dm5.cppãŒã‚りã¾ã™ï¼Žãã®ä¸­ã«nearCallback関数ãŒã‚り,å発係数を設定ã—ã¦ã„る箇所ãŒ47行目ã«ã‚りã¾ã™ï¼Žä»¥ä¸‹ã®ã‚ˆã†ã«å発係数ãŒ1.0ã«è¨­å®šã•れã¦ã„ã¾ã™ï¼Žã“ã®å€¤ã‚’ã„ã‚ã„ã‚変更ã—ã¦æŒ™å‹•を観察ã—ã¦ãã ã•ã„.1.0より大ããã™ã‚‹ã¨ã©ã†ãªã‚Šã¾ã™ã‹ï¼Ÿ è² ã«ã™ã‚‹ã¨ã©ã†ãªã‚‹ã§ã—ょã†ã‹ï¼Ÿã„ãšã‚Œã‚‚,ç¾å®Ÿã«ã¯ã‚りãˆãªã„å発係数ã§ã™ï¼Ž
  3. contact[i].surface.bounce = 1.0;
  4. サンプルプログラムã¯çƒã‚’å¼¾ã¾ã›ã¾ã—ãŸãŒï¼Œã“ã‚“ã©ã¯ç›´æ–¹ä½“ã‚’å¼¾ã¾ã›ã¦ãã ã•ã„.
  5. 直方体ã®åˆæœŸå§¿å‹¢ã‚’変ãˆï¼Œå°‘ã—æ–œã‚ã«ã—ã¦è½ä¸‹ã•ã›æŒ™å‹•を観察ã—ã¾ã—ょã†ï¼Ž
    • ヒント:姿勢を変ãˆã‚‹ã«ã¯ODE本67ページã«ã‚ã‚‹dRFromAxisAndAngle()ã§å›žè»¢è»¸ã®ã¾ã‚りを回転ã•ã›ãŸã¨ãã®å›žè»¢è¡Œåˆ—Rã‚’å–å¾—ã—,ãã‚Œã‚’åˆæœŸå§¿å‹¢ã§è¨­å®šã—ã¦ãã ã•ã„.

Tags:

コメントをã©ã†ãž

メールアドレスãŒå…¬é–‹ã•れるã“ã¨ã¯ã‚りã¾ã›ã‚“。

1,599 views  (Since 2010-08-11)