7. ジョイント(関節)

ODE(Open Dynamics Engine)åˆç´šè¬›åº§ã®ï¼—回目ã§ã™ã€‚今回ã¯ï¼Œãƒœãƒ‡ã‚£(剛体,body)ã‚’ä»–ã®ãƒœãƒ‡ã‚£ã¨ãã£ã¤ã‘るジョイント(関節)ã«ã¤ã„ã¦èª¬æ˜Žã—ã¾ã™ã€‚
ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¯æˆ‘々ã®å‘¨ã‚Šã§ã¯ã€æŠ˜ç•³ã¿æºå¸¯ã®ãƒ’ンジやドアã®è¶ç•ªã«ç›¸å½“ã—ã¾ã™ã€‚å°é›£ã—ãã„ã†ã¨ã€ï¼’ã¤ã®ãƒœãƒ‡ã‚£ã®ä½ç½®ã‚„姿勢をã‚る一定ã®é–¢ä¿‚ã«ä¿ã¤æ‹˜æŸãŒã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¨ãªã®ã§ã™ã€‚ODEã§ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¨æ‹˜æŸã‚’åŒã˜æ„味ã§ä½¿ã£ã¦ã„ã¾ã™ã€‚ジョイントをã†ã¾ã使ã†ã¨ç‰©ä½“ã®é‹å‹•ã‚’ç›´ç·šä¸Šã«æ‹˜æŸã•ã›ãŸã‚Šã€å††è»Œé“ã«æ‹˜æŸã•ã›ãŸã‚Šã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
- ジョイントã®ä½¿ã„æ–¹
- ***ジョイントã®ç”Ÿæˆã€€ã€€ã€€ã€€ã€€ã€€dJointCreate***()
- ***ジョイントã¨ãƒœãƒ‡ã‚£ã®çµåˆã€€ dJointAttach()
- ***ジョイントã®ä¸å¿ƒç‚¹ã‚’è¨å®šã€€dJointSet***Anchor()
- ***ジョイントã®å›žè»¢è»¸ã‚’è¨å®šã€€dJointSet***Axis()
上ã§***ã«ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ã‚¿ã‚¤ãƒ—ãŒå…¥ã‚Šã¾ã™ã€‚タイプã«ã¯Hinge(ヒンジ)ã€Ball(ボール)ã€Slider(スライダー)ã€Universal(ユニãƒãƒ¼ã‚µãƒ«)ç‰ãŒã‚りã¾ã™ã€‚詳ã—ã„ä½¿ã„æ–¹ã¯Manual(英語)やODE本をå‚ç…§ã—ã¦ãã ã•ã„。
- ジョイントã®ãƒ‘ラメータè¨å®š
- å¯å‹•域ã®è¨å®š
dJointSetHingeParam(dJointID, dParamLoStop, å¯å‹•域ã®ä¸‹é™ï¼‰;
dJointSetHingeParam(dJointID, dParamHiStop, å¯å‹•域ã®ä¸Šé™ï¼‰; - 目標角速度ã¨ãれを実ç¾ã™ã‚‹ãŸã‚ã®æœ€å¤§ãƒˆãƒ«ã‚¯ã®è¨å®š
dJointSetHingeParam(dJointID, dParamVel, 目標角速度);
dJointSetHingeParam(dJointID, dParamFMax, 最大トルク);
パラメータã¨ã—ã¦ã¯ã€é–¢ç¯€å¯å‹•域ã®ä¸‹é™ã‚’示ã™dParamLoStopã€ä¸Šé™ã‚’示ã™dParamHiStopã€è§’速度(ヒンジジョイント)ã¾ãŸã¯é€Ÿåº¦(ç›´å‹•å¼é–¢ç¯€ï¼‰ã‚’示ã™dParamVelã€æœ€å¤§ãƒˆãƒ«ã‚¯ã‚’示ã™dParaFMaxãªã©ãŒã‚りã¾ã™ã€‚ãªãŠã€ODEã§ã¯é–¢ç¯€ã«ãƒ¢ãƒ¼ã‚¿ãŒæ¨™æº–ã§çµ„ã¿è¾¼ã¾ã‚Œã¦ã„ã‚‹ã®ã§ã€dParamVelã‚„dParaFMaxを指定ã™ã‚‹ã¨é–¢ç¯€ãŒå‹•ãã¾ã™ã€‚
- サンプルプãƒã‚°ãƒ©ãƒ
ã•ã£ãã上図ã«ç¤ºã—ã¦ã„る玉ã¨å††æŸ±ã‚’ヒンジジョイントã§çµåˆã—ã¦ã„るオブジェクトãŒãƒã‚¦ãƒ³ãƒ‰ã™ã‚‹ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’以下ã«ç¤ºã—ã¾ã™ã€‚ãªãŠã€å‰å›žã¾ã§ã¨åŒã˜é–¢æ•°ã‚„宣言ã¯çœç•¥ã—ã¦ã„ã¾ã™ã€‚
// sample7.cpp by ã§ã‚€ 2006-2008
#ifdef dDOUBLE
#define dsDrawSphere dsDrawSphereD // å˜ç²¾åº¦ã¨å€ç²¾åº¦ã®æç”»é–¢æ•°ã«å¯¾å¿œã™ã‚‹ãŠã¾ã˜ãªã„ #define dsDrawCapsule dsDrawCapsuleD
#endif
typedef struct {
dBodyID body; //  ボディ(剛体)
dGeomID geom; // ジオメトリ(形状)
dReal radius, length, mass; // åŠå¾„[m]ã€ã€€é•·ã•[m]ã€ã€€è³ªé‡[kg]
} myLink;
myLink ball, pole;
// simLoopã¯ã“ã®ã‚½ãƒ¼ã‚¹ã§ã¯ã‚ã‹ã‚‰ãªã„ãŒwhileループã«å…¥ã£ã¦ã„ã¦ã€ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®å„ステップã§å®Ÿè¡Œã•れる。
static void simLoop (int pause)
{
const dReal *pos1,*R1,*pos2,*R2; // é…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ãŒä»£å…¥ã•れる
dSpaceCollide(space,0,&nearCallback);  // è¡çªæ¤œå‡ºè¨ˆç®—
dWorldStep(world,0.01); // 動力å¦è¨ˆç®—を1ステップ(ã“ã“ã§ã¯0.01秒)進ã‚ã‚‹
dJointGroupEmpty(contactgroup); //  接触点グループã®å¾Œå§‹æœ«
dsSetColor(1.0,0.0,0.0);  // 赤色ã®è¨å®š
pos1 = dBodyGetPosition(ball.body); // pos1(ä½ç½®ï¼‰ã¯é…列ã®ãƒã‚¤ãƒ³ã‚¿ãƒ¼
R1 = dBodyGetRotation(ball.body); // 回転行列ã®å–å¾—
dsDrawSphere(pos1,R1,ball.radius); // çƒã®æç”» // å††æŸ±ã®æç”»
pos2 = dBodyGetPosition(pole.body); // ä½ç½®ã®å–å¾—
R2 = dBodyGetRotation(pole.body); // å§¿å‹¢ã®å–å¾—
dsDrawCapsule(pos2,R2,pole.length,pole.radius); // ã‚«ãƒ—ã‚»ãƒ«ã®æç”»
}
// オブジェクトã®ä½œæˆ
void createBallPole() {
dMass m1;
dReal x0 = 0.0, y0 = 0.0, z0 = 2.5; //玉
ball.radius = 0.2;
ball.mass = 1.0;
ball.body = dBodyCreate(world);
dMassSetZero(&m1);
dMassSetSphereTotal(&m1,ball.mass,ball.radius);
dBodySetMass(ball.body,&m1);
dBodySetPosition(ball.body, x0, y0, z0);
ball.geom = dCreateSphere(space,ball.radius);
dGeomSetBody(ball.geom,ball.body);
//  カプセル
pole.radius = 0.025;
pole.length = 1.0;
pole.mass = 1.0;
pole.body = dBodyCreate(world);
dMassSetZero(&m1);
dMassSetCapsuleTotal(&m1,pole.mass,3,pole.radius,pole.length);
dBodySetMass(pole.body,&m1);
dBodySetPosition(pole.body, x0, y0, z0 - 0.5 * pole.length);
pole.geom = dCreateCapsule(space,pole.radius,pole.length);
dGeomSetBody(pole.geom,pole.body);
// ヒンジジョイント
joint = dJointCreateHinge(world, 0);    // ヒンジジョイントã®ç”Ÿæˆ
dJointAttach(joint, ball.body,pole.body); // 玉ã¨å††æŸ±ã®ãƒœãƒ‡ã‚£ã‚’ジョイントã§çµåˆ
dJointSetHingeAnchor(joint, x0, y0, z0 - ball.radius); // ヒンジã®ã‚¢ãƒ³ã‚«ãƒ¼(ä¸å¿ƒç‚¹ï¼‰ã‚’è¨å®š
dJointSetHingeAxis(joint, 1, 0, 0);  // ヒンジã®å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ«ã‚’è¨å®š(1,0,0)
}
int main (int argc, char **argv)
{
setDrawStuff();  // æç”»é–¢æ•°ã®è¨å®š
dInitODE(); // ODEã®åˆæœŸåŒ–
world = dWorldCreate(); // 動力å¦ãƒ¯ãƒ¼ãƒ«ãƒ‰ã®ç”Ÿæˆ
space = dHashSpaceCreate(0); // è¡çªè¨ˆç®—スペースã®ç”Ÿæˆ
contactgroup = dJointGroupCreate(0); // 接触点グループã®ç”Ÿæˆ
dWorldSetGravity(world,0,0,-9.8); // é‡åŠ›åŠ é€Ÿåº¦ã®è¨å®š
ground = dCreatePlane(space,0,0,1,0); // 地é¢ç”¨å¹³é¢ã‚¸ã‚ªãƒ¡ãƒˆãƒªã®ç”Ÿæˆ
createBallPole(); // 玉ã¨ã‚«ãƒ—セルã®ç”Ÿæˆ
dsSimulationLoop (argc,argv,352,288,&fn); // シミュレーションループ
dWorldDestroy (world); // ワールドã®ç ´å£Š
  dCloseODE(); // ODEã®çµ‚了
return 0;
}
ã“ã®ä¾‹ã§ã¯çމã¨å††æŸ±ã®ãƒœãƒ‡ã‚£ã‚’ヒンジジョイントã§çµã³ã¤ã‘ã¦ã„ã¾ã™ã€‚
ã§ã¯ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’èªã¿ã¾ã—ょã†ã€‚createBallandPall関数ã§ã¯ã¾ãšçŽ‰ã‚’ä½œã‚Šã€ãã®å¾Œã€å††æŸ±ã‚’作りã€ãれã‹ã‚‰ãƒ’ンジジョイントを dJointCreateHinge()㧠生æˆã—ã€dJointAttach()ã§ï¼’ã¤ã®ãƒœãƒ‡ã‚£ã‚’ヒンジジョイントã§çµåˆã—ã¾ã™ã€‚ãã®å¾Œã®dSetHingeAnchor()ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®å›žè»¢ä¸ 心点ã®ä½ç½®ã‚’è¨å®šã—ã€dJointSetHingeAxis()ã§å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ« ã‚’è¨å®šã—ã¾ã™ã€‚ã“ã®ä¾‹ã§ã¯å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ«ã¯(1,0,0)ãªã®ã§ï½˜è»¸æ–¹å‘ã¨ãªã‚Šã¾ã™ã€‚詳ã—ãã¯ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚’å‚照。
ã“れã§ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ç”Ÿæˆã¯çµ‚ã‚りã§ã™ã€‚sample7ã¯ç°¡å˜ã®ãŸã‚ã«ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ãƒ‘ラメータをè¨å®šã—ã¾ã›ã‚“ã§ã—ãŸãŒã€å¯å‹•åŸŸã‚„æœ€å¤§ãƒˆãƒ«ã‚¯ã€æœ€å¤§è§’速度ã®è¨å®šãªã©ã‚‚å¯èƒ½ã§ã™ã€‚ã“ã“ã‹ã‚‰ã‚µãƒ³ãƒ—ルプãƒã‚°ãƒ©ãƒ 7をダウンãƒãƒ¼ãƒ‰ã—ã¦éŠã‚“ã§ãã ã•ã„。
ãªãŠã€èª¬æ˜Žã§ã‚ã‹ã‚Šãšã‚‰ã„箇所や質å•ãŒã‚れã°ã‚³ãƒ¡ãƒ³ãƒˆã‚’投稿ã—ã¦ãã ã•ã„。
ä»Šå›žç™»å ´ã—ãŸAPI
- void dJointAttach(dJointID joint, dBodyID body1, dBodyID dBody2)
剛体body1ã¨body2ã«ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆjointã‚’å–り付ã‘ã‚‹ - dJointID dJointCreateHinge(dWorldID world, dJointGroupID)
worldã«ãƒ’ンジジョイントを生æˆã—ã€ãã®ï¼©ï¼¤ç•ªå·ã‚’è¿”ã™ã€‚dJointGroupIDã«ã¯0を入れる。 - void dJointSetHingeAnchor(dJointID joint, dReal x, dReal y, dReal z)
ヒンジジョイントã®å›žè»¢è»¸ã®ä¸å¿ƒç‚¹(x,y,z)ã‚’è¨å®šã™ã‚‹ã€‚ - void dJointSetHingeAxis(dJointID joint, dReal x, dReal y, dReal z)
ヒンジジョイントã®å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ«(x,y,z)ã‚’è¨å®šã™ã‚‹ã€‚