ODEã§å­¦ã¶C言語2 [Step6: ã¾ã¨ã‚]

2010-07-26
By


STEP6: 玉çªãロボット


ODEã§å­¦ã¶C言語2ã®Step6ã§ã™ï¼Žä»Šå›žã§æœ€çµ‚回ã¨ãªã‚Šã¾ã™ï¼ŽODEã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ç”Ÿæˆæ³•ã¨ç°¡å˜ãªåˆ¶å¾¡ã®ã‚µãƒ³ãƒ—ルプログラムを学ã³ã¾ã—ょã†ï¼Ž

ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¯æˆ‘々ã®å‘¨ã‚Šã§ã¯ã€æŠ˜ç•³ã¿æºå¸¯ã®ãƒ’ンジやドアã®è¶ç•ªã«ç›¸å½“ã—ã¾ã™ã€‚å°é›£ã—ãã„ã†ã¨ã€ï¼’ã¤ã®ãƒœãƒ‡ã‚£ã®ä½ç½®ã‚„姿勢をã‚る一定ã®é–¢ä¿‚ã«ä¿ã¤æ‹˜æŸãŒã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¨ãªã®ã§ã™ã€‚ODEã§ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¨æ‹˜æŸã‚’åŒã˜æ„味ã§ä½¿ã£ã¦ã„ã¾ã™ã€‚

ODEã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆï¼ˆé–¢ç¯€ï¼‰ã¯ï¼’ã¤ã®ãƒœãƒ‡ã‚£(剛体,body)ã‚’ã¤ãªã’ã‚‹ã‚‚ã®ã§ã™ã€‚1ã¤ã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã§ï¼“個以上ã®ãƒœãƒ‡ã‚£ã‚’ã¤ãªã’ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ã—,1個ã®ãƒœãƒ‡ã‚£ã ã‘ã‚’ã¤ãªã’ã‚‹ã“ã¨ã‚‚ã§ãã¾ã›ã‚“.必ãšï¼’個ã®ãƒœãƒ‡ã‚£ã‚’1ã¤ã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã§ã¤ãªã’ãªã‘れã°ãªã‚Šã¾ã›ã‚“.

ã¾ãŸï¼ŒODEã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¯æ‘©æ“¦ãŒã‚りã¾ã›ã‚“ã—,å¯å‹•域を設定ã—ãªã„ã¨+dInfinity(+ç„¡é™å¤§)ã‹ã‚‰-dInfinity(-ç„¡é™å¤§ï¼‰ã¾ã§å›žè»¢ã¾ãŸã¯ç§»å‹•ã—ã¾ã™ï¼Žè§’度ã¯[rad]ã§ã™ï¼Ž


  • ジョイントã®ä½¿ã„æ–¹
  1. ***ジョイントã®ç”Ÿæˆã€€ã€€ã€€ã€€ã€€ã€€dmJointCreate***()
  2. ***ジョイントã¨ãƒœãƒ‡ã‚£ã®çµåˆã€€ dJointAttach(dJointID, dBodyID, dBodyID)
  3. ***ジョイントã®ä¸­å¿ƒç‚¹ã‚’設定 dJointSet***Anchor()
  4. ***ジョイントã®å›žè»¢è»¸ã‚’設定 dJointSet***Axis()

上ã§***ã«ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ã‚¿ã‚¤ãƒ—ãŒå…¥ã‚Šã¾ã™ã€‚タイプã«ã¯Hinge(ヒンジ)ã€Slider(スライダー)ãŒã‚りã¾ã™ã€‚サンプルプログラムã§ã¯ãƒ’ンジジョイントã¨ç›´å‹•å¼ã®ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã‚’使ã„ã¾ã™ï¼Ž

  • ジョイントã®ãƒ‘ラメータ設定
  1. å¯å‹•域ã®è¨­å®š
    dJointSetHingeParam(dJointID, dParamLoStop, å¯å‹•域ã®ä¸‹é™ï¼‰;
    dJointSetHingeParam(dJointID, dParamHiStop, å¯å‹•域ã®ä¸Šé™ï¼‰;
  2. 目標角速度ã¨ãれを実ç¾ã™ã‚‹ãŸã‚ã®æœ€å¤§ãƒˆãƒ«ã‚¯ã®è¨­å®š
    dJointSetHingeParam(dJointID, dParamVel, 目標角速度);

    dJointSetHingeParam(dJointID, dParamFMax, 最大トルク);

パラメータã¨ã—ã¦ã¯ã€é–¢ç¯€å¯å‹•域ã®ä¸‹é™ã‚’示ã™dParamLoStopã€ä¸Šé™ã‚’示ã™dParamHiStopã€è§’速度(ヒンジジョイント)ã¾ãŸã¯é€Ÿåº¦(ç›´å‹•å¼é–¢ç¯€ï¼‰ã‚’示ã™dParamVelã€æœ€å¤§ãƒˆãƒ«ã‚¯ã‚’示ã™dParaFMaxãªã©ãŒã‚りã¾ã™ã€‚ãªãŠã€ODEã§ã¯é–¢ç¯€ã«ãƒ¢ãƒ¼ã‚¿ãŒæ¨™æº–ã§çµ„ã¿è¾¼ã¾ã‚Œã¦ã„ã‚‹ã®ã§ã€dParamVelã‚„dParaFMaxを指定ã™ã‚‹ã¨é–¢ç¯€ãŒå‹•ãã¾ã™ã€‚

ソースコード
å°‘ã—é•·ããªã‚Šã¾ã™ãŒï¼Œã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’掲載ã—ã¾ã™ï¼Žã“ã®ã‚³ãƒ¼ãƒ‰ã¯ä»Šã¾ã§ç¿’ã£ãŸï¼Œã‚­ãƒ¼æ“作関数,シミュレーションã®å†ã‚¹ã‚¿ãƒ¼ãƒˆï¼Œãƒœãƒ‡ã‚£ã¸åŠ›ã‚’åŠ ãˆã‚‹ãªã©ã®ã»ã‹ã«ï¼Œã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ç”Ÿæˆã¨åˆ¶å¾¡æ³•ãªã©ç°¡å˜ãªã‚²ãƒ¼ãƒ ã‚„シミュレータを作るãŸã‚ã«å¿…è¦ãªã“ã¨ã¯ä¸€é€šã‚Šå…¥ã£ã¦ã„ã¾ã™ï¼Ž

/* step6 */

#define START_X 0.0
#define START_Y 0.0
#define START_Z 0.1

dmObject torso, leg[2], ball;
static int STEPS = 0;      // シミュレーションã®ã‚¹ãƒ†ãƒƒãƒ—æ•°
double S_LENGTH  = 0.0;    // スライダー長
double H_ANGLE   = 0;      //ヒンジã®è§’度

// ロボットã®ç”Ÿæˆ
void createMonoBot()
{
    int i;
    double l_leg = 0.75; // é•·ã•
    double m_leg = 1.0;  // 質é‡
    double r_leg[2] = {0.05, 0.03}; // åŠå¾„
    double m_torso = 100.0; // 胴体ã®è³ªé‡
    double r_torso = 0.25;  // 胴体ã®åŠå¾„
    double l_torso = 0.2;   // 胴体ã®é«˜ã•
    double r_ball = 0.11;   // ボールã®åŠå¾„
    double m_ball = 0.5;    // ボールã®è³ªé‡
    double p_ball[3] = {START_X, START_Y+2*l_leg+0.1, START_Z}; // ボールã®ä½ç½®
    double p_torso[3] = {START_X, START_Y, START_Z};  // ä½ç½®
    double p_leg[2][3] = {{START_X, START_Y+0.5*l_leg, START_Z},
        {START_X, START_Y+l_leg, START_Z}
    };
    double p_anchor[3] = {START_X, START_Y, START_Z};
    double R[12];   // 回転行列

    static double  red[3] = {1.0, 0.0, 0.0}; // 色
    static double  color_leg[2][3] = {{0.0, 0.0, 1.0},{1.3, 1.3, 1.3}};

    dRSetIdentity(R);  //回転行列をå˜ä½è¡Œåˆ—ã§åˆæœŸåŒ–
    dmCreateSphere(&ball, p_ball,R,m_ball, r_ball, red); // ボールã®ç”Ÿæˆ
    dmCreateCylinder(&torso,p_torso,R,m_torso,r_torso,l_torso,red); // 胴体ã®ç”Ÿæˆ

    dRFromAxisAndAngle(R, 1, 0, 0, M_PI/2);
    for (i = 0; i < 2; i++)
    {
        dmCreateCapsule(&leg[i],p_leg[i],R,m_leg,r_leg[i],l_leg,color_leg[i]); // 脚ã®ç”Ÿæˆ
    }

    // ヒンジジョイント
    leg[0].joint = dmJointCreateHinge();
    dJointAttach(leg[0].joint, torso.body,leg[0].body);
    dJointSetHingeAnchor(leg[0].joint, p_anchor[0],p_anchor[1],p_anchor[2]);
    dJointSetHingeAxis(leg[0].joint, 0, 0, 1);

    // スライダージョイント
    leg[1].joint = dmJointCreateSlider();
    dJointAttach(leg[1].joint, leg[0].body,leg[1].body);
    dJointSetSliderAxis(leg[1].joint, 0, 1, 0);
    dJointSetSliderParam(leg[1].joint, dParamLoStop, -0.25);
    dJointSetSliderParam(leg[1].joint, dParamHiStop,  0.25);
}

// ヒンジジョイントã®åˆ¶å¾¡
static void controlHinge(dReal target)
{
    static dReal kp = 10.0, fmax = 1000;

    dReal tmp   = dJointGetHingeAngle(leg[0].joint);
    dReal diff  = target - tmp;
    if (diff >=   M_PI) diff -= 2.0 * M_PI; // diffãŒ2πよりå°ã•ã
    if (diff <= - M_PI) diff += 2.0 * M_PI; // diffãŒ-2πより大ãã
    dReal u     = kp * diff;

    dJointSetHingeParam(leg[0].joint, dParamVel,  u);
    dJointSetHingeParam(leg[0].joint, dParamFMax, fmax);
}

// スライダã®åˆ¶å¾¡ プログラム2.4
static void controlSlider(dReal target)
{
    static dReal kp   = 25.0;                       // 比例定数
    static dReal fmax = 1000;                        // 最大力[N]
    double tmp, u;

    tmp  = dJointGetSliderPosition(leg[1].joint);  // スライダã®ç¾åœ¨ä½ç½®
    u    = kp * (target - tmp);                    // 残差
    dJointSetSliderParam(leg[1].joint, dParamVel,  u);
    dJointSetSliderParam(leg[1].joint, dParamFMax, fmax);
}

// シミュレーションã®ãƒªã‚»ãƒƒãƒˆ
static void resetSim()
{
    STEPS    = 0;      // ステップ数ã®åˆæœŸåŒ–
    H_ANGLE  = 0.0;    // ヒンジ角度ã®åˆæœŸåŒ–
    S_LENGTH = 0.0;

    if (STEPS != 0) dmClose(); // シミュレーションã®çµ‚了

    dmInit();  // シミュレーションã®åˆæœŸåŒ–
    createMonoBot();
}

// キーæ“作
void command(int cmd)
{
    switch (cmd)
    {
    case 'j':
        S_LENGTH =   0.25;
        break;
    case 'l':
        S_LENGTH = - 0.25;
        break;
    case 'i':
        H_ANGLE +=   0.25;
        if (H_ANGLE  >   M_PI) H_ANGLE  =  -M_PI;
        break;
    case 'm':
        H_ANGLE -=   0.25;
        if (H_ANGLE  <  -M_PI) H_ANGLE  =   M_PI;
        break;
    case 'r':
        resetSim();
        break;
    case 'a':
        dBodyAddForce(torso.body, 0, -500, 0);
        break;
    case 'w':
        dBodyAddForce(torso.body, -500, 0, 0);
        break;
    case 'd':
        dBodyAddForce(torso.body, 0,  500, 0);
        break;
    case 'x':
        dBodyAddForce(torso.body,  500, 0, 0);
        break;
    case 's':
        dBodySetLinearVel(torso.body,  0, 0, 0);
        dBodySetAngularVel(torso.body, 0, 0, 0);
        break;
    default :
        printf("key missed \n");
        break;
    }
}

void simLoop(int pause)           /***  シミュレーションループ ***/
{
    int i;
    int s = 1000;                   // è·³èºã™ã‚‹å‘¨æœŸ(ステップ)

    if (!pause)
    {
        printf("STEPS=%d \n",STEPS++); //  ステップ数

        // スライダーã®ä¼¸ç¸®
        //if ((0 <= (STEPS%s)) && ((STEPS%s) <= 10)) S_LENGTH = 0.6;
        //else if ((11 <= (STEPS%s)) && ((STEPS%s) <= 15)) S_LENGTH = 0.0;

        controlSlider(S_LENGTH); // スライダージョイントã®åˆ¶å¾¡
        controlHinge(H_ANGLE);   // ヒンジジョイントã®åˆ¶å¾¡

        dmSimStep(); // シミュレーションを1ステップ進ã‚ã‚‹
    }

    dmDraw(&ball); // ãƒœãƒ¼ãƒ«ã®æç”»
    // ãƒ­ãƒœãƒƒãƒˆã®æç”»
    dmDraw(&torso);   // èƒ´ä½“ã®æç”»
    for (i = 0; i < 2; i++)dmDraw(&leg[i]); //è„šã®æç”»
    STEPS++;
}

int main()         /*** main関数 ***/
{
    dmInit(); // ODEã®åˆæœŸåŒ–
    resetSim();   // ロボットã®ç”Ÿæˆ
    dmLoop(800, 600, simLoop, command);  // シミュレーションループ ウインドウã®å¹…,高
    dmClose();          // ODEã®çµ‚了
    return 0;
}

ホームワーク

  • step6-100726.zipをダウンロードã—ã¦å®Ÿè¡Œã—ã¦ã¿ã¾ã—ょã†ï¼Ž
  • サンプルプログラムを改良ã—ã¦ãƒ“リヤードをプレイã™ã‚‹ãƒ­ãƒœãƒƒãƒˆã‚’作りã¾ã—ょã†ï¼Ž

コメントをã©ã†ãž

メールアドレスãŒå…¬é–‹ã•れるã“ã¨ã¯ã‚りã¾ã›ã‚“。

654 views  (Since 2010-08-11)