ODE講座6:è¡çªæ¤œå‡º

åˆå¿ƒè€…ã•ã‚“ã‹ã‚‰ã”質å•ãŒã‚ã£ãŸã®ã§ã€ã‚ˆã‚Šã‚ã‹ã‚Šã‚„ã™ãã™ã‚‹ãŸã‚ã«èµ¤ã„ボールãŒåœ°é¢ã«æŽ¥è§¦ã—ãŸã‚‰é’色ã«ãªã‚‹ã‚ˆã†ã«ãƒ—ãƒã‚°ãƒ©ãƒ を改良ã—ã¾ã—ãŸã€‚ゲーム開発やãƒãƒœãƒƒãƒˆã®ç ”究者ã«ã‚‚使ã‚れã¦ã„るオープンソースã®ç‰©ç†è¨ˆç®—エンジンODE (Open Dynamics Engineã€ã‚ªãƒ¼ãƒ—ン ダイナミクスエンジン)をå¦ã¶ODE講座ã®ç¬¬ï¼–回目ã§ã™ã€‚
今回ã¯è¡çªæ¤œå‡ºæ©Ÿèƒ½ã«ã¤ã„ã¦å‹‰å¼·ã—ã¾ã™ã€‚å‰å›žã®ãƒ—ãƒã‚°ãƒ©ãƒ ã§ã¯è¡çªæ¤œå‡ºæ©Ÿèƒ½ãŒãªã‹ã£ãŸã®ã§ã€ãƒœãƒ¼ãƒ«ãŒåœ°é¢ã‚’ã™ã‚ŠæŠœã‘ã¦ã„ã£ãŸã‚ã‘ã§ã™ã€‚ODEã§ã¯å‹•力å¦è¨ˆç®—ã¨è¡çªæ¤œå‡ºè¨ˆç®—ãŒåˆ¥ã€…ã«å®Ÿè£…ã•れã¦ã„ã¾ã™ã€‚動力å¦è¨ˆç®—ã‚’ã™ã‚‹ãŸã‚ã«ã¯ã€ãƒ¯ãƒ¼ãƒ«ãƒ‰worldã‚’dWorldCreate()ã§ç”Ÿæˆã—ã€ãã®ä¸ã«å‰›ä½“bodyを生æˆã—ã€dWorldStep()ã§å‹•力å¦è¨ˆç®—ã‚’ã—ã¾ã—ãŸã。
ジオメトリ
ジオメトリã¨ã¯ç‰©ä½“ã®å½¢çжã¨ã„ã†æ„味ã§ã€ä¸‹å›³ã®å·¦ã‹ã‚‰sphere(çƒï¼‰ã€box(直方体)ã€cylinder(円柱)ã€capsule(カプセル)ãªã©ã®ç¨®é¡žãŒã‚りã¾ã™ã€‚

一方ã€è¡çªæ¤œå‡ºè¨ˆç®—ã‚’ã™ã‚‹ãŸã‚ã«ã¯ã€ã‚¹ãƒšãƒ¼ã‚¹spaceã‚’dHashSpaceCreate()ã§ç”Ÿæˆã—ã€ãã®ä¸ã«å‰›ä½“bodyã«å¯¾å¿œã™ã‚‹ã‚¸ã‚ªãƒ¡ãƒˆãƒªgeometryを生æˆã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。以下ã®ã‚µãƒ³ãƒ—ルプãƒã‚°ãƒ©ãƒ ã§ã¯ã€ï¼˜ï¼•行目ã§çƒã«å¯¾å¿œã™ã‚‹ã‚¸ã‚ªãƒ¡ãƒˆãƒªã‚’dCreateSphere()ã§ç”Ÿæˆã—ã¦ã„ã¾ã™ã€‚86行目ã§ã€å‹•力å¦è¨ˆç®—ã®å¯¾è±¡ã¨ãªã‚‹ãƒœãƒ‡ã‚£ball.bodyã¨è¡çªæ¤œå‡ºè¨ˆç®—ã®å¯¾è±¡ã¨ãªã‚‹ball.geomã‚’çµã³ã¤ã‘ã¦ã„ã¾ã™ã€‚ã“れã§ODEã®ç‰©ä½“ãŒå®Œæˆã§ã™ã€‚
次ã«ã€simLoop関数ã®ä¸ã§ã€dSpaceCollide()を呼ã³å‡ºã—ã¾ã™ã€‚ã“ã®APIã¯è¡çªã—ãã†ãªï¼’ã¤ã®ã‚¸ã‚ªãƒ¡ãƒˆãƒªãŒç™ºç”Ÿã—ãŸã‚‰ã€ãれらをnearCallbacké–¢æ•°ã«æ¸¡ã—ã¾ã™ã€‚nearCallback関数ã®å¼•æ•°o1, o2ãŒè¡çªã™ã‚‹å¯èƒ½æ€§ã®ã‚ã‚‹ï¼’ã¤ã®ã‚¸ã‚ªãƒ¡ãƒˆãƒªã§ã™ã€‚nearCallback関数ã§ã¯ã€æŽ¥è§¦ç‚¹ã‚’算出ã—ãŸã‚Šã€æŽ¥è§¦ç‚¹ã®æ€§è³ªãªã©ã‚’è¨å®šã—ã¾ã™ã€‚ ãªãŠã€æ³¨æ„ã—ãªã‘れã°ã„ã‘ãªã„ã“ã¨ã¯ã€å¼•æ•°o1ã€o2ã¯æŽ¥è§¦ã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹ã ã‘ã§ã€å®Ÿéš›ã«æŽ¥è§¦ã—ã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚ˆãã‚ã‹ã‚‰ãªã„ã“ã¨ã§ã™ã€‚ãれを知るãŸã‚ã«ã¯dCollide()ã®æˆ»ã‚Šå€¤ã€ã¤ã¾ã‚Šã€æŽ¥è§¦ç‚¹æ•°ãŒï¼‘以上ã‹ã©ã†ã‹ãƒã‚§ãƒƒã‚¯ã™ã‚Œã°è‰¯ã„ã®ã§ã™ã€‚
ã¾ãŸã€ï¼—4行目ã«ã‚るよã†ã«æŽ¥è§¦ç‚¹ã®é›†ã¾ã‚ŠãŒæ ¼ç´ã•れる入れ物をdJointGroupCreate()ã§ç”Ÿæˆã—ã€ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒ«ãƒ¼ãƒ—ã§æ¯Žå›žãれをdJointGroupEmpty()を使ã£ã¦ç©ºã«ã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。サンプルプãƒã‚°ãƒ©ãƒ ã§ã¯ï¼•7行目ã§ã‚„ã£ã¦ã„ã¾ã™ã€‚ã“れを忘れるã¨ï¼‘ステップå‰ã®æŽ¥è§¦ç‚¹é”ãŒæ‚ªã•ã‚’ã—ã¾ã™ã®ã§ãŠå¿˜ã‚Œãªãï¼
- è¡çªæ¤œå‡ºã«é–¢ã™ã‚‹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)
æŽ¥è§¦ç‚¹ãŒæ ¼ç´ã•れã¦ã„るジョイントグループを空ã«ã™ã‚‹ã€‚
- dSpaceID dHashSpaceCreate(0)
以下ã«ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’示ã—ã¾ã™ã€‚ å‰å›žã®ãƒ—ãƒã‚°ãƒ©ãƒ ã¨é•ã†ã¨ã“ã‚ã ã‘コメントを入れã¦ã„ã¾ã™ã€‚
ã•ã¦ã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’ã•ã£ããèªã¿ã¾ã—ょã†ã€‚ãªãŠã€å‰å›žã®sample1 ã¨å…¨ãåŒã˜start関数やprepDrawStuff関数ã¯çœç•¥ã—ã¦ã„ã¾ã™ã€‚
[code]
// sample2.cpp  by  ã§ã‚€
#include
#include
#ifdef dDOUBLE
#define dsDrawSphere dsDrawSphereD // å˜ç²¾åº¦ã¨å€ç²¾åº¦ã®æç”»é–¢æ•°ã«å¯¾å¿œã™ã‚‹ãŠã¾ã˜ãªã„
#endif
static dWorldID world; // 動力å¦è¨ˆç®—用ã®ãƒ¯ãƒ¼ãƒ«ãƒ‰
static dSpaceID space; // è¡çªæ¤œå‡ºç”¨ã®ã‚¹ãƒšãƒ¼ã‚¹
static dGeomID ground; //  地é¢
static dJointGroupID contactgroup; // コンタクトグループ
static int flag = 0; // 地é¢ã¨ã®æŽ¥è§¦ã‚’示ã™flag
dsFunctions fn;
const dReal radius = 0.2, mass = 1.0;  // åŠå¾„[m]ã€è³ªé‡[m]
// å‰å›žã¯å‹•力å¦è¨ˆç®—用ã®bodyã ã‘ã§ã—ãŸãŒã€ä»Šå›žã¯è¡çªæ¤œå‡ºç”¨ã®geomãŒåŠ ã‚ã£ãŸã®ã§ ãƒœãƒ¼ãƒ«ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã‚’æ§‹é€ ä½“ã§å®šç¾©ã—ã¾ã—ãŸã€‚
typedef struct {
dBodyID body;  // 動力å¦è¨ˆç®—用
dGeomID geom; // è¡çªæ¤œå‡ºç”¨
} MyObject;
MyObject ball; //  ボールオブジェクト
//  è¡çªæ¤œå‡ºã®ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯é–¢æ•°
static void nearCallback(void *data, dGeomID o1, dGeomID o2)
{
static const int N = 4;    // 接触点数ã®ä¸Šé™ã¯4個 staticを忘れãšã«ã¤ã‘ã¦ãã ã•ã„.
dContact contact[N];
int isGround = ((ground == o1) || (ground == o2)); // è¡çªã™ã‚‹ï¼’ã¤ã®ã†ã¡ã©ã¡ã‚‰ã‹ãŒåœ°é¢ãªã‚‰isGroundã®ãƒ•ラグを立ã¦ã‚‹
int n = dCollide(o1,o2,N,&contact[0].geom,sizeof(dContact)); // nã¯è¡çªç‚¹æ•°
if (isGround) { // å¤§åœ°ã®æ——ãŒç«‹ã£ã¦ã„ãŸã‚‰è¡çªæ¤œå‡ºæ©Ÿèƒ½ã‚’åƒã‹ã›ã‚‹
if (n >= 1) flag = 1;
else flag = 0;
for (int i = 0; i < n; i++) {
contact[i].surface.mode = dContactBounce; // 地é¢ã®å発係数をè¨å®š
contact[i].surface.bounce = 0.0; // (0.0~1.0) å発係数ã¯0ã‹ã‚‰1ã¾ã§
contact[i].surface.bounce_vel = 0.0; // (0.0以上) å発ã«å¿…è¦ãªæœ€ä½Žé€Ÿåº¦
// コンタクトジョイント生æˆ
dJointID c = dJointCreateContact(world,contactgroup,&contact[i]);
// 接触ã—ã¦ã„ã‚‹ï¼’ã¤ã®geometryã‚’ã‚³ãƒ³ã‚¿ã‚¯ãƒˆã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã§æ‹˜æŸ
dJointAttach (c,dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));
}
}
}
static void simLoop (int pause)
{
const dReal *pos,*R;
flag = 0; // 地é¢ã¨ã®è¡çªflagã‚’ï¼ã«ã‚»ãƒƒãƒˆ
dSpaceCollide(space,0,&nearCallback); // è¡çªåˆ¤å®šã€ã“れã¯ä¸€ç•ªæœ€åˆã«æ›¸ãã“ã¨ã€‚
dWorldStep(world,0.01);      // シミュレーションを1ステップ進ã‚ã‚‹
dJointGroupEmpty(contactgroup); // ジョイントグループを空ã«ã™ã‚‹
if (flag == 0) dsSetColor(1.0, 0.0, 0.0);  // 赤色ã®è¨å®š
else dsSetColor(0.0, 0.0, 1.0); // é’色ã®è¨å®š
pos = dBodyGetPosition(ball.body);  // ä½ç½®
R = dBodyGetRotation(ball.body);  // 回転行列
dsDrawSphere(pos,R,radius);    // çƒã®æç”»
}
int main (int argc, char **argv)
{
dReal x0 = 0.0, y0 = 0.0, z0 = 2.0;
dMass m1;
prepDrawStuff();
world = dWorldCreate();
dWorldSetGravity(world,0,0,-0.5);
space = dHashSpaceCreate(0); // è¡çªæ¤œå‡ºã‚¹ãƒšãƒ¼ã‚¹ã®ç”Ÿæˆ
contactgroup = dJointGroupCreate(0); //ã€€ã‚³ãƒ³ã‚¿ã‚¯ãƒˆã‚°ãƒ«ãƒ¼ãƒ—ï¼ˆæŽ¥è§¦ç‚¹ãŒæ ¼ç´ã•れる)ã®ç”Ÿæˆ
//  地é¢ã®ç”Ÿæˆ
ground = dCreatePlane(space,0,0,1,0); // 地é¢ç”¨ã‚¸ã‚ªãƒ¡ãƒˆãƒªã®ç”Ÿæˆ
// çƒã®ç”Ÿæˆl
ball.body = dBodyCreate(world);
dMassSetZero(&m1);
dMassSetSphereTotal(&m1,mass,radius);
dBodySetMass(ball.body,&m1);
dBodySetPosition(ball.body, x0, y0, z0);
ball.geom = dCreateSphere(space,radius); // 玉ジオメトリã®ç”Ÿæˆ
dGeomSetBody(ball.geom,ball.body); //  bodyã«geomをセット
dsSimulationLoop (argc,argv,352,288,&fn);
dSpaceDestroy(space); // スペースã®ç ´å£Š
dWorldDestroy (world);
return 0;
}
[/code]
オブジェクトも動力å¦è¨ˆç®—用ã®body(ボディ)ã®ä»–ã«è¡çªæ¤œå‡ºè¨ˆç®—用ã«geom(ジオメトリ)をè¨å®šã™ã‚‹å¿…è¦ãŒã‚ã‚‹ã®ã§MyObject æ§‹é€ ä½“ã§ãれらをメンãƒã¨ã—ã¦å®šç¾©ã—ã¦ã„ã¾ã™ã。
main関数ã®ä¸ã§çŽ‰ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã®geomã‚’dCreateSphere()ã§ä½œã‚Šã€dGeomSetBodyã§bodyã¨geomを関連付ã‘ã¦ã„ã¾ã™ã®ã§ã‚ªãƒ–ジェクトã®ä½ç½®ã¨å§¿å‹¢ã¯bodyã ã‘ã§è¨å®šã™ã‚Œã°OKã§ã™ã€‚ã“れをã—ãªã„ã¨å¹½ä½“離脱ç¾è±¡ã«é™¥ã£ã¦ã—ã¾ã„ã¾ã™ã€‚
è¡çªæ¤œå‡ºé–¢æ•°dSpaceCollideã¯ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®å„ステップã§å®Ÿè¡Œã•れるsimLoop関数ã®ä¸ã§å‘¼ã³å‡ºã•れã¦ã„ã¾ã™ã€‚注æ„ã™ã‚‹ç‚¹ã¨ã—ã¦ã¯ã€å¿…ãšsimLoopã®ä¸€ç•ªå§‹ã‚ã§å‘¼ã³å‡ºã—ã¦ãã ã•ã„。ã“れを後ã®ã»ã†ã«ã‚‚ã£ã¦ã„ãã¨çމãŒåœ°é¢ã‚’çªã抜ã‘ã¦ã—ã¾ã„ã¾ã™ã‚ˆã€‚dSpaceCollideã§ã¯ã‚³ãƒ¼ ルãƒãƒƒã‚¯é–¢æ•°nearCallbackを呼ã³å‡ºã—ã¦ã„ã¾ã™ã€‚31è¡Œç›®ã§æŽ¥è§¦ã™ã‚‹å¯èƒ½æ€§ã®ã‚ã‚‹ï¼’ã¤ã®ç‰©ä½“ã®ã†ã¡ã€ã©ã¡ã‚‰ã‹ãŒåœ°é¢groundãªã‚‰isGroundã‚’trueã«ã‚»ãƒƒãƒˆã—ã¾ã™ã€‚32行目ã®dCollide()ã®æˆ»ã‚Šå€¤ã¯æŽ¥è§¦ç‚¹æ•°ã§ã™ã€‚
34行目ã®if (isGround)æ–‡ã¯ï¼Œè¡çªã™ã‚‹å¯èƒ½æ€§ã®ã‚る物体ã®ã†ã¡ã©ã¡ã‚‰ã‹ãŒåœ°é¢ãªã‚‰ï¼“5行目ã‹ã‚‰ï¼”8行目ã¾ã§ã®å‡¦ç†ã‚’ã—ã¾ã™ï¼Žã¤ã¾ã‚Šï¼Œåœ°é¢ã¨ã®è¡çªä»¥å¤–ã¯è€ƒãˆã¦ã„ã¾ã›ã‚“.地é¢ä»¥å¤–ã¨ã®è¡çªã‚’考慮ã™ã‚‹å ´åˆã¯ï¼Œã“ã®if文を削除ã—ã¦ãã ã•ã„.
35行目ã§åœ°é¢ã§ã‹ã¤æŽ¥è§¦ç‚¹æ•°ãŒï¼‘以上ãªã‚‰ã€åœ°é¢ã¨æŽ¥è§¦ã—ãŸã“ã¨ã‚’示ã™flagを1ã«ã‚»ãƒƒãƒˆã—ã¦ã„ã¾ã™ã€‚
ã§ã¯ã€ã“ã“ã‹ã‚‰ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰sample2-080124.tgzをダウンãƒãƒ¼ãƒ‰ã—ã¦å®Ÿè¡Œã—ã¦ãã ã•ã„。今度ã¯åœ°é¢ã‚’çªã抜ã‘ãªã„ã¯ãšã§ã™ã€‚ 実行ã®ä»•æ–¹ã¯å‰å›žã¨ã»ã¼åŒã˜ã§ã™ã€‚sample1ã‚’sample2ã¨èªã¿æ›¿ãˆã¦ãã ã•ã„。
課題を1ã¤å‡ºã—ã¾ã™ã€‚sample2を実行ã™ã‚‹ã¨å¤§åœ°ãŒå¥½ããªã®ã‹ã©ã†ã‹ã‚ˆãã‚ã‹ã‚Šã¾ã›ã‚“ãŒãƒœãƒ¼ãƒ«ãŒã¾ã£ãŸãå¼¾ã¿ã¾ã›ã‚“。 ã“ã®å‘ªç¸›ã‚’è§£ã„ã¦ãã ã•ã„。
ã§ã¯ã€ã¾ãŸæ¬¡å›žï¼
æ›´æ–°å±¥æ´
- 2008-6-26: nearCallbackã®èª¬æ˜Žã‚’補足(赤å—).
- 2008-1-24: 接触ã—ãŸã‚‰è‰²ãŒå¤‰ã‚るよã†ã«ãƒ—ãƒã‚°ãƒ©ãƒ を変更ã—ã€æ‹¡å¼µåã‚’cppã«ã—ãŸã€‚
- 2008-1-13: ソースコードを整形ã—ãŸï¼Ž
- 2007-9-19: sample2.tgzã®makefileã‚’å¤‰æ›´ã—æ€’られãšã«æ¸ˆã‚€ã‚ˆã†ã«ã—ãŸã€‚
- 2007-1-20: 本文ã®èª¬æ˜Žã‚’より詳ã—ãã—ã€ã‚¸ã‚ªãƒ¡ãƒˆãƒªã®ç¨®é¡žã®å›³ã‚’è¿½åŠ ã¾ã—ãŸã€‚
ã¯ã˜ã‚ã¾ã—ã¦mituã§ã™
今自分ã¯å‹•力å¦ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã‚’作æˆã—ã¦ã„ã‚‹ã®ã§ã™ãŒï¼Œ
動力å¦è¨ˆç®—を自分ã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã§è¡Œã„,è¡çªè¨ˆç®—ã¯
ODEã§ã‚„りãŸã„ã¨è€ƒãˆã¦ã„ã¾ã™ï¼Ž
サンプルã§ã¯æŽ¥è§¦ç‚¹ã‹ã‚‰ã®å発力ã¯è³ªé‡ã‚’考慮ã—ã¦ã„ã‚‹ã¨
æ€ã†ã®ã§ã™ãŒï¼Œè‡ªåˆ†ã¯ã“れを質é‡ã‚’考慮ã›ãšã«æŽ¥è§¦ç‚¹ã®æ²ˆã¿
å…·åˆã‹ã‚‰è¨ˆç®—ã§ãã‚‹ã¨è€ƒãˆã¦ã„ã‚‹ã®ã§ã™ãŒï¼Œå¯èƒ½ã§ã—ょã†ã‹ï¼Ÿ
mituã•ã‚“ã€
ã¯ã˜ã‚ã¾ã—ãŸã€‚
以下ã«ã¤ã„ã¦æ•™ãˆã¦ãã ã•ã„。
1. サンプルã¨ã¯å…·ä½“çš„ã«ä½•ã§ã™ã‹ï¼Ÿã€€
2. æŽ¥è§¦ç‚¹ã®æ²ˆã¿ã¨ã¯Penetration Depthã®ã“ã¨ã§ã™ã‹ï¼Ÿ
3. ã€ŒæŽ¥è§¦ç‚¹ã®æ²ˆã¿å…·åˆã‹ã‚‰è¨ˆç®—ã§ãã‚‹ã€ã¨ã¯ã€ŒæŽ¥è§¦ç‚¹ã®æ²ˆã¿å…·åˆã‹ã‚‰å発力を計算ã§ãã‚‹ã€ã¨ã„ã†ã“ã¨ã§ã™ã‹ï¼Ÿ
4. 拘æŸåŠ›ã®è¨ˆç®—ã¯mituã•ã‚“ãŒã‚„られるã®ã§ã™ã‹ï¼Ÿãれã¨ã‚‚ODEã§ã—ょã†ã‹ï¼Ÿã€€
ã§ã‚€
mituã§ã™
サンプルã¨ã„ã†ã®ã¯çƒä½“ã®è½ä¸‹ã®ãƒ—ãƒã‚°ãƒ©ãƒ ã§ã™ï¼Ž
今自分ã¯è¡çªæ¤œå‡ºã‚’ODEã§è¡Œã£ã¦ã‚‚らã„,ãã“ã§ç”Ÿã˜ã‚‹æŽ¥è§¦åŠ›ï¼ˆè¡æ’ƒåŠ›ï¼‰
ã®è¨ˆç®—ã¯è‡ªåˆ†ã®å‹•力å¦ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã®æ–¹ã§è¡ŒãŠã†ã¨è€ƒãˆã¦ã„ã¾ã™ï¼Ž
接触力ãªã©ã¯å½¢çжãªã©ã®å‹•力å¦ã‚’考慮ã—ãªã„ã‚‚ã®ã ã‘ã§ã¯å‡ºã›ãªã„ã¨æ€ã„ã¾ã™ã®ã§ï¼Ž
ã¨ã„ã†ã“ã¨ã‚’考ãˆã¦ã„ãŸã®ã§ã™ãŒï¼ŒãŸã¶ã‚“接触力ã®è¨ˆç®—ã«é–¢ã—ã¦ã¯ãƒšãƒŠãƒ«ãƒ†ã‚£æ³•ã®
よã†ãªã‚„り方ã«ãªã‚‹ã®ã‹ã¨è€ƒãˆã¦ã„ã¾ã™ï¼Ž
ã¾ãŸï¼Œè³ªå•ãŒå¢—ãˆã‚‹ã®ã§ã™ãŒï¼Œç¾åœ¨ã¯æŽ¥è§¦ç‚¹ã®ä½ç½®ã‚„æ³•ç·šã®æƒ…å ±ã‚’ã©ã®ã‚ˆã†ã«è¿”ã›ã°
ã„ã„ã§ã—ょã†ã‹ï¼Ÿ
ä»–ã«ã‚‚,çƒä½“ã«é€Ÿåº¦ã‚’与ãˆã¦ODEã§å‹•力å¦è¨ˆç®—を行ã‚ãªã„(dWorldStep関数を使ã‚ãªã„)
å ´åˆï¼ŒæŽ¥è§¦å¾Œã®çƒä½“ã®é€Ÿåº¦ã¯è¿”ã›ã¾ã™ã‹ï¼Ÿ
ãŠè¿”事ã‚りãŒã¨ã†ã”ã–ã„ã¾ã™
ãã†ã ã£ãŸã‚“ã§ã™ã‹ã€‚知りã¾ã›ã‚“ã§ã—ãŸã€‚
ä»–ã®å½¢ã§è©¦ã—ã¦è¦‹ã¾ã™ã€‚ã‚りãŒã¨ã†ã”ã–ã„ã¾ã—ãŸã€‚
ミツルギã•ã‚“ã€
円柱プリミティブãŒå°Žå…¥ã•れãŸã®ã¯ï¼¯ï¼¤ï¼¥0.6ã‹ã‚‰ã§ã¾ã コードãŒç†Ÿæˆã—ã¦ã„ãªã„よã†ã§ã™ã€‚
ã¡ãªã¿ã«ã€å††æŸ±ã¨å††æŸ±ã€å††æŸ±ã¨ã‚«ãƒ—セルã®è¡çªæ¤œå‡ºã¯ODE0.7ã§ã‚‚ã¾ã 実装ã•れã¦ã„ã¾ã›ã‚“。è¡çªã®æ¤œå‡ºçжæ³ã¯ODE Wikiã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«(http://opende.sourceforge.net/wiki/index.php/Manual_%28Collision_Detection%29)ã‚’ã”覧ãã ã•ã„。
ã“ã®å‰ã®ã‚‚ã®ã‚’ã„ã‚ã„ã‚ã¨ã¾ãŸå¤‰ãˆã¦ã¿ãŸã®ã§ã™ãŒã‚„ã¯ã‚Šã¾ã 円柱åŒå£«ã§ã¯ã™ã‚ŠæŠœã‘ã¦ã—ã¾ã„ã¾ã™ã€‚
ãŸã デãƒãƒƒã‚¯ã—ã¦ã¿ãŸã¨ã“ã‚nearCallbackã«ã¯å††æŸ±åŒå£«ã®è¡çªã§ã‚‚å…¥ã£ã¦ã„るよã†ã§ã™ã€‚
ã‚„ã¯ã‚Šsurfaceã®ã‚ãŸã‚Šã®è¨å®šãŒãŠã‹ã—ã„ã®ã§ã—ょã†ã‹ï¼Ÿ
ã¯ã£ãりã„ã£ã¦ã“ã®è¾ºãŒã¾ã£ãŸãã‚ã‹ã‚Šã¾ã›ã‚“…よã‚ã—ããŠé¡˜ã„ã—ã¾ã™ã€‚
ãŠè¿”事ã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚
下ãŒè‡ªåˆ†ã®é–¢æ•°ã§ã™
static void nearCallback(void *data, dGeomID o1, dGeomID o2)
{
dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2);
if(b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact)) return;
static const int N = 4;
dContact contact[N];
int n = dCollide(o1,o2,N,&contact[0].geom,sizeof(dContact));
if(n>0)
{
for(int i=0;i<n;i++)
{
contact[i].surface.mode = dContactSlip1 | dContactSlip2 |
dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactBounce;
contact[i].surface.mu = dInfinity;
contact[i].surface.bounce = 0.0;
contact[i].surface.bounce_vel = 0.0;
contact[i].surface.slip1 = 0.1;
contact[i].surface.slip2 = 0.1;
contact[i].surface.soft_erp = 0.8;
contact[i].surface.soft_cfm = 1e-4;
dJointID c = dJointCreateContact(world,contactgroup,&contact[i]);
dJointAttach(c,b1,b2);
}
}
}
サンプルã¨å¤§ã—ã¦å¤‰ã‚ã£ã¦ã„ãªã„ã§ã™ã€‚片岡ã•ã‚“ã®æ›¸ãè¾¼ã¿ã‚’見ã¤ã¤å¤‰ãˆã¦ã¿ãŸã®ã§ã™ãŒã‚„ã¯ã‚Š
検出ãŒå‡ºæ¥ã¦ãªã„よã†ã§ã™ã€‚
modeã«å…¥ã‚Œã‚‹dContactSlip1ãªã©ã®æ„味ãŒã‚ã‹ã‚‰ãªã„ã¾ã¾ä½¿ã£ã¦ã„ã¾ã™ã€‚ãŠã‹ã—ã„ã®ã¯ãã®è¾ºã§ã—ょã†ã‹ï¼Ÿ
片岡ã•ã‚“ã€
æ‹¡å¼µåã‚’.cã‹.cppã«ã™ã‚‹ã‹ã§è¿·ã£ã¦ã„ã‚‹ã®ã§ã¨ã¦ã‚‚å‚考ã«ãªã‚Šã¾ã—ãŸã€‚ã©ã†ã‚‚ã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚
経緯を簡å˜ã«èª¬æ˜Žã™ã‚‹ã¨ã€ã“ã®è¬›åº§ã§ã¯å¤šãã®æ–¹ã«ç†è§£ã§ãるよã†ã«C言語ã§ãƒ—ãƒã‚°ãƒ©ãƒ を書ã„ã¦ã„ã¾ã™ã€‚ãŸã ã€99å¹´ã«æ¨™æº–化ã•れãŸC99を使ã£ã¦æ›¸ã„ã¦ã„ã‚‹ã®ã§ã‚³ãƒ³ãƒ‘ã‚¤ãƒ©ã®æ¨™æº–è¨å®šãªã‚‰ã‚¨ãƒ©ãƒ¼ãŒã§ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。gccãªã‚‰-std=c99ã®ã‚ªãƒ—ションをã¤ã‘ãªã„ã¨ã‚¨ãƒ©ãƒ¼ãŒã§ã‚‹å ´åˆãŒã‚りã¾ã™ã€‚ã¾ãŸã€æ˜¨å¹´ã€cygwinã§ã‚µãƒ³ãƒ—ルプãƒã‚°ãƒ©ãƒ を書ã„ãŸã¨ãã«g++ã§ãªã„ã¨makeãŒã©ã†ã—ã¦ã‚‚通らãªã‹ã£ãŸã®ã§ã‚³ãƒ³ãƒ‘イラã«ã¯g++を使ã£ã¦ã„ã¾ã™ã€‚コンパイラã«c++言語用ã®g++を使ã£ã¦ã„ã‚‹ã®ã§æ‹¡å¼µåã‚’.cppã«ã™ã‚‹æ–¹ãŒã™ã£ãりã™ã‚‹ã—ã€ã‚³ãƒ³ãƒ‘イル(ビルド)ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒå‡ºã‚‹ã¨åˆå¿ƒè€…ã¯é€”æ–¹ã«ãれるã®ã§.cppã«å¤‰æ›´ã—ã¦ã„ããŸã„ã¨æ€ã„ã¾ã™ã€‚
片岡ã•ã‚“ã€
VC++ã§ã®bounce_velã®åˆæœŸå€¤ã‚’調ã¹ã¦é ‚ãã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚ODEã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’èªã¿ã¾ã—ãŸãŒbounce_velã¯æ˜Žç¤ºçš„ã«åˆæœŸåŒ–ã•れã¦ã„ã¾ã›ã‚“。明示的ã«0ã§åˆæœŸåŒ–ã™ã¹ãã ã¨è€ƒãˆã¾ã™ã€‚本家ã®ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆã«ãƒã‚¹ãƒˆã—ã¦ã¿ã¾ã™ã€‚
ç´°ã‹ã„ã“ã¨ã‚’言ã£ã¦ç”³ã—訳ãªã„ã®ã§ã™ãŒã€
ODEã®VC用プãƒã‚¸ã‚§ã‚¯ãƒˆã®åˆæœŸè¨å®šã‚’使ã†ã¨ã‚µãƒ³ãƒ—ルファイルã®å½¢å¼ãŒã€Œ.cã€ã ã¨
C++ã˜ã‚ƒãªãã¦C言語ã¨èª¤èªã—ã¦ã—ã¾ã£ã¦ã‚¨ãƒ©ãƒ¼ãŒå‡ºã¦ã—ã¾ã†ã®ã§ã€Œ.cppã€ã«å¤‰ãˆã¦ãŠã„ãŸæ–¹ãŒ
VCを使ã†äººã«ã‚‚ã‚ã‹ã‚Šã‚„ã™ã„ã¨æ€ã„ã¾ã™ã€‚
ã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚
調ã¹ãŸçµæžœVC++ã§ã®bounce_velã®åˆæœŸå€¤ã¯-107374176.0fã§ã—ãŸã€‚
片岡ã•ん,
mingw(g++)ã¨Visual C++ã§ã¯ä¸€éƒ¨æŒ™å‹•ãŒç•°ãªã‚‹ã¨ã“ã‚ãŒã‚るよã†ã§ã™ã.
ã©ã†ã‚‚ã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ï¼Žã‚µãƒ³ãƒ—ルコードを修æ£ã—ã¾ã™ï¼Ž
ãªãŠï¼Œå発部分ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã¯ä»¥ä¸‹ã¨ãªã£ã¦ã„ã¦bounce_velãŒ0以上ã§ï¼Œå¤–ã«å‡ºã¦è¡Œã速度ベクトル(outgoing)ã®è² ã®å€¤ãŒbounce_velより大ãã‘れã°å発ã—ã¾ã™ï¼Ž
// from ode-0.7/ode/src/joint.cpp (l1382-1398)
// deal with bounce
if (j->contact.surface.mode & dContactBounce) {
// calculate outgoing velocity (-ve for incoming contact)
dReal outgoing = dDOT(info->J1l,j->node[0].body->lvel) +
dDOT(info->J1a,j->node[0].body->avel);
if (j->node[1].body) {
outgoing += dDOT(info->J2l,j->node[1].body->lvel) +
dDOT(info->J2a,j->node[1].body->avel);
}
// only apply bounce if the outgoing velocity is greater than the
// threshold, and if the resulting c[0] exceeds what we already have.
if (j->contact.surface.bounce_vel >= 0 &&
(-outgoing) > j->contact.surface.bounce_vel) {
dReal newc = – j->contact.surface.bounce * outgoing;
if (newc > info->c[0]) info->c[0] = newc;
}
}
mingw(g++)ã®bounce_velã®ãƒ‡ãƒ•ォルト値ã¯0ã«ãªã£ã¦ã„ã‚‹ã®ã§bounce_velを明示的ã«è¨å®šã—ãªãã¦å発ã™ã‚‹ã®ã ã¨è€ƒãˆã¦ã„ã¾ã™ï¼ŽVisual C++ã§ã¯bounce_velã®ãƒ‡ãƒ•ォルト値ã¯ã„ãらã§ã™ã‹ï¼Ÿ
以下ã®ã‚ˆã†ã«bounce_velã‚’è¨å®šã—ãªã„ã§ï¼Œãã®å€¤ã‚’調ã¹ã¦é ‚ã‘れã°ã‚りãŒãŸã„ã§ã™ï¼Ž
static void nearCallback(void *data, dGeomID o1, dGeomID o2)
{
const int N = 10;
dContact contact[N];
int isGround = ((ground == o1) || (ground == o2));
int n = dCollide(o1,o2,N,&contact[0].geom,sizeof(dContact));
if (isGround) {
for (int i = 0; i < n; i++) {
contact[i].surface.mode = dContactBounce;
contact[i].surface.bounce = 1.0; // (0.0~1.0)
printf(“bounce_vel=%f \n”,contact[i].surface.bounce_vel);
dJointID c = dJointCreateContact(world,contactgroup,&contact[i]);
dJointAttach (c,dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));
}
}
}
ç§ã®ä½¿ç”¨ã—ã¦ã„る環境ã¯(ODE0.7,Windows XP Professional, Visual C++.net Standard Ver.2003)ã§ã™ã€‚
å発ã—ãªã„ã¨è¨€ã£ã¦ã‚‚ã€è¡çªã®æ¤œå‡ºã¯ã•れã¦ã„ã¾ã™ã€‚
ã—ã‹ã—ã€å発係数を変ãˆã¦ã‚‚ã€ãã®å ´ã§åœæ¢ã—ã¦ã—ã¾ã†ã¨ã„ã†ç¾è±¡ãŒç™ºç”Ÿã—ã¾ã™ã€‚
bounce_velã«0ä»¥ä¸Šã®æ•°å€¤ã‚’入力ã™ã‚‹ã¨ã€å発係数ã«å¿œã˜ãŸå応をã¿ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã—ãŸã€‚
ミツルギã•ん,
プãƒã‚ャンプをèªã‚“ã§é ‚ãã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ï¼Žæžšæ•°ã®åˆ¶é™ã®ãŸã‚説明ãŒå分ã«ã§ããšï¼Œã‚ã‹ã‚Šã¥ã‚‰ãã‚りã¾ã›ã‚“ã‹ï¼Ÿ
ã•ã¦ï¼ŒãŠä½¿ã„ã®nearCallback関数ã ã‘を投稿ã—ã¦é ‚ã‘ã¾ã™ã‹ï¼Ÿã€€
æã‚‰ã,çƒã¨åœ°é¢ä»¥å¤–ã¯è¡çªæ¤œå‡ºã—ã¦ã„ãªã„ã®ã ã¨æ€ã„ã¾ã™ï¼Ž
ã§ã‚€
片岡ã•ん,
ç§ã®ç’°å¢ƒ(ODE0.7,Windows XP Professional, MinGW-5.0.3)ã§ã¯bounce_velã‚’è¨å®šã—ãªãã¦ã‚‚å発ã—ã¾ã—ãŸï¼Žbounce_velã¯ãŠã£ã—ゃるã¨ãŠã‚Šã§ã™ï¼Ž
環境を教ãˆã¦é ‚ã‘ã¾ã™ã‹ï¼Ÿ
ã¯ã˜ã‚ã¾ã—ã¦ã“ã‚“ã«ã¡ã¯
豊田高専ã§ï¼¯ï¼¤ï¼¥ã‚’使ã£ã¦ç ”ç©¶ã‚’ã—ã¦ã„る者ã§ã™ã€‚
ãƒãƒœã‚«ãƒƒãƒ—・プãƒã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã®ã‚µãƒ³ãƒ—ルをベースã«å††æŸ±ã®ç‰©ä½“何個ã‹ä½œã‚Šã€
速度を与ãˆã¦å‹•ã‹ã—ã¦ã„ã‚‹ã®ã§ã™ãŒã€åŒã˜å½¢çжã®å††æŸ±ç‰©ä½“åŒå£«ãŒå½“ãŸã‚‹ã¨ãã«
ã™ã‚ŠæŠœã‘ã¦ã—ã¾ã„ã¾ã™ã€‚(ãªãœã‹ãƒœãƒ¼ãƒ«ã¨ã®æŽ¥è§¦æ™‚ã¯å¤§ä¸ˆå¤«ã§ã™ï¼‰
bodyã¨geomã®æŽ¥ç¶šã¯dGeomSetBodyã§è¡Œã£ã¦ãŠã‚Šã€ç†ç”±ãŒè‡ªåˆ†ã§ã¯è¦‹å½“ãŸã‚Šã¾ã›ã‚“…。
解決方法を教ãˆã¦ã„ãŸã ã‘ãªã„ã§ã—ょã†ã‹ã€‚よã‚ã—ããŠé¡˜ã„ã—ã¾ã™ã€‚
ã¯ã˜ã‚ã¾ã—ã¦
大阪電気通信大å¦ã®å¦ç”Ÿã§ã™ã€‚
ODEã®å‹‰å¼·ã®å‚考ã«ã•ã›ã¦ã‚‚らã£ã¦ã„ã¾ã™ã€‚
ODEã®0.7ã‹ã‚‰ï¼ˆ0.7ã‹ã©ã†ã‹è©³ã—ãã¯ã‚ã‹ã‚Šã¾ã›ã‚“ãŒï¼‰ç‰©ä½“ãŒå発ã™ã‚‹ã«ã¯å発係数ã®ã»ã‹ã«
bounce_vel ã¨ã„ã†å¤‰æ•°ã«0以上をè¨å®šã—ãªã‘れã°å発ã—ãªã„よã†ã§ã™ã€‚
見ãŸã¨ã“ã‚bounce_velã¯è¡çªã—ãŸç‰©ä½“ã®é€Ÿåº¦ãŒã“ã®å€¤ã‚ˆã‚Šå°ã•ã„ã¨å発ã—ãªã„ã€æœ€ä½Žå発速度ã®ã‚ˆã†ã«æ€ã„ã¾ã™ã€‚