2010-04-12 30 views
9

我想在二維手臂(由三個關節組成)上實現逆運動學。我能夠將最低臂旋轉到所需的位置。現在,我有一些問題:二維逆運動學實現

  1. 我該如何讓上臂隨第三個一起移動,以便臂的終點達到所需點。我是否需要爲兩者使用旋轉矩陣,如果是的話,是否有人可以給我一些例子或幫助,並有任何其他可能;沒有旋轉矩陣的方式做這個?

  2. 最下臂只能朝一個方向移動。我試過谷歌它,他們說,兩個向量的交叉產品給手臂的方向,但這是3D。我正在使用2D和兩個2D向量的叉積給出一個標量。那麼,我怎樣才能確定它的方向?

PLZ人任何幫助,將不勝感激....

在此先感謝 維克拉姆

回答

7

我給它一個鏡頭,但因爲我的機器人是二十年過去,帶上一粒鹽。

我學到的方式,每一個關節由自己的旋轉矩陣描述,相對於當前位置和方向確定。然後通過將旋轉矩陣組合在一起來計算整個手臂端點的座標。

這正是實現你正在尋找的效果:你可以只移動一個關節(改變其方向),和所有其他關節會自動跟隨。

你不會有讓周圍多少機會矩陣這裏 - 事實上,如果你使用齊次座標,所有關節計算(旋轉和平移)可以用矩陣乘法模型。優點是可以用單個矩陣(加上手臂的原點)來描述完整的手臂位置。

使用這種變換矩陣,可以解決逆運動學問題:由於變換矩陣的元素將取決於關節的角度,因此可以將整個計算的「終點=起點x變換」視爲一個方程組,並且已知起點和終點,則可以解決該系統以確定未知角度。這裏的困難在於方程可能不可解,或者有多種解決方案。

雖然我不太明白你的第二個問題 - 你在找什麼?

3

在機器人技術中,我們經常使用DH參數來計算正向和反向運動。 Wikipedia有一個很好的介紹。

3

DH(Denavit-Hartenberg)符號是解決方案的一部分。它可以幫助您收集一組簡潔的值,描述機器人的機械裝置,例如連接長度和連接類型。

從那裏計算正向運動學變得更加容易。首先,您必須瞭解的是如何將座標系從一個地方翻譯成另一個座標系。例如,給定你的機器人(或它的DH表),你必須將一組旋轉和平移應用於一個座標系(例如世界)以知道點(或矢量)在機器人的手腕座標系。

正如您可能已經知道的,齊次變換矩陣對於這種變換非常有用。它們是封裝旋轉和平移的4x4矩陣。這些矩陣的另一個非常有用的特性是,如果有兩個座標框架通過一些旋轉和平移進行鏈接和定義,那麼如果將兩個矩陣相乘,那麼只需將乘積乘以轉換目標即可。

所以DH表將幫助你建立矩陣。

逆運動學雖然有點複雜,但取決於您的應用。複雜性來自針對相同問題的多種解決方案。自由度越多,解決方案的數量就越多。

想想你的手臂。捏住你周圍的東西。您可以將手臂移動到空間中的多個位置,並仍然保持捏合矢量不變。解決逆運動學問題涉及決定選擇哪種解決方案。

6
  1. 除了旋轉矩陣,旋轉可以用角度表示,也可以用complex number of the unit circle表示,但它確實是一回事。更重要的是,你需要一個代表Trigid body transformations,這樣你就可以編寫像t1 * t2 * t3這樣的東西來計算第三個鏈接的位置和方向。

  2. 使用atan2來計算angle between the vectors

正如以下Python示例所示,這兩件事足以構建一個小型IK解算器。

from gameobjects.vector2 import Vector2 as V 
from matrix33 import Matrix33 as T 
from math import sin, cos, atan2, pi 
import random 

gameobjects庫沒有2D轉換,所以你要自己寫matrix33。它的接口就像gameobjects.matrix44

定義從一個關節到下一個關節轉換的正向運動學函數。我們通過angle擔任聯合旋轉,接着是一個固定的轉型joint

def fk_joint(joint, angle): return T.rotation(angle) * joint 

工具的轉型是tool == fk(joints, q)其中joints是固定的轉換和q是關節角度:

def fk(joints, q): 
    prev = T.identity() 
    for i, joint in enumerate(joints): 
     prev = prev * fk_joint(joint, q[i]) 
    return prev 

如果手臂的底部有偏移量,則替換T.identity()變換。

OP正在通過循環座標下降來解決位置IK問題。這個想法是通過一次調整一個關節變量來將工具靠近目標位置。設q爲聯合的角度,並且prev爲聯合的基礎的變換。接頭應通過向工具和目標位置的矢量之間的角度進行旋轉:

def ccd_step(q, prev, tool, goal): 
    a = tool.get_position() - prev.get_position() 
    b = goal - prev.get_position() 
    return q + atan2(b.get_y(), b.get_x()) - atan2(a.get_y(), a.get_x()) 

遍歷關節和更新關節值的每一個變化的工具結構:

def ccd_sweep(joints, tool, q, goal): 
    prev = T.identity() 
    for i, joint in enumerate(joints): 
     next = prev * fk_joint(joint, q[i]) 
     q[i] = ccd_step(q[i], prev, tool, goal) 
     prev = prev * fk_joint(joint, q[i]) 
     tool = prev * next.get_inverse() * tool 
    return prev 

注意對於3D,fk()ccd_sweep()是相同的;你只需要重寫fk_joint()ccd_step()

構造一個臂n相同的鏈接和運行CCD掃描的cnt迭代,從隨機臂形態q開始:

def ccd_demo(n, cnt): 
    q = [random.uniform(-pi, pi) for i in range(n)] 
    joints = [T.translation(0, 1)] * n 
    tool = fk(joints, q) 
    goal = V(0.9, 0.75) # Some arbitrary goal. 
    print "i  Error" 
    for i in range(cnt): 
     tool = ccd_sweep(joints, tool, q, goal) 
     error = (tool.get_position() - goal).get_length() 
     print "%d %e" % (i, error) 

我們可以嘗試求解器和比較收斂的不同數量的速度鏈接:

>>> ccd_demo(3, 7) 
i  Error 
0 1.671521e-03 
1 8.849190e-05 
2 4.704854e-06 
3 2.500868e-07 
4 1.329354e-08 
5 7.066271e-10 
6 3.756145e-11 
>>> ccd_demo(20, 7) 
i  Error 
0 1.504538e-01 
1 1.189107e-04 
2 8.508951e-08 
3 6.089372e-11 
4 4.485040e-14 
5 2.601336e-15 
6 2.504777e-15