ODE講座8:関節(ジョイント)を動ã‹ãーï¼

一昨年,レーザーラモンHGã•ã‚“ã¯å°å¦ç”Ÿã«äººæ°—ãŒã‚ã£ãŸãã†ã§ã™ãŒä»Šã¯ãã®ãƒ–ームをéŽãŽãƒ†ãƒ¬ãƒ“ã§ã‚‚ã‚ã¾ã‚Šå§¿ã‚’見ã‹ã‘ãªããªã‚Šã—ãŸï¼ŽåŽŸã‚†ãŸã‹å…ˆç”Ÿã®æ€ªå‚‘ゾãƒãƒªã‚‚一昨年ã¾ã§ã®å‹¢ã„ã¯å°‘ã—失速ã—,オヤジギャグをã‹ã¾ã™å°å¦ç”Ÿã¯ã™ã£ã‹ã‚Šå½±ã‚’潜ã‚,ç§ã®ã‚ˆã†ãªã‚ªãƒ¤ã‚¸é”ãŒæ„›å¥½ã™ã‚‹æœ¬æ¥ã®å§¿ã«æˆ»ã‚Šã¾ã—ãŸï¼Žã“ã®ã‚ˆã†ã«æµè¡Œã¯å»ƒã‚Œã‚‹ã®ã‚‚æ—©ã„ã§ã™ãŒï¼ŒODEã¯ã¾ã™ã¾ã™ãƒ¦ãƒ¼ã‚¶ã‚’拡大ã—ã¦ã„ã¾ã™ï¼Ž
ゲーム開発やãƒãƒœãƒƒãƒˆã®ç ”究者ã«ã‚‚使ã‚れã¦ã„るオープンソースã®ç‰©ç†è¨ˆç®—エンジンODE(Open Dynamics Engineã€ã‚ªãƒ¼ãƒ—ン ダイナミクスエンジン)をå¦ã¶ODE講座ã®ç¬¬ï¼˜å›žç›®ã§ã™ã€‚
今回ã¯é–¢ç¯€ï¼ˆã‚¸ãƒ§ã‚¤ãƒ³ãƒˆï¼‰ã®å‹•ã‹ã—方をå¦ã³ã¾ã—ょã†ã€‚
ジョイントã¯ä»¥ä¸‹ã®æ‰‹é †ã¨APIを使ã£ã¦å‹•ã‹ã—ã¾ã™ã€‚
- ジョイントã®å¯å‹•域をè¨å®šã™ã‚‹
dJointSetHingeParam(dJointID joint_no, dParamLoStop);
dJointSetHingeParam(dJointID joint_no, dParamHiStop);
joint_noã«ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ID番å·ã€dParamLoStopã¯é–¢ç¯€ã®å¯å‹•域ã®ä¸‹é™[rad]ã€dParamHiStopã¯å¯å‹•域ã®ä¸Šé™[rad]。 - ジョイントã®ç›®æ¨™è§’速度ã¨ãれを実ç¾ã™ã‚‹ãŸã‚ã®æœ€å¤§ãƒˆãƒ«ã‚¯ã‚’è¨å®šã™ã‚‹
dJointSetHingeParam(dJointID, dParamVel);
dJointSetHingeParam(dJointID, dParamFMax)
dParamVelã¯é–¢ç¯€ã®ç›®æ¨™è§’速度[rad]/s](直動å¼é–¢ç¯€ã®å ´åˆã¯é€Ÿåº¦[m/s])ã€dParamFMaxã¯ãã®é€Ÿåº¦ã‚’锿ˆã™ã‚‹ãŸã‚ã«ç™ºæ®ã™ã‚‹ãƒˆãƒ«ã‚¯[Nm](直動å¼é–¢ç¯€ã®å ´åˆã¯åŠ›[N])。
㪠ãŠï¼ŒODEã§ã¯é–¢ç¯€ã®ç›®æ¨™è§’度を直接指定ã™ã‚‹APIãŒã‚りã¾ã›ã‚“ã®ã§ï¼Œç›®æ¨™è§’度ã«é–¢ç¯€è§’ã‚’ã‚‚ã£ã¦ã„ããŸã‚ã«ã¯ï¼Œç¾åœ¨ã®é–¢ç¯€è§’ã‚’ dJointGetHingeAngleã§å–å¾—ã—,ãã®è§’度ã«ãªã‚‹ã¾ã§dJointSetHingeParamを使ã£ã¦è§’速度を関節ã«ä¸Žãˆï¼Œç›®æ¨™è§’度㫠ãªã£ãŸã‚‰è§’速度をï¼ã«ã™ã‚‹ã¨ã„ã†æ–¹æ³•を使ã„ã¾ã™ï¼Ž
ã§ã¯ï¼Œã‚½ãƒ¼ スコードを以下ã«ç¤ºã—ã¾ã™ã€‚å‰å›žã¨ã®é•ã„ã¯ã‚ªãƒ–ジェクトを胴体(torso)ã€ä¸Šè…¿ã€ä¸‹è…¿ã‚’ã‚‚ã¤ï¼‘本足ãƒãƒœãƒƒãƒˆMonoBotã«å¤‰æ›´ã—ã¦ã„ã¾ã™ã€‚自由度㯠腰関節(hip joint)ãŒï¼‘ã€è†é–¢ç¯€(knee joint)ãŒï¼‘ã®è¨ˆï¼’自由度ã¨ãªã£ã¦ã„ã¾ã™ãŒã€ä»Šå›žã¯è…°é–¢ç¯€ã ã‘å‹•ã‹ã—ã¾ã™ã€‚
[code]
// sample4.c by by ã§ã‚€
#ifdef dDOUBLE
#define dsDrawSphere dsDrawSphereD // å˜ç²¾åº¦ã¨å€ç²¾åº¦ã®æç”»é–¢æ•°ã«å¯¾å¿œã™ã‚‹ãŠã¾ã˜ãªã„
#define dsDrawCapsule dsDrawCapsuleD
#endif
myLink torso,leg[2];
dJointID joint[2];
enum jointNo {
HIP,
KNEE
};
// ジョイントã®åˆ¶å¾¡
void control()
{
double velCoeff = 1.0; // 比例定数
double p; ç¾åœ¨ã®é–¢ç¯€è§’度
static double angle = 0.5 * M_PI; // M_PIã¯å††å‘¨çއ
p = dJointGetHingeAngle(joint[HIP]); // ç¾åœ¨ã®é–¢ç¯€è§’度ã®å–å¾—
dReal z = angle - p;            // angleã¯ç›®æ¨™è§’度[rad]
if (p > 0.25 * M_PI) angle = - 0.25 * M_PI; // 目標角度ã®ä¸‹é™
if (p < - 0.25 * M_PI) angle = 0.25 * M_PI; // 目標角度ã®ä¸Šé™
dJointSetHingeParam(joint[HIP], dParamVel, velCoeff*z); // 目標角速度[rad/s]ã®è¨å®š
dJointSetHingeParam(joint[HIP], dParamFMax, 100);  // 最大トルク[Nm]ã®è¨å®š
}
static void simLoop (int pause)
{
const dReal *pos1,*R1,*pos2,*R2;
time++;
control();                   // ジョイントã®åˆ¶å¾¡
dSpaceCollide(space,0,&nearCallback); // è¡çªæ¤œå‡ºè¨ˆç®—
dWorldStep(world,0.01);         // 動力å¦è¨ˆç®—
dJointGroupEmpty(contactgroup);   // è¡çªæ¤œå‡ºè¨ˆç®—ã®å¾Œå§‹æœ«ï¼ˆæŽ¥è§¦ç‚¹ã‚°ãƒ«ãƒ¼ãƒ—ã®è§£æ”¾ï¼‰
// draw a torso 胴体をæç”»
dsSetColor(1.0,0.0,0.0);            // 色ã®è¨å®š(r, g, b) ã“ã“ã§ã¯èµ¤
pos1 = dBodyGetPosition(torso.body);  // ä½ç½®ã®å–å¾—
R1 = dBodyGetRotation(torso.body);   // 回転行列ã®å–å¾—
dsDrawSphere(pos1,R1,torso.radius); // çƒã®æç”»
// draw legs 脚をæç”»
for (int i = 0; i< 2; i++) {
pos2 = dBodyGetPosition(leg[i].body);
R2 = dBodyGetRotation(leg[i].body);
dsDrawCapsule(pos2,R2,leg[i].length,leg[i].radius);  // ã‚«ãƒ—ã‚»ãƒ«ã®æç”»
}
}
//  Create a monobot 一本足ãƒãƒœãƒƒãƒˆã®ç”Ÿæˆ
void createMonoBot()
{
dMass m1;
dReal x0 = 0.0, y0 = 0.0, z0 = 2.5;
// torso 胴体
torso.radius = 0.2;    // åŠå¾„[m]
torso.mass = 10.0; // 質é‡[kg]
torso.body = dBodyCreate(world);
dMassSetZero(&m1);
dMassSetSphereTotal(&m1,torso.mass,torso.radius);
dBodySetMass(torso.body,&m1);
dBodySetPosition(torso.body, x0, y0, z0);
torso.geom = dCreateSphere(space,torso.radius);
dGeomSetBody(torso.geom,torso.body);
// legs 上腿ã€ä¸‹è…¿
for (int i = 0; i < 2; i++) {
leg[i].radius = 0.025; leg[i].length = 0.5;  leg[i].mass = 1.0;
leg[i].body = dBodyCreate(world);
dMassSetZero(&m1);
dMassSetCapsuleTotal(&m1,leg[i].mass,3,leg[i].radius,leg[i].length);
dBodySetMass(leg[i].body,&m1);
dBodySetPosition(leg[i].body, x0, y0, z0 -torso.radius
- 0.5 * (2 * i + 1) *leg[i].length);
leg[i].geom = dCreateCapsule(space,leg[i].radius,leg[i].length);
dGeomSetBody(leg[i].geom,leg[i].body);
}
// hip joint 腰関節
joint[HIP] = dJointCreateHinge(world, 0);
dJointAttach(joint[HIP], torso.body,leg[0].body);
dJointSetHingeAnchor(joint[HIP], x0, y0, z0 - torso.radius);
dJointSetHingeAxis(joint[HIP], 1, 0, 0);
dJointSetHingeParam(joint[HIP], dParamLoStop, -0.25 * M_PI); // å¯å‹•域è¨å®š 下é™
dJointSetHingeParam(joint[HIP], dParamHiStop, 0.25 * M_PI); // 上é™ã€€å˜ä½ã¯radian
// knee joint è†é–¢ç¯€
joint[KNEE] = dJointCreateHinge(world, 0);
dJointAttach(joint[KNEE],leg[0].body,leg[1].body);
dJointSetHingeAnchor(joint[KNEE], x0, y0, z0 - torso.radius - leg[0].length);
dJointSetHingeAxis(joint[KNEE], 1, 0, 0);
dJointSetHingeParam(joint[KNEE], dParamLoStop, 0.0 * M_PI); // å¯å‹•域
dJointSetHingeParam(joint[KNEE], dParamHiStop, 0.0 * M_PI); // M_PIã¯å††å‘¨çŽ‡Ï€ï¼ˆãƒ‘ã‚¤ï¼‰
}
int main (int argc, char **argv)
{
setDrawStuff();
world = dWorldCreate();
space = dHashSpaceCreate(0);
contactgroup = dJointGroupCreate(0);
dWorldSetGravity(world,0,0,-9.8);
ground = dCreatePlane(space,0,0,1,0);
createMonoBot(); // 一本足ãƒãƒœãƒƒãƒˆã®ç”Ÿæˆ
dsSimulationLoop (argc,argv,352,288,&fn);
dWorldDestroy(world);
return 0;
}
[/code]
ジョ イントを動ã‹ã—ã¦ã„る関数controlã¯ç›®æ¨™å€¤ã¨ç¾åœ¨å€¤ã®å·®ã«æ¯”例ã—ã¦åˆ¶å¾¡ã™ã‚‹ï¼°åˆ¶å¾¡ã¨ ãªã£ã¦ã„ã¾ã™ã€‚ジョイントã®ãƒ‘ラメータdParamVelã¯ç›®æ¨™è§’速度ã§ã€dParamFMaxã¯ãã®è§’速度を実ç¾ã™ã‚‹ãŸã‚ã«ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆãŒç™ºæ®ã§ãる最大 トルクã§ã™ã€‚ã“ã®å€¤ã‚’ï¼ã«è¨å®šã™ã‚‹ã¨ç›®æ¨™è§’速度をè¨å®šã—ã¦ã‚‚トルクãŒï¼ãªã®ã§ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¨ã¯å‹•ã„ã¦ãれã¾ã›ã‚“。
ã“ã“ã‹ã‚‰sample4.cã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦éŠã‚“ã§ãã ã•ã„。ã§ã¯ã€ã¾ãŸæ¬¡å›žã€‚
æ›´æ–°å±¥æ´
- 2008-1-13: コードを整形ã—ãŸï¼Ž
- 2007-1-14: サンプルプãƒã‚°ãƒ©ãƒ ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’より詳ã—ãã—ãŸã€‚
ã§ã‚€ã•ã‚“ã€ã”返信ã‚りãŒã¨ã†å¾¡åº§ã„ã¾ã—ãŸã€‚
PARTã”ã¨ã«åˆ†ã‘よã†ã¨ã€ãƒ•ォルダã«åŒºåˆ‡ã‚ã†ã¨æ–°ã—ã„フォルダを
作æˆã—ãŸã®ãŒåŽŸå› ã§ã—ãŸã€‚
自分ãªã‚Šã«èª¿ã¹ã¾ã—ã¦ã€æ–°ã—ã„フォルダã«ã‚‚対応ã§ãるよã†ã«
ä¿®æ£ã—ã¾ã—ãŸã€‚
æ‚©ã‚ã‚‹åˆå¿ƒè€…ã•ã‚“ã€
以下ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãªã®ã§drawstuff.hã®å ´æ‰€ãŒåˆ†ã‹ã‚‰ãªã„よã†ã§ã™ã€‚æã‚‰ãファイルを解å‡ã—ãŸå ´æ‰€ãŒæ‚ªã„ã®ã ã¨æ€ã„ã¾ã™ã€‚サンプルプãƒã‚°ãƒ©ãƒ ã¯æ£ã—ã„å ´æ‰€ã«ç½®ã‹ãªã„ã¨ã‚³ãƒ³ãƒ‘イルã§ããªã„ã®ã§æ³¨æ„ã—ã¦ãã ã•ã„。
sample4.cpp:7:33: drawstuff/drawstuff.h: No such file or directory
次ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«è§£å‡ã—ã¦ãã ã•ã„。
c:\msys\1.0\home\ユーザå\src\ode-ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·\myprog
è§£å‡ã—ãŸã‚‰ä»¥ä¸‹ã®ãƒ•ァイルãŒã‚ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。ã‚ã‚Œã°æ£ã—ã„å ´æ‰€ã«è§£å‡ã§ãã¦ã„ã¾ã™ã€‚
c:\msys\1.0\home\ユーザå\src\ode-ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·\myprog\sample4\sample4.cpp
ã§ã‚€
ã§ã‚€ã•ã‚“ã€ã“ã‚“ã«ã¡ã‚
上記ã®ãƒ•ァイルをコンパイルã—ã¾ã—ãŸãŒä»¥ä¸‹ã®ã‚¨ãƒ©ãƒ¼ãŒå‡ºã¦ãã¾ã—ãŸã€‚
g++ -Wall -fno-exceptions -fno-rtti -g -DWIN32 -c sample4.cpp -L../../drawst
uff/src -L/usr/X11R6/lib -L/usr/local/lib -L/usr/lib/w32api/lib -I. -I../../inc
lude -I/usr/X11R6/include -I/usr/include -I/usr/include/w32api/include
sample4.cpp:7:33: drawstuff/drawstuff.h: No such file or directory
sample4.cpp:18: error: ‘dsFunctions’ is used as a type, but is not defined as a
type.
sample4.cpp: In function `void simLoop(int)’:
sample4.cpp:84: error: `dsSetColor’ undeclared (first use this function)
sample4.cpp:84: error: (Each undeclared identifier is reported only once for
each function it appears in.)
sample4.cpp:89: error: `dsDrawSphereD’ undeclared (first use this function)
sample4.cpp:95: error: `dsDrawCapsuleD’ undeclared (first use this function)
sample4.cpp: In function `void start()’:
sample4.cpp:103: error: `dsSetViewpoint’ undeclared (first use this function)
sample4.cpp: In function `void prepDrawStuff()’:
sample4.cpp:107: error: `fn’ undeclared (first use this function)
sample4.cpp:107: error: `DS_VERSION’ undeclared (first use this function)
sample4.cpp: In function `int main(int, char**)’:
sample4.cpp:190: error: `dsSimulationLoop’ undeclared (first use this function)
make: *** [sample4.o] Error 1
ç§ã®äºˆæƒ³ã§ã¯ä½•ã‹é–¢æ•°å†…ã§ã‚¨ãƒ©ãƒ¼ãŒã—ょã†ã˜ã¦ã‚‹ã®ã§ã¯ãªã„ã§ã—ょã†ã‹ï¼Ÿ
自分ãªã‚Šã«è€ƒãˆã¾ã—ãŸãŒç”ãˆãŒè¦‹ã¤ã‹ã‚‰ãªã‹ã£ãŸã®ã§ã€ã‚ˆã‚ã—ã‘ã‚Œã°æ•™ãˆã¦ã‚‚らãˆãªã„ã§ã—ょã†ã‹ï¼Ÿ
ãŠãらã該当ã™ã‚‹ã®ã¯ã“ã®è¬›åº§ã§ã¯ç„¡ã„ã‹ã¨æ€ã„ã€
ã“ã“ã«è³ªå•ã•ã›ã¦ã„ãŸã ãã¾ã™ã€‚
以å‰ã¯ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ä¸ã«æç”»ã—ãªã„方法を教ãˆã¦é ‚ãã€
本当ã«ã‚りãŒã¨ã†ã”ã–ã„ã¾ã—ãŸã€‚
ã„ã¾ODEを用ã„ã¦ã€è…°ã€è†ã€è¸ã®3関節ã¨
上腿ã€ä¸‹è…¿ã€è¶³ã®3関節ã‹ã‚‰ãªã‚‹ãƒ’トã®è„šã‚’模ã—ãŸ
力å¦ãƒ¢ãƒ‡ãƒ«ã‚’作æˆã—ã€é‹å‹•ã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’行ã£ã¦ã„ã‚‹ã®ã§ã™ãŒã€
å„関節ã«åˆæœŸè§’速度をè¨å®šã™ã‚‹æ–¹æ³•ãŒåˆ†ã‹ã‚‰ãªãã¦å›°ã£ã¦ã„ã¾ã™ã€‚
dJointSetHingeParam(joint, dParamVel, 値);
ã¨ã„ã†é–¢æ•°ã§è¨å®šã§ãã‚‹ã®ã‹ã¨æ€ã£ãŸã®ã§ã™ãŒã€
ODE本やã“ã®ã‚µã‚¤ãƒˆã‚’見るã¨ã€Œç›®æ¨™è§’速度ã€ã¨è¨˜è¿°ãŒæœ‰ã‚Šã€
ã©ã†ã‚„ら求ã‚ã¦ã„ã‚‹ã€åˆæœŸè§’速度ã®è¨å®šã§ã¯ç„¡ã„よã†ã§ã€
ã©ã®ã‚ˆã†ã«è¨å®šã—ãŸã‚‰è‰¯ã„ã‹åˆ†ã‹ã‚Šã¾ã›ã‚“。
é‹å‹•途ä¸ã®ä¸€éƒ¨åˆ†ã‚’抜ã出ã—ã¦ã€
ãã®éƒ¨åˆ†ã«å¯¾ã—シミュレーションを行ã£ã¦ã„ã‚‹ã®ã§ã€
åˆæœŸé€Ÿåº¦(åŠ é€Ÿåº¦)ãŒè¨å®šã§ããªã„ã¨ã€
æ£ç¢ºãªã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒå‡ºæ¥ã¾ã›ã‚“。
ã‚‚ã—よã‚ã—ã‘れã°ã€è¨å®šæ–¹æ³•ã‚’æ•™ãˆã¦ã„ãŸã ã‘ãªã„ã§ã—ょã†ã‹ã€‚