ODE講座24:AMOTORã¯ã‚¨ãƒ¼(良ã„)モータ

図:2リンク機構ã«åˆæœŸè§’速度を与ãˆã‚‹ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³
CohCohã•ã‚“ã®ã”質å•ã§åˆæœŸã®é–¢ç¯€è§’速度ã®è¨å®šæ³•ãŒã‚りã¾ã—ãŸã®ã§ã€ä¹…ã—ã¶ã‚Šã«ODE(Open Dynamics Engine)講座を開講ã—ã¾ã™ã€‚
ODEã§ã¯é–¢ç¯€ã«ãƒ¢ãƒ¼ã‚¿ãŒæ¨™æº–ã§ä»˜å±žã—ã¦ã„ã¾ã™ãŒã€é–¢ç¯€è§’速度をè¨å®šã—よã†ã¨ã—ã¦ã‚‚ã€ç›®æ¨™è§’速度ã«åˆ°é”ã™ã‚‹ã¾ã§æ™‚é–“ãŒã‹ã‹ã‚Šã¾ã™ã—ã€ãã®è§’é€Ÿåº¦ã‚’ç¶æŒã™ã‚‹ãŸã‚ã«ã¯ãれãªã‚Šã®åˆ¶å¾¡ãŒå¿…è¦ã§ã™ã€‚ç¾å®Ÿã®ãƒ¢ãƒ¼ã‚¿ã‚’å˜ç´”ã«ãƒ¢ãƒ‡ãƒ«åŒ–ã—ãŸã‚‚ã®ã§ã™ã€‚
ã“れã§ã¯ã€åˆæœŸè§’速度をè¨å®šã§ãã¾ã›ã‚“。ã“ã®å•題を解決ã™ã‚‹æ–¹æ³•ã¨ã—ã¦ã€ODEã«ã¯ç†æƒ³çš„ãªAMOTORãŒã‚りã¾ã™ã€‚マニュアルã§ã¯ï¼‘ステップã§ç›®æ¨™è§’速度ã«åˆ°é”ã™ã‚‹ã¨ã‚りã¾ã™ãŒã€é–¢ç¯€ã«ä¸Žãˆã‚‹æœ€å¤§ãƒˆãƒ«ã‚¯dParamFmaxã®å€¤ãŒ0ã ã¨ç›®æ¨™è§’速度ã«åˆ°é”ã—ã¾ã›ã‚“。ã¾ãŸã€å°ã•ãªå€¤ã®å ´åˆã¯ã€ç›®æ¨™è§’速度ã«åˆ°é”ã™ã‚‹ã¾ã§æ•°ã‚¹ãƒ†ãƒƒãƒ—ã‹ã‹ã‚‹ã“ã¨ã‚’確èªã—ã¾ã—ãŸã€‚
ãã“ã§ã€å分大ããªå€¤ã‚’è¨å®šã—ã¦ãã ã•ã„。以下ã®ã‚µãƒ³ãƒ—ルプãƒã‚°ãƒ©ãƒ ã§ã¯ç›®æ¨™è§’速度dParamVelã«ç„¡é™å¤§dInifinityを与ãˆã¦ã„ã¾ã™ã€‚
ã¾ãŸã€åˆæœŸè§’速度ã ã‘与ãˆãŸã„å ´åˆã¯ã€è§’速度ãŒç›®æ¨™å€¤ã«åˆ°é”ã—ãŸã‚‰ã€dJointDestroy()ã§amotorã‚’ç ´å£Šã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ã“れを忘れるã¨å¸¸ã«è§’速度ã¯ç›®æ¨™è§’速度ã®ã¾ã¾ã§ã™ã€‚amotorã‚’ç ´å£Šã—ãŸããªã„å ´åˆã¯ã€dJointSetAMotorNumAxes(amotor, 0)ã§åˆ¶å¾¡ã™ã‚‹è»¸æ•°ã‚’ï¼ã«è¨å®šã—ã€ç„¡åŠ¹åŒ–ã—ã¦ã‚‚OKã§ã™ã€‚
次ã«ã€APIを紹介ã—ã¾ã™ã€‚
dJointID dJointCreateAMotor(dWorldID, dJointGroupID);
AMOTORã®ç”Ÿæˆã€‚void dJointSetAMotorMode(dJointID, int mode);
AMOTORã®ãƒ¢ãƒ¼ãƒ‰è¨å®šã€‚modeã¯ãƒ¦ãƒ¼ã‚¶ãŒç‹¬è‡ªã«è¨å®šã™ã‚‹dAMotorUserã¾ãŸã¯ã€è‡ªå‹•çš„ã«ã‚ªã‚¤ãƒ©ãƒ¼è§’ãŒè¨ˆç®—ã•れるdAMotorEulerã®ï¼’ã¤ã®ãƒ¢ãƒ¼ãƒ‰ãŒã‚る。void dJointSetAMotorNumAxes(dJointID, int num);
AMOTORã§ã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ«ã•れる軸数をè¨å®šã™ã‚‹ã€‚numã®å€¤ã¯0ã‹ã‚‰3ã¾ã§ã§ã€0ã®å ´åˆã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã‚’無効化ã™ã‚‹ã€‚dAMotorEulerモードã®å ´åˆã¯è‡ªå‹•çš„ã«3ãŒè¨å®šã•れる。void dJointSetAMotorAxis (dJointID, int anum, int rel, dReal x, dReal y, dReal z);
AMOTORã®å›žè»¢è»¸ã‚’è¨å®šã™ã‚‹ã€‚引数anumã¯å¤‰æ›´ã™ã‚‹è»¸(0, 1, 2)ã€relã¯ä»¥ä¸‹ã®ç›¸å¯¾å›žè»¢ãƒ¢ãƒ¼ãƒ‰ã‚’è¨å®šã™ã‚‹ã€‚最後ã®(x,y,z)ã¯å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ«ã€‚
- 0: 軸ã¯çµ¶å¯¾åº§æ¨™ç³»ã«å›ºå®š
- 1: 1番目ã®ãƒœãƒ‡ã‚£ã«å›ºå®š
- 2: 2番目ã®ãƒœãƒ‡ã‚£ã«å›ºå®š
void dJointSetAMotorParam (dJointID, int parameter, dReal value);
AMOTORã®ãƒ‘ラメータをè¨å®šã™ã‚‹ã€‚ parameterã«ã¤ã„ã¦ã¯ä»–ã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¨åŒã˜ã€‚ã“ã®ä¾‹ã§ã¯è§’速度(スライダージョイントã®å ´åˆã¯é€Ÿåº¦ï¼‰dParamVelã€æœ€å¤§ç™ºæ®ãƒˆãƒ«ã‚¯dParamFMaxを使用ã—ãŸã€‚
AMOTORã¯Angular Motorã®ç•¥ã§ã™ãŒã€ã‚¨ãƒ¼ï¼ˆè‰¯ã„)モータã§ã™ã。ソースコードを以下ã«ç¤ºã—ã¾ã™ã®ã§è©¦ã—ã¦ãã ã•ã„。
ãªãŠã€ç°¡å˜ã«ã™ã‚‹ãŸã‚ã«è¡çªæ¤œå‡ºæ©Ÿèƒ½ã¯å®Ÿè£…ã•れã¦ã„ã¾ã›ã‚“。ã“ã“ã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰å¯èƒ½ã§ã™(amotor2-080115.tgz)。
[code]
// 2008-1-15
// amotor2.c: 2 Links with an amotor by Kosei Demura
#include
#include
#include
#include
#define NUM 2
#ifdef dDOUBLE
#define dsDrawCylinder dsDrawCylinderD
#endif
dWorldID world;
dSpaceID space;
dGeomID ground;
dJointID joint[NUM], amotor;
dsFunctions fn;
typedef struct {
dBodyID body;
dGeomID geom;
} MyLink;
MyLink rlink[NUM];
void createArm()
{
dReal init_avel = 1.0; // åˆæœŸè§’速度[rad/s]
dMass mass;
dReal x[] = { 0.00, 0.00}, y[] = { 0.00, 0.00}, z[]= { 0.75 ,0.25}; // é‡å¿ƒ
dReal length[] = { 0.50, 0.50}; // リンク長
dReal weight[] = { 1.00, 1.00}; // 質é‡
dReal r[] = { 0.02, 0.02}; // åŠå¾„
dReal anchor_x[] = { 0.00, 0.00}; // 回転軸ä¸å¿ƒ
dReal anchor_y[] = { 0.00, 0.00};
dReal anchor_z[] = { 1.00, 0.50};
dReal axis_x[] = { 1.00, 1.00}; // 回転軸ベクトル
dReal axis_y[] = { 0.00, 0.00};
dReal axis_z[] = { 0.00, 0.00};
// リンクã®ç”Ÿæˆ
for (int i = 0; i < NUM; i++) {
rlink[i].body = dBodyCreate(world);
dBodySetPosition(rlink[i].body, x[i], y[i], z[i]);
dMassSetZero(&mass);
dMassSetCylinderTotal(&mass,weight[i],3,r[i],length[i]);
dBodySetMass(rlink[i].body, &mass);
rlink[i].geom = dCreateCylinder(space,r[i],length[i]);
dGeomSetBody(rlink[i].geom,rlink[i].body);
}
//ジョイントã®ç”Ÿæˆã¨çµåˆ
for (int j = 0; j < NUM; j++) {
joint[j] = dJointCreateHinge(world, 0);
// リンク1ã¯joint[0]ã«ã‚ˆã‚Šé™çš„環境0ã¨çµåˆ
if (j == 0) dJointAttach(joint[0], rlink[0].body, 0);
else dJointAttach(joint[j], rlink[j].body, rlink[j-1].body);
dJointSetHingeAnchor(joint[j], anchor_x[j], anchor_y[j], anchor_z[j]);
dJointSetHingeAxis(joint[j], axis_x[j], axis_y[j],axis_z[j]);
}
// リンク1ã¨ãƒªãƒ³ã‚¯2ã‚’çµåˆã—ã¦ã„るジョイントをå¯å‹•域è¨å®š
dJointSetHingeParam(joint[1], dParamLoStop, -0.0 * M_PI); // å¯å‹•域ã®ä¸‹é™
dJointSetHingeParam(joint[1], dParamHiStop, 0.0 * M_PI); // å¯å‹•域ã®ä¸Šé™
// amotorã®ç”Ÿæˆ
amotor = dJointCreateAMotor(world, 0); // AMotorã®ç”Ÿæˆ
dJointAttach(amotor, rlink[0].body, 0); // AMotorã¨ãƒªãƒ³ã‚¯ã¨ã®çµåˆ
dJointSetAMotorMode(amotor, dAMotorUser); // ユーザモードã«è¨å®šã€ãƒ‡ãƒ•ォルトã€çœç•¥å¯
dJointSetAMotorNumAxes(amotor, 1); // AMotorã§ã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ«ã™ã‚‹è»¸æ•°
// 軸ã®è¨å®šï¼šå›žè»¢è»¸0を絶対座標系ã«å›ºå®šã€å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ«ã¯(1, 0, 0)
dJointSetAMotorAxis(amotor, 0 /*軸0*/, 0 /*絶対座標系ã«å›ºå®š*/, 1 /*xæˆåˆ†*/, 0 /*yæˆåˆ†*/, 0 /*zæˆåˆ†*/);
// amotorã®è¨å®š, åˆæœŸè§’速度をinit_avelã«è¨å®š
dReal fmax = dInfinity; // ç„¡é™å¤§
dJointSetAMotorParam(amotor, dParamVel, init_avel);
dJointSetAMotorParam(amotor, dParamFMax, fmax);
}
void drawLink()
{
dReal r,length;
for (int i = 0; i < NUM; i++ ) {
if (i == 1) dsSetColor(1.3, 1.3, 0.0);
else dsSetColor(0.0, 0.0, 1.3);
dGeomCylinderGetParams(rlink[i].geom, &r,&length);
dsDrawCylinder(dBodyGetPosition(rlink[i].body),
dBodyGetRotation(rlink[i].body),length,r);
}
}
void start()
{
float xyz[3] = { 2, 0, 1};
float hpr[3] = {-180, 0, 0.0};
dsSetViewpoint(xyz,hpr);
}
// ç°¡å˜ã«ã™ã‚‹ãŸã‚è¡çªæ¤œå‡ºã¯æœªå®Ÿè£…
void simLoop(int pause)
{
static int step = 0;
drawLink();
const dReal ang_rate = dJointGetHingeAngleRate(joint[0]);
printf("step=%4d: angle rate=%8.6f \n", step, ang_rate);
dWorldStep(world, 0.001);
dReal k1 = 0.0; // 摩擦トルク用比例係数 è² å€¤ã‚’è¨å®š
dJointAddHingeTorque(joint[0], k1 * ang_rate); // 摩擦トルクを付åŠ
if (step == 0) dJointDestroy(amotor); // amotorã®ç ´å£Š
// amotorã‚’ç ´å£Šã—ãŸããªã„å ´åˆã¯ä»¥ä¸‹ã§ã‚‚良ã„
// if (step == 0) dJointSetAMotorNumAxes(amotor, 0);
step++;
}
void setDrawStuff() {
fn.version = DS_VERSION;
fn.start = &start;
fn.step = &simLoop;
fn.path_to_textures = "../../drawstuff/textures";
}
int main(int argc, char *argv[])
{
setDrawStuff();
world = dWorldCreate();
space = dHashSpaceCreate(0);
// dWorldSetGravity (world, 0, 0, -9.8); // é‡åŠ›åŠ é€Ÿåº¦
createArm();
dsSimulationLoop(argc,argv,640, 480,&fn);
dSpaceDestroy(space);
dWorldDestroy(world);
return 0;
}
[/code]
終ã‚り。