この記事では、Python言語を用いて、2リンクマニピュレータ(2自由度アーム)の逆運動学を収束計算で求め、シミュレーションする方法をソースコード付きで解説します。
逆運動学の計算(収束計算)
ロボットアームの構造が複雑になると数式で逆運動学が解けなくなります。
そのような場合は、収束計算を用いて解を求めます。
– | 収束計算の流れ |
---|---|
1 | 仮の解(初期関節角度)を設定する |
2 | 仮の解から順運動学を用いて手先位置を求める |
3 | 目標位置と手先位置の誤差から仮の解を微修正する |
4 | 位置誤差が十分小さくなるまで1~3を繰り返す |
逆運動学の計算プログラム(数値計算)
Pythonを用いて収束計算で逆運動学を解き、姿勢を描画するプログラムを作成しました。
– | プログラムの処理手順 |
---|---|
1 | 2リンクアームのパラメータ(リンクの長さ、初期関節角度)を設定する |
2 | 手先の目標位置を設定する |
3 | 逆運動学を収束演算で計算し,目標位置を達成するための関節角度を導出する |
4 | 計算結果からアームの姿勢を表示する |
ソースコード
サンプルプログラムのソースコードです。
# -*- coding: utf-8 -*- import numpy as np from numpy import sin,cos import matplotlib.pyplot as plt # 並進行列(x軸方向に並進) def L(l): Li = np.matrix(( ( 1., 0., l), ( 0., 1., 0.), ( 0., 0., 1.) )); return Li # 回転行列(z軸周りに回転) def Rz(th): R = np.matrix(( (cos(th), -sin(th), 0.), (sin(th), cos(th), 0.), (0., 0., 1.) )) return R # 座標変換行列の微係数(z軸周り) def dRz(th): dR = np.matrix( ( (-sin(th),-cos(th),0.), ( cos(th),-sin(th),0.), (0.,0.,0.) )); return dR # グラフの描画 def plot(x, y): fn = "Times New Roman" # グラフ表示の設定 fig = plt.figure() ax = fig.add_subplot(111, axisbg="w") ax.tick_params(labelsize=13) # 軸のフォントサイズ plt.xlabel("$x [m]$", fontsize=20, fontname=fn) plt.ylabel("$y [m]$", fontsize=20, fontname=fn) plt.plot(x, y,"-g",lw=5,label="link") # リンクの描画 plt.plot(x, y,"or",lw=5, ms=10,label="joint") # 関節の描画 plt.xlim(-1.2,1.2) plt.ylim(-1.2,1.2) plt.grid() plt.legend(fontsize=20) # 凡例 plt.show() def arm2_ik(X, L, th): [x, y] = X [l1, l2] = L [th1, th2] = th X = np.matrix(( ( np.array(x) ), ( np.array(y) ) )) th1 = np.radians(th1) # 仮りの解1 th2 = np.radians(th2) # 仮りの解2 # 収束計算を50回繰り返す for j in range(50): # 原点座標(縦ベクトル) x = np.array([[0.],[0.],[1.]] ) P = np.matrix(( (1.,0.,0.), (0.,1.,0.), )) # 現在の手先位置を求める Xg = P * Rz(th1) * L(l1) * Rz(th2) * L(l2) * x # ヤコビ行列を求める J1 = dRz(th1) * L(l1) * x J2 = Rz(th1) * L(l1) * dRz(th2) * L(l2) * x JJ = np.c_[J1,J2] # 3つの列ベクトルを連結する J = P * JJ #ヤコビ行列 invJ = J.T * np.linalg.inv(J * J.T) #ヤコビ行列の逆行列 dx = X - Xg #位置の変位量 th = 0.1 * invJ * dx #逆運動学の式 th1 = th1 + th[0,0] th2 = th2 + th[1,0] return th1, th2 # 順運動学の計算 def arm2_fk(L, th): [l1, l2] = L [th1, th2] = th vec = np.array([[0.],[0.],[1.]] ) (x1, y1, z1) = Rz(th1) * L(l1) * vec # 第1関節の位置 (x2, y2, z2) = Rz(th1) * L(l1) * Rz(th2) * L(l2) * vec # 第2関節の位置 return x1, y1, x2, y2 # メイン def main(): # パラメータ L = [0.5, 0.5] # リンク1, 2の長さ X = [0.5, 0.5] # 手先の目標位置(x,y) th = [20, 20] # 初期関節角度(仮の解) # 逆運動学の計算 th = arm2_ik(X, L, th) # 順運動学の計算 (x1, y1, x2, y2) = arm2_fk(L, th) # ロボットアームの描画 x = (0, x1, x2) y = (0, y1, y2) plot(x, y) if __name__ == '__main__': main()
実行結果
サンプルプログラムの実行結果です。
リンク1、2の長さが0.5で手先の目標位置(0.5, 0.5)で計算した結果です。
– | 関連ページ |
---|---|
1 | ■Pythonでロボットシミュレーション |
2 | ■ロボット工学入門 基礎編 |
3 | ■Python入門 サンプル集 |
4 | ■NumPy入門 サンプル集 |
コメント