2013-07-26 2 views
0

3 RC Servos와 Arduino를 사용하여 간단한 로봇 팔을 만들었습니다. 방금 ​​놀고 로봇에 대해 배우고 싶습니다.전방 운동학 데이터 모델링

현재 서보의 세 각도 위치를 사용하여 로봇 팔의 끝 부분의 위치를 ​​계산하려고합니다. "Forward Kinematics"나는 이것을위한 기술적 용어라고 생각합니다. 팔 끝은 펜이지만, 나중에 그 위에 무언가를 그려 볼 수도 있다고 생각했습니다.

팔의 동작 범위에서 나는 직교 좌표계를 설정하고 24 (각도 => 위치) 샘플을 기록했습니다. pastebin.com/ESqWzJJB

이제이 데이터를 모델링하려고합니다.하지만 여기서는 약간 깊이 있습니다. 여기 내 접근 방식은 다음과 같습니다.

나는 Denikit-Hartenberg 방정식을 Wikipedia en.wikipedia.org/wiki/Denavit-Hartenberg_parameters에 있습니다. 그런 다음 최소 제곱 최적화를 사용하여 매개 변수를 결정하려고합니다.

y = f(ax+b)*c+d 

내 파이썬 코드 :

minimize(sum(norm(f(x,P)-y)^2)) 

는 또한 가능한 왜곡 (서보 각도 즉 위상 시프트)을 보상하기 위해 입력 및 모델의 출력과 선형 조건을 추가 pastebin.com을/gQF72mQn

from numpy import * 
from scipy.optimize import minimize 

# Denavit-Hartenberg Matrix as found on Wikipedia "Denavit-Hartenberg parameters" 
def DenHarMat(theta, alpha, a, d): 
    cos_theta = cos(theta) 
    sin_theta = sin(theta) 
    cos_alpha = cos(alpha) 
    sin_alpha = sin(alpha) 


    return array([ 
     [cos_theta, -sin_theta*cos_alpha, sin_theta*sin_alpha, a*cos_theta], 
     [sin_theta, cos_theta*cos_alpha, -cos_theta*sin_alpha, a*sin_theta], 
     [0, sin_alpha, cos_alpha, d], 
     [0, 0, 0, 1], 
    ]) 


def model_function(parameters, x): 
    # split parameter vector 
    scale_input, parameters = split(parameters,[3]) 
    translate_input, parameters = split(parameters,[3]) 

    scale_output, parameters = split(parameters,[3]) 
    translate_output, parameters = split(parameters,[3]) 

    p_T1, parameters = split(parameters,[3]) 
    p_T2, parameters = split(parameters,[3]) 
    p_T3, parameters = split(parameters,[3]) 

    # compute linear input distortions 
    theta = x * scale_input + translate_input 

    # load Denavit-Hartenberg Matricies 
    T1 = DenHarMat(theta[0], p_T1[0], p_T1[1], p_T1[2]) 
    T2 = DenHarMat(theta[1], p_T2[0], p_T2[1], p_T2[2]) 
    T3 = DenHarMat(theta[2], p_T3[0], p_T3[1], p_T3[2]) 

    # compute joint transformations 
    # y = T1 * T2 * T3 * [0 0 0 1] 
    y = dot(T1,dot(T2,dot(T3,array([0,0,0,1])))) 

    # compute linear output distortions 
    return y[0:3] * scale_output + translate_output 


# least squares cost function 
def cost_function(parameters, X, Y): 
    return sum(sum(square(model_function(parameters, X[i]) - Y[i])) for i in range(X.shape[0]))/X.shape[0] 


# ========== main script start =========== 

# load data 
data = genfromtxt('data.txt', delimiter=',', dtype='float32') 
X = data[:,0:3] 
Y = data[:,3:6] 


cost = 9999999 

#try: 
# parameters = genfromtxt('parameters.txt', delimiter=',', dtype='float32') 
# cost = cost_function(parameters, X, Y) 
#except IOError: 
# pass 


# random init 
for i in range(100): 
    tmpParams = (random.rand(7*3)*2-1)*8 
    tmpCost = cost_function(tmpParams, X, Y) 
    if tmpCost < cost: 
     cost = tmpCost 
     parameters = tmpParams 
     print('Random Cost: ' + str(cost)) 
     savetxt('parameters.txt', parameters, delimiter=',') 


# optimization 
continueOptimization = True 
while continueOptimization: 
    res = minimize(cost_function, parameters, args=(X,Y), method='nelder-mead', options={'maxiter':100,'xtol': 1e-5}) 
    parameters = res.x 
    print(res.fun) 
    savetxt('parameters.txt', parameters, delimiter=',') 
    continueOptimization = not res.success 


print(res) 

하지만 작동하지 않을 것입니다. 또한 간단한 3x4 행렬 곱셈을 시도했습니다.이 곱셈은 모델로서별로 의미가 없지만 이상하게도 위에 나온보다 정교한 모델보다 좋지 않습니다.

도움이 될만한 사람이 있기를 바랍니다.

+0

당신이 당신의 질문에 코드를 게시 아닌 사람들은 그것을보고 다른 웹 사이트로 이동하시기 바랍니다 수 :

여기에 도움이 될 수 있습니다 일부 동영상은? –

답변

1

정확하게 이해했다면 로봇 팔의 역 기구학 (inverse kinematics, IK) 문제를 해결하려고합니다. Forward Kinematics (FK)는 관절 각이 주어지면 엔드 이펙터의 위치를 ​​파악하는 것입니다. 엔드 이펙터가 원하는 위치에 도달하게하는 각도를 찾고자합니다.

IK 문제를 해결하려면 팔의 앞으로 운동학을 알아야합니다. 현재 FK에 대해 잘 모르는 경우 다음 스크립트를 사용하여 각 관절 (엔드 이펙터 포함)에 대한 기호식 FK 행렬을 얻을 수 있습니다. 또한 야 코비 행렬을 생성합니다.

import numpy as np 
from sympy import * 

def pos(matrix): 
list = [0,0,0] 
list[0] = matrix[0,3] 
list[1] = matrix[1,3] 
list[2] = matrix[2,3] 
return np.array(list).astype(float).tolist() 

class KinematicChain: 

def __init__(self): 
    self.i = 1 
    self.syms = [] 
    self.types = [] 
    self.matrices = [] 
    self.fk = [] 

def add(self, type, relPos): 
    """ 
    Parameters: 
     type - the type of joint 
     relpos - the position of the joint relative to the previos one 
    """ 
    mat = self.transMatrix(type, relPos); 
    self.matrices.append(mat) 
    self.types.append(type) 
    if len(self.fk) == 0: 
     self.fk.append(eye(4)*mat) 
    else: 
     self.fk.append(simplify(self.fk[-1]*mat)) 


def jacobian(self): 
    fk = self.fk[-1] 

    px = fk[0,3] 
    py = fk[1,3] 
    pz = fk[2,3] 

    f = Matrix([px, py, pz]) 

    if (len(self.syms) < 1): 
     return eye(4) 
    else: 
     x = Matrix(self.syms) 
     ans = f.jacobian(x) 
     return ans 



def transMatrix(self, type, p): 
    if (type != "FIXED"): 
     s1 = "a" + str(self.i) 
     self.i += 1 
     a = symbols(s1) 
     self.syms.append(a) 

    if (type == "FIXED"): 
     return Matrix([ 
     [1, 0, 0, p[0]], 
     [0, 1, 0, p[1]], 
     [0, 0, 1, p[2]], 
     [0, 0, 0, 1]]) 
    elif (type == "RX"): 
     return Matrix([ 
     [1, 0, 0, p[0]], 
     [0, cos(a), -sin(a), p[1]], 
     [0, sin(a), cos(a), p[2]], 
     [0, 0, 0, 1]]) 
    elif (type == "RY"): 
     return Matrix([ 
     [cos(a), 0, sin(a), p[0]], 
     [0, 1, 0, p[1]], 
     [-sin(a), 0, cos(a), p[2]], 
     [0, 0, 0, 1]]) 
    elif (type == "RZ"): 
     return Matrix([ 
     [cos(a), -sin(a), 0, p[0]], 
     [sin(a), cos(a), 0, p[1]], 
     [0, 0, 1, p[2]], 
     [0, 0, 0, 1]]) 
    elif (type == "PX"): 
     return Matrix([ 
     [1, 0, 0, p[0] + a], 
     [0, 1, 0, p[1]], 
     [0, 0, 1, p[2]], 
     [0, 0, 0, 1]]) 
    elif (type == "PY"): 
     return Matrix([ 
     [1, 0, 0, p[0]], 
     [0, 1, 0, p[1] + a], 
     [0, 0, 1, p[2]], 
     [0, 0, 0, 1]]) 
    elif (type == "PZ"): 
     return Matrix([ 
     [1, 0, 0, p[0]], 
     [0, 1, 0, p[1]], 
     [0, 0, 1, p[2] + a], 
     [0, 0, 0, 1]]) 
    else: 
     return eye(4) 

IK를 해결하는 데는 여러 가지 방법이 있습니다. 좋은 방법은 Damped Least Squared 방법입니다. 참조 : http://math.ucsd.edu/~sbuss/ResearchWeb/ikmethods/iksurvey.pdf

더 간단한 방법은 제한된 매트릭스 지원으로 arduino에서 작업하기에 꽤 관리할만한 Cyclic Coordinate Decent입니다. 참조 : http://www.cs.cmu.edu/~15464-s13/assignments/assignment2/jlander_gamedev_nov98.pdf

0

나는 당신이하려고하는 것이 일종의 "운동학 보정"이라고 생각합니다 : 일련의 측정 데이터에서 로봇 매개 변수를 식별하는 것입니다. 정말로 깊이 파고 싶다면이 주제에 대해 이야기하는 수많은 고전 교과서가 있습니다 (예 : [Mooring et al.] "Fundamentals of manipulator calibration").

질문으로 돌아 가면 매개 변수 식별이 수렴에 실패 할 수 있으므로 많은 경우 요리 책 응답이 아닙니다. ;)

한 가지 가능한 경우는 평행 축이있는 두 개 (이상)의 접합부가있는 경우입니다. 예를 들어 SCARA 또는 PUMA과 같은 메커니즘과 같이 단순한 로봇에서는 이러한 종류의 구성을 사용하는 것이 일반적입니다. 이 경우 DH 규칙을 사용하면 축선을 선택할 수있는 방법이 무한합니다.

이 문제를 해결하는 방법에는 여러 가지가 있지만 YMMV가 있습니다. 한 가지 시도해 볼 수있는 것은 Hayati 수정 DH 모델을 사용하는 것입니다. 이 모델은 병렬 축의 경우 특이점을 극복하기 위해 기본 DH에 하나 이상의 매개 변수 "베타"를 추가합니다.

또는 자신의 "사용자 지정"변환 행렬을 만들어 메커니즘을 모델링 해 볼 수 있습니다. 예를 들어, 롤 피치 요 (또는 오일러 각도)를 사용하여 관절 축 간의 회전을 표현한 다음 하나의 길이 매개 변수를 추가하여 다음 관절에 도달 할 수 있습니다.

주의를 끌기 위해 _scale_output_ . 이것은 주어진 데이터 세트에 대해 여러 "팔 길이"솔루션을 가질 수 있다는 것을 의미한다고 생각합니다. 예로서, [scale_output=1, arm_length=100][scale_output=100, arm_length=1]은 동일한 관절 각을 갖는 동일한 위치를 제공 할 것이다. 모델에서 scale_output을 제거하고 도움이되는지 확인하십시오.

다른 최적화/최소화 루틴을 사용해 볼 수도 있습니다. 과거에는 기구학 교정에 scipy.optimize.leastsq()을 성공적으로 사용했습니다.

희망이 도움이됩니다.