简介

相信很多搞机械臂的人都用过UR这款机械臂,目前主流的正逆运动学是C++版本的,我早期写过一个Python版本的,今天也贡献出来给大家,需要的可以直接获取,想自己优化代码的也可以自己优化,有问题的欢迎关注发私信或者关注微信公众号,我会进行解释。感谢大家的支持。

代码如下

#!/usr/bin/python
"""
author:yuexiaoshu
time:20180812
version:v2
info:1,change class function 2,add best sol function
"""
import math
import numpy
#UR5 parmas
d1 = 0.089159
a2 = -0.42500
a3 = -0.39225
d4 = 0.10915
d5 = 0.09465
d6 = 0.0823
PI = math.pi
ZERO_THRESH = 0.00000001
class Kinematic:
    def __init__(self):
        global d1
        global a2
        global a3
        global d4
        global d5
        global d6
        global PI
        global ZERO_THRESH
    def Forward(self,q):
        T=[0]*16
        #00
        s1 = math.sin(q[0])
        c1 = math.cos(q[0])
        ##01
        q234 = q[1]
        s2 = math.sin(q[1])
        c2 = math.cos(q[1])
        ##02
        s3 = math.sin(q[2])
        c3 = math.cos(q[2])
        q234 += q[2]
        ##03
        q234 += q[3]
        ##04
        s5 = math.sin(q[4])
        c5 = math.cos(q[4])
        ##05
        s6 = math.sin(q[5])
        c6 = math.cos(q[5])
        s234 = math.sin(q234)
        c234 = math.cos(q234)
        #4*4 roate arrary
        #00 parameter
        T[0] = ((c1 * c234 - s1 * s234) * s5) / 2.0 - c5 * s1 + ((c1 * c234 + s1 * s234) * s5) / 2.0
        # 01 parameter
        T[1] = (c6 * (s1 * s5 + ((c1 * c234 - s1 * s234) * c5) / 2.0 + ((c1 * c234 + s1 * s234) * c5) / 2.0) -
              (s6 * ((s1 * c234 + c1 * s234) - (s1 * c234 - c1 * s234))) / 2.0)
        # 02 parameter
        T[2] = (-(c6 * ((s1 * c234 + c1 * s234) - (s1 * c234 - c1 * s234))) / 2.0 -
              s6 * (s1 * s5 + ((c1 * c234 - s1 * s234) * c5) / 2.0 + ((c1 * c234 + s1 * s234) * c5) / 2.0))
        # 03 parameter
        T[3] = ((d5 * (s1 * c234 - c1 * s234)) / 2.0 - (d5 * (s1 * c234 + c1 * s234)) / 2.0 -
              d4 * s1 + (d6 * (c1 * c234 - s1 * s234) * s5) / 2.0 + (d6 * (c1 * c234 + s1 * s234) * s5) / 2.0 -
              a2 * c1 * c2 - d6 * c5 * s1 - a3 * c1 * c2 * c3 + a3 * c1 * s2 * s3)
        # 04 parameter
        T[4] = c1 * c5 + ((s1 * c234 + c1 * s234) * s5) / 2.0 + ((s1 * c234 - c1 * s234) * s5) / 2.0
        # 05 parameter
        T[5] = (c6 * (((s1 * c234 + c1 * s234) * c5) / 2.0 - c1 * s5 + ((s1 * c234 - c1 * s234) * c5) / 2.0) +
              s6 * ((c1 * c234 - s1 * s234) / 2.0 - (c1 * c234 + s1 * s234) / 2.0))
        # 06 parameter
        T[6] = (c6 * ((c1 * c234 - s1 * s234) / 2.0 - (c1 * c234 + s1 * s234) / 2.0) -
              s6 * (((s1 * c234 + c1 * s234) * c5) / 2.0 - c1 * s5 + ((s1 * c234 - c1 * s234) * c5) / 2.0))
        # 07 parameter
        T[7] = ((d5 * (c1 * c234 - s1 * s234)) / 2.0 - (d5 * (c1 * c234 + s1 * s234)) / 2.0 + d4 * c1 +
              (d6 * (s1 * c234 + c1 * s234) * s5) / 2.0 + (d6 * (s1 * c234 - c1 * s234) * s5) / 2.0 + d6 * c1 * c5 -
              a2 * c2 * s1 - a3 * c2 * c3 * s1 + a3 * s1 * s2 * s3)
        # 08 parameter
        T[8] = ((c234 * c5 - s234 * s5) / 2.0 - (c234 * c5 + s234 * s5) / 2.0)
        # 09 parameter
        T[9] = ((s234 * c6 - c234 * s6) / 2.0 - (s234 * c6 + c234 * s6) / 2.0 - s234 * c5 * c6)
        # 10 parameter
        T[10] = (s234 * c5 * s6 - (c234 * c6 + s234 * s6) / 2.0 - (c234 * c6 - s234 * s6) / 2.0)
        # 11 parameter
        T[11] = (d1 + (d6 * (c234 * c5 - s234 * s5)) / 2.0 + a3 * (s2 * c3 + c2 * s3) + a2 * s2 -
              (d6 * (c234 * c5 + s234 * s5)) / 2.0 - d5 * c234)
        # 12 parameter
        T[12] = 0.0
        # 13 parameter
        T[13] = 0.0
        # 14 parameter
        T[14] = 0.0
        # 15 parameter
        T[15] = 1.0
        return T
    def SIGN(self,x):
        return (x>0)-(x<0)
    def Forward_all(self,q):
        #result
        result=[]
        T1=[]
        T2=[]
        T3=[]
        T4=[]
        T5=[]
        T6=[]
        #q01
        s1 = math.sin(q[0])
        c1 = math.cos(q[0])
        #q02
        q23 = q[1]
        q234 = q[1]
        s2 = math.sin(q[1])
        c2 = math.cos(q[1])
        #q03
        s3 = math.sin(q[2])
        c3 = math.cos(q[2])
        q23 += q[2]
        q234 += q[2]
        #q04
        q234 += q[3]
        #q05
        s5 = math.sin(q[4])
        c5 = math.cos(q[4])
        #q06
        s6 = math.sin(q[5])
        c6 = math.cos(q[5])
        s23 = math.sin(q23)
        c23 = math.cos(q23)
        s234 = math.sin(q234)
        c234 = math.cos(q234)
        #01T
        #00-15 param
        T1[0] = c1
        T1[1] = 0
        T1[2] = s1
        T1[3] = 0
        T1[4] = s1
        T1[5] = 0
        T1[6] = -c1
        T1[7] = 0
        T1[8] = 0
        T1[9] = 1
        T1[10] = 0
        T1[11] =d1
        T1[12] = 0
        T1[13] = 0
        T1[14] = 0
        T1[15] = 1
        result.append(("T1",T1))
        #01T*12T=02T
        #00-15 parameters
        T2[0] = c1 * c2
        T2[1] = -c1 * s2
        T2[2] = s1
        T2[3] =a2 * c1 * c2
        T2[4] = c2 * s1
        T2[5] = -s1 * s2
        T2[6] = -c1
        T2[7] =a2 * c2 * s1
        T2[8] = s2
        T2[9] = c2
        T2[10] = 0
        T2[11] = d1 + a2 * s2
        T2[12] = 0
        T2[13] = 0
        T2[14] = 0
        T2[15] = 1
        result.append(("T2",T2))
        #01T*12T*23T=03T
        T3[0] = c23 * c1
        T3[1] = -s23 * c1
        T3[2] = s1
        T3[3] =c1 * (a3 * c23 + a2 * c2)
        T3[4] = c23 * s1
        T3[5] = -s23 * s1
        T3[6] = -c1
        T3[7] =s1 * (a3 * c23 + a2 * c2)
        T3[8] = s23
        T3[9] = c23
        T3[10] = 0
        T3[11] = d1 + a3 * s23 + a2 * s2
        T3[12] = 0
        T3[13] = 0
        T3[14] = 0
        T3[15] =1
        result.append(("T3",T3))
        #01T*12T*23T*34T=04T
        T4[0] = c234 * c1
        T4[1] = s1
        T4[2] = s234 * c1
        T4[3] =c1 * (a3 * c23 + a2 * c2) + d4 * s1
        T4[4] = c234 * s1
        T4[5] = -c1
        T4[6] = s234 * s1
        T4[7] =s1 * (a3 * c23 + a2 * c2) - d4 * c1
        T4[8] = s234
        T4[9] = 0
        T4[10] = -c234
        T4[11] =d1 + a3 * s23 + a2 * s2
        T4[12] =0
        T4[13] = 0
        T4[14] = 0
        T4[15] = 1
        result.append(("T4",T4))
        #01T*12T*23T*34T*45T=05T
        T5[0] = s1 * s5 + c234 * c1 * c5
        T5[1] = -s234 * c1
        T5[2] = c5 * s1 - c234 * c1 * s5
        T5[3] =c1 * (a3 * c23 + a2 * c2) + d4 * s1 + d5 * s234 * c1
        T5[4] = c234 * c5 * s1 - c1 * s5
        T5[5] = -s234 * s1
        T5[6] = - c1 * c5 - c234 * s1 * s5
        T5[7] =s1 * (a3 * c23 + a2 * c2) - d4 * c1 + d5 * s234 * s1
        T5[8] =  s234 * c5
        T5[9] = c234
        T5[10] = -s234 * s5
        T5[11] = d1 + a3 * s23 + a2 * s2 - d5 * c234
        T5[12] = 0
        T5[13] = 0
        T5[14] = 0
        T5[15] =1
        result.append(("T5",T5))
        #01T*12T*23T*34T*45T*56T=06T
        T6[0] =   c6 * (s1 * s5 + c234 * c1 * c5) - s234 * c1 * s6
        T6[1] = - s6 * (s1 * s5 + c234 * c1 * c5) - s234 * c1 * c6
        T6[2] = c5 * s1 - c234 * c1 * s5
        T6[3] =d6 * (c5 * s1 - c234 * c1 * s5) + c1 * (a3 * c23 + a2 * c2) + d4 * s1 + d5 * s234 * c1
        T6[4] = - c6 * (c1 * s5 - c234 * c5 * s1) - s234 * s1 * s6
        T6[5] = s6 * (c1 * s5 - c234 * c5 * s1) - s234 * c6 * s1
        T6[6] = - c1 * c5 - c234 * s1 * s5
        T6[7] =s1 * (a3 * c23 + a2 * c2) - d4 * c1 - d6 * (c1 * c5 + c234 * s1 * s5) + d5 * s234 * s1
        T6[8] =c234 * s6 + s234 * c5 * c6
        T6[9] = c234 * c6 - s234 * c5 * s6
        T6[10] = -s234 * s5
        T6[11] = d1 + a3 * s23 + a2 * s2 - d5 * c234 - d6 * s234 * s5
        T6[12] = 0
        T6[13] = 0
        T6[14] = 0
        T6[15] = 1
        result.append(("T6", T6))
        return result
    def Iverse(self,T,q6_des):
        q_sols=[0]*48
        num_sols = 0
        T02 = - T[0]
        T00 = T[1]
        T01 = T[2]
        T03 = -T[3]
        T12 = - T[4]
        T10 = T[5]
        T11 = T[6]
        T13 = - T[7]
        T22 = T[8]
        T20 = - T[9]
        T21 = - T[10]
        T23 = T[11]

        #####shoulder rotate  joint(q1) ###########################
        q1=[0,0]
        A = d6 * T12 - T13
        B = d6 * T02 - T03
        R = A * A + B * B
        if math.fabs(A) < ZERO_THRESH:
            if math.fabs(math.fabs(d4) - math.fabs(B)) < ZERO_THRESH:
                div = -self.SIGN(d4) * self.SIGN(B)
            else:
                div = -d4 / B
            arcsin = math.asin(div)
            if math.fabs(arcsin) < ZERO_THRESH:
                arcsin = 0.0
            if arcsin < 0.0:
                q1[0] = arcsin + 2.0 * PI
            else:
                q1[0] = arcsin
                q1[1] = PI - arcsin
        elif math.fabs(B) < ZERO_THRESH:
            if math.fabs(math.fabs(d4) - math.fabs(A)) < ZERO_THRESH:
                div = self.SIGN(d4) * self.SIGN(A)
            else:
                div = d4 / A
            arccos = math.acos(div)
            q1[0] = arccos
            q1[1] = 2.0 * PI - arccos
        elif d4 * d4 > R:
            return num_sols
        else:
            arccos = math.acos(d4 / math.sqrt(R))
            arctan = math.atan2(-B, A)
            pos = arccos + arctan
            neg = -arccos + arctan
            if math.fabs(pos) < ZERO_THRESH:
                pos = 0.0
            if math.fabs(neg) < ZERO_THRESH:
                neg = 0.0
            if pos >= 0.0:
                q1[0] = pos
            else:
                q1[0] = 2.0 * PI + pos
            if neg >= 0.0:
                q1[1] = neg
            else:
                q1[1] = 2.0 * PI + neg

        ###### wrist2  joint(q5) ##########################
        q5=numpy.zeros((2,2))#define 2*2 q5 array

        for i in range(2):
            numer = (T03 * math.sin(q1[i]) - T13 * math.cos(q1[i]) - d4)
            if math.fabs(math.fabs(numer) - math.fabs(d6)) < ZERO_THRESH:
                div = self.SIGN(numer) * self.SIGN(d6)
            else:
                div = numer / d6
            arccos = math.acos(div)
            q5[i][0] = arccos
            q5[i][1] = 2.0 * PI - arccos
        #############################################################
        for i in range(2):
            for j in range(2):
                c1 = math.cos(q1[i])
                s1 = math.sin(q1[i])
                c5 = math.cos(q5[i][j])
                s5 = math.sin(q5[i][j])
                ######################## wrist 3 joint (q6) ################################
                if math.fabs(s5) < ZERO_THRESH:
                    q6 = q6_des
                else:
                    q6 = math.atan2(self.SIGN(s5) * -(T01 * s1 - T11 * c1),self.SIGN(s5) * (T00 * s1 - T10 * c1))
                    if math.fabs(q6) < ZERO_THRESH:
                        q6 = 0.0
                    if (q6 < 0.0):
                        q6 += 2.0 * PI
                q2=[0,0]
                q3=[0,0]
                q4=[0,0]
                #####################RRR joints (q2, q3, q4) ################################
                c6 = math.cos(q6)
                s6 = math.sin(q6)
                x04x = -s5 * (T02 * c1 + T12 * s1) - c5 * (s6 * (T01 * c1 + T11 * s1) - c6 * (T00 * c1 + T10 * s1))
                x04y = c5 * (T20 * c6 - T21 * s6) - T22 * s5
                p13x = d5 * (s6 * (T00 * c1 + T10 * s1) + c6 * (T01 * c1 + T11 * s1)) - d6 * (T02 * c1 + T12 * s1) +T03 * c1 + T13 * s1
                p13y = T23 - d1 - d6 * T22 + d5 * (T21 * c6 + T20 * s6)
                c3 = (p13x * p13x + p13y * p13y - a2 * a2 - a3 * a3) / (2.0 * a2 * a3)
                if math.fabs(math.fabs(c3) - 1.0) < ZERO_THRESH:
                    c3 = self.SIGN(c3)
                elif math.fabs(c3) > 1.0:
                    # TODO NO SOLUTION
                    continue
                arccos = math.acos(c3)
                q3[0] = arccos
                q3[1] = 2.0 * PI - arccos
                denom = a2 * a2 + a3 * a3 + 2 * a2 * a3 * c3
                s3 = math.sin(arccos)
                A = (a2 + a3 * c3)
                B = a3 * s3
                q2[0] = math.atan2((A * p13y - B * p13x) / denom, (A * p13x + B * p13y) / denom)
                q2[1] = math.atan2((A * p13y + B * p13x) / denom, (A * p13x - B * p13y) / denom)
                c23_0 = math.cos(q2[0] + q3[0])
                s23_0 = math.sin(q2[0] + q3[0])
                c23_1 = math.cos(q2[1] + q3[1])
                s23_1 = math.sin(q2[1] + q3[1])
                q4[0] = math.atan2(c23_0 * x04y - s23_0 * x04x, x04x * c23_0 + x04y * s23_0)
                q4[1] = math.atan2(c23_1 * x04y - s23_1 * x04x, x04x * c23_1 + x04y * s23_1)
                ###########################################
                for k in range(2):
                    if math.fabs(q2[k]) < ZERO_THRESH:
                        q2[k] = 0.0
                    elif q2[k] < 0.0:
                        q2[k] += 2.0 * PI
                    if math.fabs(q4[k]) < ZERO_THRESH:
                        q4[k] = 0.0
                    elif q4[k] < 0.0:
                        q4[k] += 2.0 * PI
                    q_sols[num_sols * 6 + 0] = q1[i]
                    q_sols[num_sols * 6 + 1] = q2[k]
                    q_sols[num_sols * 6 + 2] = q3[k]
                    q_sols[num_sols * 6 + 3] = q4[k]
                    q_sols[num_sols * 6 + 4] = q5[i][j]
                    q_sols[num_sols * 6 + 5] = q6
                    num_sols+=1
        return num_sols,q_sols
    """
    q_inverse:ur kinematics solution joint q
    q_last:last joint q
    """
    def solve_2pi_pro(self,q_inverse,q_last):
        if abs(q_inverse-PI*2.0-q_last)<abs(q_inverse-q_last):
            q_inverse-=PI*2.0
            return q_inverse
        else:
            return q_inverse
    #ik_fk,1:ik,0:fk
    def display(self,q,q6_des,ik_fk):
        T = self.Forward(q)
        result_list=[]
        #q_sols=[0]*48
        num_sols, q_sols = self.Iverse(T, q6_des)
        j=0
        if ik_fk==1:
            for i in range(num_sols):
                print i+1,"th solution"
                print q_sols[j],q_sols[j+1],q_sols[j+2],q_sols[j+3],q_sols[j+4],q_sols[j+5]
                print "solve 2 pi pro"
                print self.solve_2pi_pro(q_sols[j],q[0]),self.solve_2pi_pro(q_sols[j+1],q[1]),self.solve_2pi_pro(q_sols[j+2],q[2]),self.solve_2pi_pro(q_sols[j+3],q[3]),\
                    self.solve_2pi_pro(q_sols[j+4], q[4]),self.solve_2pi_pro(q_sols[j+5],q[5])
                j+=6
            print "you have ",num_sols,"solutions"
        elif ik_fk==0:
            for i in range(4):
                print T[j],T[j+1],T[j+2],T[j+3]
                j+=4
        else:
            print "######################forward solution######################"
            for i in range(4):
                print T[j],T[j+1],T[j+2],T[j+3]
                j+=4
            print "######################inverse solutions#####################"
            j=0
            for i in range(num_sols):
                print i+1,"th solution"
                print q_sols[j],q_sols[j+1],q_sols[j+2],q_sols[j+3],q_sols[j+4],q_sols[j+5]
                result_list.append([q_sols[j],q_sols[j+1],q_sols[j+2],q_sols[j+3],q_sols[j+4],q_sols[j+5]])
                j+=6
            print result_list
            return result_list
            print "you have ",num_sols,"solutions"
    """
    q:last time joint q
    """
    def get_ik_data(self,T,q):
        #T = self.Forward()
        result_list=[]
        #q_sols=[0]*48
        # print "T",T
        num_sols, q_sols = self.Iverse(T, 0)
        # print "num_sols, q_sols",num_sols, q_sols
        j = 0
        for i in range(num_sols):
            result_list.append([self.solve_2pi_pro(q_sols[j],q[0]),self.solve_2pi_pro(q_sols[j+1],q[1]),self.solve_2pi_pro(q_sols[j+2],q[2]),self.solve_2pi_pro(q_sols[j+3],q[3]),\
                    self.solve_2pi_pro(q_sols[j+4], q[4]),self.solve_2pi_pro(q_sols[j+5],q[5])])
            j += 6
        # print result_list
        return result_list

    def best_sol(self,weights,q_guess,T):
        #q_guess=q
        sols=self.get_ik_data(T,q_guess)
        # print "sols",sols
        valid_sols = []
        for sol in sols:
            test_sol = numpy.ones(6) * 9999.
            for i in range(6):
                for add_ang in [-2. * numpy.pi, 0, 2. * numpy.pi]:
                    test_ang = sol[i] + add_ang
                    if (abs(test_ang) <= 2. * numpy.pi and
                            abs(test_ang - q_guess[i]) < abs(test_sol[i] - q_guess[i])):
                        test_sol[i] = test_ang
            if numpy.all(test_sol != 9999.):
                valid_sols.append(test_sol)
        if len(valid_sols) == 0:
            return None
        best_sol_ind = numpy.argmin(numpy.sum((weights * (valid_sols - numpy.array(q_guess))) ** 2, 1))
        print "#########################the best sol##################"
        print valid_sols[best_sol_ind]
        return valid_sols[best_sol_ind]

    def best_sol_for_other_py(self,weights,q_guess,T):
        sols=self.get_ik_data(T)
        valid_sols = []
        for sol in sols:
            test_sol = numpy.ones(6) * 9999.
            for i in range(6):
                for add_ang in [-2. * numpy.pi, 0, 2. * numpy.pi]:
                    test_ang = sol[i] + add_ang
                    if (abs(test_ang) <= 2. * numpy.pi and
                            abs(test_ang - q_guess[i]) < abs(test_sol[i] - q_guess[i])):
                        test_sol[i] = test_ang
            if numpy.all(test_sol != 9999.):
                valid_sols.append(test_sol)
        if len(valid_sols) == 0:
            return None
        best_sol_ind = numpy.argmin(numpy.sum((weights * (valid_sols - numpy.array(q_guess))) ** 2, 1))
        print "#########################the best sol##################"
        print valid_sols[best_sol_ind].tolist()
        #print best_sol_ind
        print sols[best_sol_ind]
        return valid_sols[best_sol_ind].tolist()

def main():
    q = [0, 0, 1, 0, 1, 0]
    q1=[-1.5654299894915982, -1.6473701635943812, 0.05049753189086914, -1.4097726980792444, -1.140495349565615, -0.8895475069154913]
    q2=[-0.25277, -0.8561733333333333, 1.2195411111111112, -3.557096666666667, -1.3205444444444445, -1.1349355555555556]
    q3=[0,0,0,0,0,0]
    q4=[3.3985266666666667, -1.3765411111111112, -1.944881111111111, 0.14112555555555556, -4.9428833333333335, 5.663687777777778]
    q5=[-3.59860155164,-1.82648800883,-1.41735542252,0.0812199084238,1.27000134315,0.734254316924]
    # q5=[-3.66249992472,-1.27642603705,-1.9559700595,0.0701396996895,1.3338858418,0.73287290524]
    c=Kinematic()
    # c.display(q5,0,3)
    weights=[1.] * 6
    T=[-0.13464668997929136, 0.9394821469191765, -0.3150294660785803, 0.0, 0.13751164454300352, 0.3325644757714387, 0.9330012953206159, 0.0, 0.981305669245164, 0.08230531620134232, -0.17396844090897007, 0.5790479214783786, 0.0, 0.0, 0.0, 1.0]
    print c.Iverse(T,q5)
    # c.best_sol(weights,q5,c.Forward(q5))
    # c.best_sol_for_other_py(weights,q,c.Forward())
    # print type(c.Forward())
    #c.best_sol_new(c.Forward(q2))
if __name__ == '__main__':
    main()