13. ç°¡å˜ãªåˆ¶å¾¡

3関節ロボットアーム(ソースコードã¯ãŸã£ãŸ100行)

3関節マニピュレータã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã€€ï¼ˆã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã¯ãŸã£ãŸ100行)

ODE (Open Dynamics Engine) åˆç´šè¬›åº§ã®ç¬¬ï¼‘3回目ã§ã™ã€‚

今回ã¯ä»Šã¾ã§ã®çŸ¥è­˜ã‚’æ•´ç†ã™ã‚‹ãŸã‚ã«ã€ç°¡å˜ãªï¼“関節マニピュレータã®ãƒ—ãƒã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã‚’作ã£ã¦ã¿ã¾ã—ょã†ã€‚ã“れã¯ODEを使ã†ã¨ã€ŒãŸã£ãŸï¼‘ï¼ï¼è¡Œç¨‹åº¦ã§ã“ã®ã‚ˆã†ãªã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ãŒã§ãã‚‹ã‚“ã§ã™ï¼Žã€ã¨ã„ã†ãƒ—ログラムãªã®ã§è¡çªè¨ˆç®—部分ã¯çœç•¥ã—ã¦ã„ã¾ã™ï¼Žã“ã®ãƒ­ãƒœãƒƒãƒˆã¯ã‚­ãƒ¼ãƒœãƒ¼ãƒ‰ã§æ“作å¯èƒ½ã§ã™ï¼Ž ロボットã®ç¬¬ï¼‘関節ã¯j(増加)åˆã¯f(減少)キーã§ï¼Œç¬¬ï¼’関節ã¯dåˆã¯kキーã§ï¼Œç¬¬ï¼“関節ã¯såˆã¯lキーã§å‹•ã‹ã™ã“ã¨ãŒã§ãã¾ã™ã€‚

速度&比例制御

関節を制御ã™ã‚‹æ–¹æ³•を説明ã—ã¾ã™ã€‚ODEã®é–¢ç¯€ã«ã¯ãƒ¢ãƒ¼ã‚¿ãŒå†…蔵ã•れã¦ã„ã¾ã™ï¼Žã“ã®ãƒ¢ãƒ¼ã‚¿ã®ãƒˆãƒ«ã‚¯ã‚’コントロールã™ã‚‹ãƒˆãƒ«ã‚¯åˆ¶å¾¡ã‚‚å¯èƒ½ã§ã™ãŒï¼Œã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã®å®‰å®šæ€§ã‚’考ãˆã‚‹ã¨ãƒ¢ãƒ¼ã‚¿ã®å›žè»¢é€Ÿåº¦ã‚’コントロールã™ã‚‹é€Ÿåº¦åˆ¶å¾¡ãŒãŠå‹§ã‚ã§ã™ï¼Žã“ã“ã§ã¯é€Ÿåº¦åˆ¶å¾¡ã®å®Ÿç¾æ³•ã«ã¤ã„ã¦èª¬æ˜Žã—ã¾ã™ï¼Ž

速度制御ã®ä¸­ã§ã‚‚色々ã‚りã¾ã™ãŒï¼Œã“ã“ã§ã¯æœ€ã‚‚ç°¡å˜ãªP制御(比例制御)を説明ã—ã¾ã™ï¼Žã“れã¯ç›®æ¨™å€¤ã¨ç¾åœ¨å€¤ã®å·®ã«æ¯”例ã—ã¦é–¢ç¯€ã®è§’速度を変更ã™ã‚‹æ–¹æ³•ã§ã™ã€‚関節角度ã®ç¾åœ¨å€¤ãŒç›®æ¨™å€¤ã¨é›¢ã‚Œã¦ã„ã‚‹å ´åˆã¯å¤§ããªè§’速度を与ãˆã€ç›®æ¨™å€¤ã¨åŒã˜å ´åˆã¯è§’速度ãŒï¼ã¨ãªã‚Šé–¢ç¯€ãŒåœæ­¢ã—ã¾ã™ã€‚ã¾ãŸã€ç¾åœ¨å€¤ãŒç›®æ¨™å€¤ã‚’ã¨ãŠã‚Šè¶Šã—ãŸå ´åˆã¯ã€ç¬¦å·ãŒãƒžã‚¤ãƒŠã‚¹ã«ãªã‚‹ãŸã‚回転ãŒå転ã—ã€ç¾åœ¨å€¤ãŒç›®æ¨™å€¤ã«è¿‘ããªã‚Šã¾ã™ã€‚

ã“れを実ç¾ã—ã¦ã„る関数ãŒcontrolã§ã™ã€‚関節ã®ãƒ‘ラメータdParamVelã¯ç›®æ¨™è§’速度ã§ã€dParamFMaxã¯ãã®è§’速度を実ç¾ã™ã‚‹ãŸã‚ã«ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆãŒç™ºæ®ã§ãる最大 トルクã§ã™ã€‚dParamFMaxã‚’ï¼ã«è¨­å®šã™ã‚‹ã¨ç›®æ¨™è§’速度を設定ã—ã¦ã‚‚トルクãŒï¼ãªã®ã§é–¢ç¯€ã¯å‹•ã„ã¦ãれã¾ã›ã‚“。

ã§ã¯ï¼Œã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’次ã«ç´¹ä»‹ã—ã¾ã—ょã†ï¼Ž

éŽåŽ»ã®ODEåˆç´šè¬›åº§ã‚’ç†è§£ã•れã¦ã„ã‚‹æ–¹ã«ã¯ç°¡å˜ãªã®ã§èª¬æ˜ŽãŒã»ã¨ã‚“ã©ã„らãªã„ã¨æ€ã„ã¾ã™ï¼Žã‚ã‹ã‚‰ãªã„箇所ãŒã‚れã°ã‚³ãƒ¡ãƒ³ãƒˆã«æ›¸ã込んã§ãã ã•ã„.補足説明をã—ã¾ã™ã€‚

//  sample13.cpp  3 DOF manipulator by   Kosei Demura  2006-2008
#include "ode/ode.h"     // ODE
#include "drawstuff/drawsutt.h"  // ODEã®æç”»ãƒ©ã‚¤ãƒ–ãƒ©ãƒª
#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]

void control() {  /***  P制御  ****/
  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); // 最大トルクã®è¨­å®š
  }
}

void start() { /*** æç”»APIã®åˆæœŸåŒ– ***/
  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);               // 視点ã¨è¦–ç·šã®è¨­å®š
}

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 ‘j’:  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;
  }

  // 目標角度ãŒé–¢ç¯€å¯å‹•域を越ãˆãªã„よã†ã«åˆ¶é™ã™ã‚‹
  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;
}

// シミュレーションループ。簡å˜ã«ã™ã‚‹ãŸã‚è¡çªæ¤œå‡ºã«é–¢ã™ã‚‹ã‚³ãƒ¼ãƒ‰ã¯çœç•¥ã€‚
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++ ) // ロボットã®ãƒªãƒ³ã‚¯ã‚’ã‚«ãƒ—ã‚»ãƒ«ã§æç”»
    dsDrawCapsuleD(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";

  dInitODE();  // ODEã®åˆæœŸåŒ–
  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); // シミュレーションループ
  dCloseODE();
  return 0;
}

ãªãŠã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã¯ã“ã“ã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã§ãã¾ã™ã€‚ ãŠã—ã¾ã„.

コメントをã©ã†ãž

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

3,822 views