天天看點

V-rep學習筆記:機器人逆運動學數值解法(The Pseudo Inverse Method)

There are two ways of using the Jacobian matrix to solve kinematics. One is to use the transpose of the Jacobian JT. The other is to calculate the inverse of the Jacobian J-1. J is most likely redundant and non square,thus an ordinary inverse is not possible. We can try using the pseudo inverse to find a matrix that effectively inverts a non square matrix. J+ is the pseudoinverse of J, also called the Moore-Penrose inverse of J . It is defined for all matrices J , even ones which are not square or not of full row rank.

  雅可比矩陣将關節空間速度映射到直角坐标空間:ΔP = J(θ)Δθ。對于機器人運動學逆解來說可以考慮求雅克比矩陣J的逆,然後根據Δθ=J(θ)-1ΔP計算出關節角變動量并反複疊代。然當很多情況下J不可逆,是以可以考慮求其廣義逆(Moore-Penrose逆)來求解方程。設A∈Cm×n,b∈Cm,則線性方程組Ax=b有解的充分必要條件是AA+b=b,且通解為x=A+b + (I-A+A)y (y∈Cn任意),并且它的唯一極小範數解為x0 = A+b(矩陣論簡明教程 P150 A+在解線性方程組中的應用)。根據矩陣論(《矩陣論簡明教程 第二版》 科學出版社 第6章 廣義逆矩陣),設J為m×n階實矩陣,當rankJ=m時,有J+ = JT(J JT)-1;而當rankJ=n時,有J+ = (JTJ )-1 JT,此時方程組J(θ)Δθ=ΔP的解唯一。 對一般機器人來說n≥m,且rankJ=m,即有J+ = JT(J JT)-1。當n>m,即機構驅動數目多于末端自由度時,會出現多解的情況,pseudo inverse方法會尋找解向量中長度最小的一個(無窮多個解中2範數最小的解,即||Δθ0||2=min||Δθ||2,稱為極小範數解)

 Let  ΔP be e = t - P,where t is the target position,P is the end effector position and e is the desirable change of the end effector. The first iteration will result in a new θ from equation Δθ=J(θ)-1ΔP. By using forward kinematics a new position P of the end effector is acquired and a new iteration begins. This is done until either e is small enough or the end effector does not move. 使用Pseudo Inverse方法求機器人逆解的基本步驟如下所示:

V-rep學習筆記:機器人逆運動學數值解法(The Pseudo Inverse Method)

Operating Principle:

1. Shortest path in q-space

Advantages:

1. Computationally fast (second order method)

Disadvantages:

1. Matrix inversion necessary (numerical problems)

2. Unpredictable joint configurations

3. Non conservative

  The pseudoinverse tends to have stability problems in the neighborhoods of singularities. At a singularity, the Jacobian matrix no longer has full row rank, corresponding to the fact that there is a direction of movement of the end effectors which is not achievable. If the configuration is exactly at a singularity, then the pseudoinverse method will not attempt to move in an impossible direction, and the pseudoinverse will be well-behaved. However, if the configuration is close to a singularity, then the pseudoinverse method will lead to very large changes in joint angles, even for small movements in the target position. In practice, roundoff errors mean that true singularities are rarely reached and instead singularity have to be detected by checking values for being near-zero. 對于平面二連杆機構,當θ2趨近于0°或180°時,機械手接近奇異形位,關節J2速度将趨于無窮大。(參考John J.Craig. Introduction to Robotics: Mechanics and Control Chapter 5-->Section 5.8 Singularities)

  下面使用同樣的模型驗證Pseudo Inverse方法。從輸出視窗可以看出,該方法疊代次數相比Jacobian Transpose法明顯減少(疊代5次就達到精度要求)。The Jacobian pseudoinverse method is equivalent to solving by Newton's method.(相當于牛頓法)。Jacobian transpose is also related to solution by the method of steepest descent.(相當于最速降法或梯度法)。牛頓法是梯度法的進一步發展,梯度法在确定搜尋方向時隻考慮目标函數在疊代點的局部性質,即隻利用一階偏導數的資訊,而牛頓法進一步利用了目标函數的二階偏導數,考慮了梯度的變化趨勢,因而可以更為全面的确定合适的搜尋方向,以便很快的搜尋到極小點。

V-rep學習筆記:機器人逆運動學數值解法(The Pseudo Inverse Method)
V-rep學習筆記:機器人逆運動學數值解法(The Pseudo Inverse Method)
import vrep             #V-rep library
import sys      
import time
import math  
import numpy as np

# Starts a communication thread with the server (i.e. V-REP). 
clientID=vrep.simxStart('127.0.0.1', 20001, True, True, 5000, 5)

# clientID: the client ID, or -1 if the connection to the server was not possible
if clientID!=-1:  #check if client connection successful
    print 'Connected to remote API server'
else:
    print 'Connection not successful'
    sys.exit('Could not connect')    # Exit from Python


# Retrieves an object handle based on its name.
errorCode,J1_handle = vrep.simxGetObjectHandle(clientID,'j1',vrep.simx_opmode_oneshot_wait)
errorCode,J2_handle = vrep.simxGetObjectHandle(clientID,'j2',vrep.simx_opmode_oneshot_wait)
errorCode,target_handle = vrep.simxGetObjectHandle(clientID,'target',vrep.simx_opmode_oneshot_wait)
errorCode,consoleHandle = vrep.simxAuxiliaryConsoleOpen(clientID,'info',5,1+4,None,None,None,None,vrep.simx_opmode_oneshot_wait)

uiHandle = -1
errorCode,uiHandle = vrep.simxGetUIHandle(clientID,"UI", vrep.simx_opmode_oneshot_wait)
buttonEventID = -1
err,buttonEventID,aux = vrep.simxGetUIEventButton(clientID,uiHandle,vrep.simx_opmode_streaming)


L1 = 0.5    # link length
L2 = 0.5
gamma = 1       # step size
stol = 1e-2     # tolerance
nm = 100        # initial error
count = 0       # iteration count
ilimit = 1000   # maximum iteration


# initial joint value
# note that workspace-boundary singularities occur when q2 approach 0 or 180 degree
q = np.array([0,1])   


while True:
    retcode, target_pos = vrep.simxGetObjectPosition(clientID, target_handle, -1, vrep.simx_opmode_streaming)


    if(nm > stol):
        vrep.simxAuxiliaryConsolePrint(clientID, consoleHandle, None, vrep.simx_opmode_oneshot_wait) # "None" to clear the console window

        x = np.array([L1*math.cos(q[0])+L2*math.cos(q[0]+q[1]), L1*math.sin(q[0])+L2*math.sin(q[0]+q[1])])
        error = np.array([target_pos[0],target_pos[1]]) - x

        J = np.array([[-L1*math.sin(q[0])-L2*math.sin(q[0]+q[1]), -L2*math.sin(q[0]+q[1])],\
                      [L1*math.cos(q[0])+L2*math.cos(q[0]+q[1]), L2*math.cos(q[0]+q[1])]])

        J_pseudo = np.dot(J.transpose(), np.linalg.inv(J.dot(J.transpose())))
        dq = J_pseudo.dot(error)
        q = q + dq

        nm = np.linalg.norm(error)

        count = count + 1
        if count > ilimit:
            vrep.simxAuxiliaryConsolePrint(clientID,consoleHandle,"Solution wouldn't converge\r\n",vrep.simx_opmode_oneshot_wait)
        vrep.simxAuxiliaryConsolePrint(clientID,consoleHandle,'q1:'+str(q[0]*180/math.pi)+' q2:'+str(q[1]*180/math.pi)+'\r\n',vrep.simx_opmode_oneshot_wait)  
        vrep.simxAuxiliaryConsolePrint(clientID,consoleHandle,str(count)+' iterations'+'  err:'+str(nm)+'\r\n',vrep.simx_opmode_oneshot_wait)   


    err, buttonEventID, aux = vrep.simxGetUIEventButton(clientID,uiHandle,vrep.simx_opmode_buffer)    
    if ((err==vrep.simx_return_ok) and (buttonEventID == 1)):
        '''A button was pressed/edited/changed. React to it here!'''
        vrep.simxSetJointPosition(clientID,J1_handle, q[0]+math.pi/2, vrep.simx_opmode_oneshot )  
        vrep.simxSetJointPosition(clientID,J2_handle, q[1], vrep.simx_opmode_oneshot )
        
        '''Enable streaming again (was automatically disabled with the positive event):'''
        err,buttonEventID,aux=vrep.simxGetUIEventButton(clientID,uiHandle,vrep.simx_opmode_streaming)

    time.sleep(0.01)      
V-rep學習筆記:機器人逆運動學數值解法(The Pseudo Inverse Method)

  上面使用Python Remote API來進行逆解計算并控制V-rep中的模型(因為涉及到矩陣求逆等運算,而我不太熟悉Lua的相關數值計算庫)。需要注意的是要先在V-rep模型中調用函數simExtRemoteApiStart(portNumber)開啟通信服務端,然後在Python程式的用戶端進行連接配接。

繼續閱讀