4
1
さて今回は前回作ったロボットアームを本格的に動かしていきたいと思います。
以下の書籍で逆運動学なるものを知りましたので、その逆運動学でロボットアームを制御します。
ここではアームにペンをつけて文字を書かせてみます。
逆運動学とは
前回は各サーボモータの角度を指定して、ロボットアームの姿勢を制御していました。つまり各サーボの角度でアーム先端の座標(x, y, z)が決まります。これを順運動学(Forward Kinematics)といいます。
逆運動学(Inverse Kinematics)とは、まさに逆でロボットアーム先端の座標(x, y, z)を指定して、各サーボの角度を算出する手法です。IKなどと言われているようです。
逆運動学によるサーボ角度算出
前回作ったロボットアームにマジックペンをつけて、ペン先の座標を指定して文字を書くことを目指します。
各アームの長さは以下の通りです。
L1=92 mm
L2=137 mm
L3=165 mm

それでは算出していきましょう!
座標は以下のように平面上を(x, y)、高さをzとします。

首振りサーボの角度θ1は平面座標(x, y)ですぐ導出できます。
θ1=tan−1(yx)
2個目のサーボの角度θ2は余弦定理を用いて導出します。
L32=L22+ld2–2L2ldcosθ2′
θ2′=cos−1(L22+ld2–L322L2ld)
θ2=θ2′+φ=cos−1(L22+ld2–L322L2ld)+φ
但し、φ=tan−1(z–L1l)
ld=√l2+(z–L1)2
l=√x2+y2
3個目のサーボの角度θ3も余弦定理を用いて導出します。
ld2=L22+L32–2L2L3cos(90°+θ3)=L22+L32+2L2L3sinθ3
θ3=sin−1(ld2−L22–L322L2L3)
以上のとおり、所望の座標(x, y, z)とロボットアームの長さL1、L2、L3からサーボの角度を導出することができました。
参考
動作
逆運動学によって座標の指定のみでロボットアームの制御ができるようになったので以下のように線がひけます。
Arduinoコード
冒頭に紹介した書籍の第5章サンプルコードを参考にプログラミングしました。
以下でArduinoサンプルコードをダウンロードできます。ありがたい!
https://www.ohmsha.co.jp/book/9784274222115/
求めた逆運動学の式を用いてロボットアーム先端の座標を制御します。
シリアルモニタで打ち込んだ文字によってロボットアームの動作を選択しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
#include <Servo.h> Servo myservo1, myservo2, myservo3; float th1=90,th2=90,th3=90; float phi,ld,l; int pos = 0; float L1=92,L2=137,L3=165; float x,y,z; void setup() { Serial.begin(115200); myservo1.attach(9, 500, 2420); //MG995 myservo2.attach(10, 820, 2140); //DS3115 myservo3.attach(11, 820, 2140); //DS3115 set_servo(); ik(-45, 228, 10); } void loop() { char c; if ( Serial.available() > 0 ) { c = Serial.read(); if(c=='1'){ //一を書く delay(100); for(x = -60; x <= 60; x += 5){ ik(x, 210, 0); delay(100); } ik(0, 170, 230); //初期姿勢 }else if(c=='u'){ //ウを書く ik(-45, 228, 10); delay(500); ik(-45, 228, 0); delay(200); ik(-45, 220, 0); delay(200); ik(-45, 220, 10); delay(200); ik(-57, 220, 10); delay(200); ik(-57, 220, 0); delay(200); ik(-54, 210, 0); delay(200); ik(-54, 210, 10); delay(200); ik(-57, 220, 10); delay(200); ik(-57, 220, 0); delay(200); ik(-35, 220, 0); delay(200); ik(-35, 210, 0); delay(200); ik(-37, 200, 0); delay(200); ik(-42, 195, 0); delay(200); ik(-42, 195, 10); delay(200); //ンを書く ik(-15, 220, 10); delay(500); ik(-15, 220, 0); delay(200); ik(-5, 210, 0); delay(200); ik(-5, 210, 10); delay(200); ik(15, 220, 10); delay(200); ik(15, 220, 0); delay(200); ik(10, 210, 0); delay(200); ik(10, 205, 0); delay(200); ik(8, 200, 0); delay(200); ik(-2, 195, 0); delay(200); ik(-10, 195, 0); delay(200); ik(-10, 195, 10); delay(200); //コを書く ik(35, 220, 10); delay(500); ik(35, 220, 0); delay(200); ik(60, 220, 0); delay(200); ik(60, 195, 0); delay(200); ik(35, 195, 0); delay(200); ik(35, 195, 10); }else if(c=='0'){ ik(0, 170, 230); //初期姿勢 } } } void ik(float x,float y,float z){ th1=atan2(y,x); l=sqrt(x*x + y*y); ld=sqrt(l*l + (z-L1)*(z-L1)); phi=atan2((z-L1),l); th2=phi + acos((ld*ld+L2*L2-L3*L3)/(2*ld*L2)); th3=asin((ld*ld-L2*L2-L3*L3)/(2*L2*L3)); th1=th1*180/3.14; th2=th2*180/3.14; th3=th3*180/3.14; set_servo(); } void set_servo(){ myservo1.write(th1); myservo2.write(th2); myservo3.write(th3); } |
おわりに
逆運動学によって座標の指定でロボットアームを自由に動かせるようになりました。

さて、次は現状ちょっと可動範囲が狭いのでアームの構成の調整と
もっと手軽にアームを制御できるように工夫したいと思います。
それではまた
次の記事
Processing で制御 ーロボットアーム自作への道3ー