ODE講座16:ãƒãƒœãƒƒãƒˆã‚¢ãƒ¼ãƒ ・プãƒã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿

3関節マニピュレータã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã€€ï¼ˆã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã¯ãŸã£ãŸ100行)
ゲーム開発やãƒãƒœãƒƒãƒˆã®ç ”究者ã«ã‚‚使ã‚れã¦ã„るオープンソースã®ç‰©ç†è¨ˆç®—エンジンODE(Open Dynamics Engineã€ã‚ªãƒ¼ãƒ—ン ダイナミクスエンジン)をå¦ã¶ODE講座ã®ç¬¬ï¼‘6回目ã§ã™ã€‚
今回ã¯ä»Šã¾ã§ã®çŸ¥è˜ã‚’æ•´ç†ã™ã‚‹ãŸã‚ã«ã€ç°¡å˜ãªï¼“関節マニピュレータã®ãƒ—ãƒã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã‚’作ã£ã¦ã¿ã¾ã—ょã†ã€‚ã“れã¯ODEを使ã†ã¨ã€ŒãŸã£ãŸï¼‘ï¼ï¼è¡Œç¨‹åº¦ã§ã“ã®ã‚ˆã†ãªã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ãŒã§ãã‚‹ã‚“ã§ã™ï¼Žã€ã¨ã„ã†ãƒ—ãƒã‚°ãƒ©ãƒ ãªã®ã§è¡çªè¨ˆç®—部分ã¯çœç•¥ã—ã¦ã„ã¾ã™ï¼Žé‹å‹•å¦ã‚„逆é‹å‹•å¦ã‚’ç¿’ã£ãŸæ–¹ã¯ã“ã®ãƒãƒœãƒƒãƒˆã«å®Ÿè£…ã—ã¦ã¿ã¦ãã ã•ã„.ãƒãƒœãƒƒãƒˆãŒå‹•ãã¨ä¸æ€è°ã«ã‚ã‹ã£ãŸæ°—ã«ãªã‚‹ã‚‚ã®ã§ã™ï¼Ž
ã§ã¯ï¼Œã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’次ã«ç´¹ä»‹ã—ã¾ã—ょã†ï¼Ž
ãƒãƒœãƒƒãƒˆã¯ã‚ãƒ¼ãƒœãƒ¼ãƒ‰ã§æ“作å¯èƒ½ã§ã™ï¼Ž ãƒãƒœãƒƒãƒˆã®ç¬¬ï¼‘関節ã¯jï¼ˆå¢—åŠ ï¼‰åˆã¯f(減少)ã‚ーã§ï¼Œç¬¬ï¼’関節ã¯dåˆã¯kã‚ーã§ï¼Œç¬¬ï¼“関節ã¯såˆã¯lã‚ーã§å‹•ã‹ã—ã¾ã™ï¼Žã“れã¯ãƒ—ãƒã‚°ãƒ©ãƒ ã®command関数ã«è¨˜è¿°ã—ã¦ã„ã¾ã™ï¼Ž
éŽåŽ»ã®ODE講座をç†è§£ã•れã¦ã„ã‚‹æ–¹ã«ã¯ç°¡å˜ãªã®ã§èª¬æ˜ŽãŒã»ã¨ã‚“ã©ã„らãªã„ã¨æ€ã„ã¾ã™ï¼Žã‚ã‹ã‚‰ãªã„箇所ãŒã‚れã°ã‚³ãƒ¡ãƒ³ãƒˆã«æ›¸ã込んã§ãã ã•ã„.
[code]
// arm.cpp 3 DOF manipulator by Kosei Demura 2006
#include // ODE
#include // ODEã®æç”»ãƒ©ã‚¤ãƒ–ãƒ©ãƒª
#ifdef dDouble
#define dsDrawCapsule dsDrawCapsuleD
#endif
#define NUM 4 // リンク数(土å°å«ã‚€)
dWorldID world; // 動力å¦è¨ˆç®—世界
dBodyID link[NUM]; // リンク link[0]ã¯åœŸå°
dJointID joint[NUM]; // 関節 joint[0]ã¯åœŸå°ã¨åœ°é¢ã‚’固定
static double THETA[NUM] = { 0.0, 0.0, 0.0, 0.0}; // 関節目標角[rad]
static double l[NUM] = { 0.10, 0.90, 1.00, 1.00}; // リンク長[m]
static double r[NUM] = { 0.20, 0.04, 0.04, 0.04}; // リンクåŠå¾„[m]
// P制御
void control() {
static int step = 0; // シミュレーションã®ã‚¹ãƒ†ãƒƒãƒ—æ•°
double k1 = 10.0, fMax = 100.0; // k1:比例ゲイン, fMax:最大トルク[Nm]
printf("\r%6d:",step++);
for (int j = 1; j < NUM; j++) {
double tmpAngle = dJointGetHingeAngle(joint[j]); // ç¾åœ¨ã®é–¢ç¯€è§’[rad]
double z = THETA[j] - tmpAngle; // z: 残差=目標関節角ï¼ç¾åœ¨é–¢ç¯€è§’
dJointSetHingeParam(joint[j], dParamVel, k1*z); // 角速度ã®è¨å®š
dJointSetHingeParam(joint[j], dParamFMax, fMax); // 最大トルクã®è¨å®š
}
}
// æç”»APIã®åˆæœŸåŒ–
// ODEã®APIã¯å…¨ã¦é–¢ç¯€ã®å˜ä½ã¯[rad]ã§ã™ãŒã€drawstuffã®APIã§ã‚ã‚‹dsSetViewpointã®å¼•æ•°3次元é…列hpr[3]ã®å„è¦ç´ ã®å˜ä½ã¯[°]ã¨ãªã£ã¦ã„ã¾ã™ã€‚ã“れã ã‘é•ã†ã®ã§æ°—ã‚’ã¤ã‘ã¾ã—ょã†ï¼
void start() {
float xyz[3] = { 3.04, 1.28, 0.76}; // 視点x, y, z [m]
float hpr[3] = { -160.0, 4.50, 0.00}; // 視線(heading, pitch, roll) [°]
dsSetViewpoint(xyz,hpr); // 視点ã¨è¦–ç·šã®è¨å®š
}
// ã‚ーæ“作関数
// ã‚ーã®å…¥åŠ›ãŒã‚ã‚‹ãŸã³ã«cmdã«ã¯ãã®ã‚ーã®å€¤ãŒä»£å…¥ã•れã¾ã™ã€‚
void command(int cmd) { //
switch (cmd) {
case ‘j’: THETA[1] += 0.05; break; // jã‚ãƒ¼ãŒæŠ¼ã•れるã¨THETA[1]ã®è§’度ãŒ0.05[rad]å¢—åŠ ã™ã‚‹
case ‘f’: THETA[1] -= 0.05; break;
case ‘k’: THETA[2] += 0.05; break;
case ‘d’: THETA[2] -= 0.05; break;
case ‘l’: THETA[3] += 0.05; break;
case ’s’: THETA[3] -= 0.05; break;
}
// 目標角度ãŒé–¢ç¯€å¯å‹•域を越ãˆãªã„よã†ã«åˆ¶é™ã™ã‚‹
// 関節å¯å‹•域ã¯dJointSetHingeParam(dJointID, int parameter, dReal value)ã§ã€parameterを関節下é™ã®å ´åˆdParamLoStopã€é–¢ç¯€ä¸Šé™ã®å ´åˆã¯dParamHiStopã«è¨å®šã™ã‚‹ã€‚valueã¯ãã®å€¤ã‚’入れる。å˜ä½ã¯[rad]。
if (THETA[1] < - M_PI) THETA[1] = - M_PI; // M_PI:円周率
if (THETA[1] > M_PI) THETA[1] = M_PI;
if (THETA[2] < -2*M_PI/3) THETA[2] = - 2*M_PI/3;
if (THETA[2] > 2*M_PI/3) THETA[2] = 2*M_PI/3;
if (THETA[3] < -2*M_PI/3) THETA[3] = - 2*M_PI/3;
if (THETA[3] > 2*M_PI/3) THETA[3] = 2*M_PI/3;
}
// シミュレーションループ
// ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³å®Ÿè¡Œæ™‚ã«æ¯Žå›žå‘¼ã³å‡ºã•れã¾ã™ã€‚ソースコードã§ã¯ã‚ã‹ã‚Šã¾ã›ã‚“ãŒã€ã“ã®éƒ¨åˆ†ã¯whileループã«å…¥ã£ã¦ã„ã¾ã™ã€‚ã¾ãŸã€ã“ã“ã§ã¯è¡çªæ¤œå‡ºã«é–¢ã™ã‚‹ã‚³ãƒ¼ãƒ‰ã¯çœç•¥ã•れã¦ã„ã¾ã™ã€‚
void simLoop(int pause) {
control();
dWorldStep(world, 0.02);
// ãƒãƒœãƒƒãƒˆã®æç”»
dsSetColor(1.0,1.0,1.0); // 色ã®è¨å®š(r, g, b) å„値ã¯0~1ã€ã“ã“ã§ã¯ç™½ã«è¨å®š
for (int i = 0; i < NUM; i++ ) // ãƒãƒœãƒƒãƒˆã®ãƒªãƒ³ã‚¯ã‚’ã‚«ãƒ—ã‚»ãƒ«ã§æç”»
dsDrawCapsule(dBodyGetPosition(link[i]), dBodyGetRotation(link[i]), l[i], r[i]);
}
int main(int argc, char *argv[]) {
dsFunctions fn; // æç”»é–¢æ•°
dMass mass; // 質é‡ãƒ‘ラメータ
double x[NUM] = {0.00}, y[NUM] = {0.00}; // é‡å¿ƒä½ç½®
double z[NUM] = { 0.05, 0.50, 1.50, 2.55};
double m[NUM] = {10.00, 2.00, 2.00, 2.00}; // 質é‡
double anchor_x[NUM] = {0.00}, anchor_y[NUM] = {0.00};
double anchor_z[NUM] = { 0.00, 0.10, 1.00, 2.00} ;//回転ä¸å¿ƒ
double axis_x[NUM] = { 0.00, 0.00, 0.00, 0.00}; //回転軸
double axis_y[NUM] = { 0.00, 0.00, 1.00, 1.00};
double axis_z[NUM] = { 1.00, 1.00, 0.00, 0.00};
fn.version = DS_VERSION; fn.start = &start;
fn.step = &simLoop; fn.command = &command;
fn.path_to_textures = "../../drawstuff/textures";
world = dWorldCreate(); // 動力å¦è¨ˆç®—世界ã®ç”Ÿæˆ
dWorldSetGravity(world, 0, 0, -9.8); // é‡åŠ›è¨å®š
for (int i = 0; i < NUM; i++) { // リンクã®ç”Ÿæˆã¨è¨å®š
link[i] = dBodyCreate(world); // リンクã®ç”Ÿæˆ
dBodySetPosition(link[i], x[i], y[i], z[i]); // ä½ç½®ã®è¨å®š
dMassSetZero(&mass); // 質é‡ãƒ‘ラメータã®åˆæœŸåŒ–
dMassSetCappedCylinderTotal(&mass,m[i],3,r[i],l[i]); // リンクã®è³ªé‡è¨ˆç®—
dBodySetMass(link[i], &mass); // 質é‡ã®è¨å®š
}
// 関節ã®ç”Ÿæˆã¨è¨å®š
joint[0] = dJointCreateFixed(world, 0); // 固定関節(土å°ã¨åœ°é¢ã®å›ºå®šï¼‰
dJointAttach(joint[0], link[0], 0); // 固定関節ã®å–付ã‘
dJointSetFixed(joint[0]); // 固定関節ã®è¨å®š
for (int j = 1; j < NUM; j++) {
joint[j] = dJointCreateHinge(world, 0); // ヒンジ関節生æˆ
dJointAttach(joint[j], link[j-1], link[j]); // 関節ã®å–付ã‘
dJointSetHingeAnchor(joint[j], anchor_x[j], anchor_y[j],anchor_z[j]); //関節ä¸å¿ƒã®è¨å®š
dJointSetHingeAxis(joint[j], axis_x[j], axis_y[j], axis_z[j]); // 関節回転軸ã®è¨å®š
}
dsSimulationLoop(argc, argv, 640, 570, &fn); // シミュレーションループ
return 0;
}
[/code]
ãªãŠï¼Œãƒ—ãƒã‚°ãƒ©ãƒ arm070919.tgzã¯ã“ã“ã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰å¯èƒ½ã§ã™
動作ã•ã›ã‚‹ãŸã‚ã«ã¯mingwã¾ãŸã¯LinuxãŒå¿…è¦ã§ã™ï¼ŽéŽåŽ»ã®è¬›åº§ã‚’å‚考ã«ã—ã¦ãã ã•ã„。以下ã®è¦é ˜ã§å±•開,make,実行ã—ã¦ãã ã•ã„.
- arm070919.tgzã‚’/home/ユーザå/src/ode-0.8/myprogã®ä¸ã«ã‚³ãƒ”ーã™ã‚‹ï¼Žä¸€ç•ªæœ€å¾Œã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªåmyprogã¯åˆ¥ã®åå‰ã§ã‚‚ã‹ã¾ã„ã¾ã›ã‚“.
- 以下ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’cygwinã®ã‚¿ãƒ¼ãƒŸãƒŠãƒ«ã‚½ãƒ•トやxtermãªã©ã§å®Ÿè¡Œã™ã‚‹ï¼Ž
- cd ~/src/ode-0.8/myprog
- tar  xvzf  arm070919.tgz
- cd  arm
- make
- ./arm
ãŠã—ã¾ã„.
æ›´æ–°å±¥æ´
- 2008-1-13: ã‚³ãƒ¼ãƒ‰ã®æ•´å½¢
- 2007-9-19: makefileã®æ›´æ–°ã€‚arm070919.tgzã«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚¢ãƒƒãƒ—。
ã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ï¼Ž
å˜ç²¾åº¦ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ã¾ã—ãŸï¼Žå€ç²¾åº¦ã§ã‚„ã‚‹ã¨make
ã§ãã¾ã—ãŸï¼Ž
最近忙ã—ãã¦è¿”事ãŒé…れã¾ã—ãŸã€‚
ODEã¯å˜ç²¾åº¦ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã—ãŸãŒã€ãれã¨ã‚‚å€ç²¾åº¦ã§ã™ã‹ï¼Ÿ
一番目ã®å¼•数を(cont dReal*)ã«ã‚ャストã—ã¦ã¿ã¦ãã ã•ã„。
ダウンãƒãƒ¼ãƒ‰ã—ãŸãƒ—ãƒã‚°ãƒ©ãƒ ã‚’osxã§makeã™ã‚‹ã¨ä»¥ä¸‹ã®ã‚ˆã†ãªã‚¨ãƒ©ãƒ¼ãŒã§ã¦ã—ã¾ã„ã¾ã™ï¼Žã©ã†å¯¾å‡¦ã™ã‚Œã°ã‚ˆã„ã§ã—ょã†ï¼Ÿ
arm.cpp: In function ‘void simLoop(int)’:
arm.cpp:60: error: cannot convert ‘const dReal*’ to ‘const double*’ for argument ‘1’ to ‘void dsDrawCapsuleD(const double*, const double*, float, float)’
make: *** [arm.o] Error 1
環境ã¯ODE0.8 ibookG4ã§ã™ï¼Ž