MAGIKS  1.1
Manipulator General Inverse Kinematic Solver
 All Classes Namespaces Files Functions Variables Pages
pr2_symbolics.py
Go to the documentation of this file.
1 ## @file PR2_symbolics.py
2 # @brief Contains functions to represent symbolic formulations of pr2 kinematics
3 # @author Nima Ramezani Taghiabadi
4 #
5 # PhD Researcher
6 # Faculty of Engineering and Information Technology
7 # University of Technology Sydney (UTS)
8 # Broadway, Ultimo, NSW 2007, Australia
9 # Phone No. : 04 5027 4611
10 # Email(1) : nima.ramezani@gmail.com
11 # Email(2) : Nima.RamezaniTaghiabadi@uts.edu.au
12 # @version 2.0
13 #
14 # Last Revision: 03 January 2015
15 
16 from sympy import Symbol, simplify
17 
19  '''
20  This class provides a parametric representation of the kinematics of PR2 arm
21  The position, orientation and the Jacobian can be expressed in terms of DH parameters and sine and cosine of the joint angles
22  It uses sympy as a tool for symbols algebra
23  '''
24  def __init__(self):
25 
26  n = 7
27 
28  c = [Symbol('c' + str(i)) for i in range(n)]
29  s = [Symbol('s' + str(i)) for i in range(n)]
30  a = [Symbol('a0'), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
31  d = [0.0, 0.0, Symbol('d2'), 0.0, Symbol('d4'), 0.0, 0.0]
32  alpha = [- math.pi/2, math.pi/2, - math.pi/2, math.pi/2, - math.pi/2, math.pi/2, 0.0]
33 
34  ca = [math.cos(alpha[i]) for i in range(n)]
35  sa = [math.sin(alpha[i]) for i in range(n)]
36 
37  for i in range(len(ca)):
38  ca[i] = gen.round(ca[i])
39  sa[i] = gen.round(sa[i])
40 
41  # A[i] transfer matrix from link i-1 to i according to standard DH parameters:
42  self.A = [numpy.array([[ c[i], -ca[i]*s[i], sa[i]*s[i], a[i]*c[i] ],
43  [ s[i], ca[i]*c[i], -sa[i]*c[i], a[i]*s[i] ],
44  [ 0 , sa[i] , ca[i] , d[i] ],
45  [ 0 , 0 , 0 , 1 ]]) for i in range(n)]
46 
47  # B[i] transfer matrix from link i to i-1 or B[i] = inv(A[i])
48  self.B = [numpy.array([[ c[i], s[i], 0 , 0 ],
49  [ -ca[i]*s[i], ca[i]*c[i], sa[i] , -d[i]*sa[i] ],
50  [ ca[i]*s[i], -sa[i]*c[i], ca[i] , -d[i]*ca[i] ],
51  [ 0 , 0 , 0 , 1 ]]) for i in range(n)]
52 
53  # R[i] rotation matrix from link i-1 to i according to standard DH parameters:
54  self.R = [numpy.array([[ c[i], -ca[i]*s[i], sa[i]*s[i]],
55  [ s[i], ca[i]*c[i], -sa[i]*c[i]],
56  [ 0 , sa[i] , ca[i] ]]) for i in range(n)]
57 
58  # T[i] transfer matrix from link -1(ground) to i
59  self.T = numpy.copy(self.A)
60  for i in range(n-1):
61  self.T[i + 1] = numpy.dot(self.T[i],self.A[i + 1])
62 
63  # Desired Pose:
64  T_d = numpy.array([[ Symbol('r11'), Symbol('r12') , Symbol('r13') , Symbol('px') ],
65  [ Symbol('r21'), Symbol('r22') , Symbol('r23') , Symbol('py') ],
66  [ Symbol('r31'), Symbol('r32') , Symbol('r33') , Symbol('pz') ],
67  [ 0 , 0 , 0 , 1 ]])
68 
69  self.x_d = T_d[0:3, 3]
70  self.R_d = T_d[0:3, 0:3]
71 
72  '''
73  "p_W" denotes the position vector of the wrist joint center
74  "R_W" denotes the orientation of the gripper (Endeffector Orientation)
75  '''
76  self.T_W = self.T[6]
77  self.p_W = self.T_W[0:3, 3]
78  self.R_W = self.T_W[0:3, 0:3]
79 
80  '''
81  "p_EF_W" denotes the position of the arm endeffector (end of the gripper) relative to the wrist joint center
82  in the coordinates system of the right gripper.
83  '''
84 
85  self.p_EF_W = numpy.array([0.0, 0.0, Symbol('d7')])
86 
87  self.H = numpy.copy(self.T)
88  self.H[n - 1] = numpy.copy(T_d)
89 
90  # H[i] transfer matrix from link -1(ground) to i calculated from inverse transform
91  for i in range(n-1):
92  self.H[n - i - 2] = numpy.dot(self.H[n - i - 1], self.B[n - i - 1])
93 
94  self.div_theta_err = sympy.Matrix([
95  [ 0 , 0 , -2*d[2]*d[4]*s[3] , 0 , 0 , 0 ],
96  [0 , - 2*c[2]*s[2]*s[3]**2 , Symbol('e23') , 0 , 0 , 0 ],
97  [Symbol('e31') , d[4]*Symbol('s321') , Symbol('e33') , 0 , 0 , 0 ],
98  [Symbol('e41') , Symbol('e42') , Symbol('e43') , 0 , - s[5] , 0 ],
99  [Symbol('e51') , Symbol('e52') , 0 , c[4]*s[5] , c[5]*s[4] , 0 ],
100  [Symbol('e61') , Symbol('e62') , Symbol('e63') , 0 , Symbol('c65') , - Symbol('s65') ]])
101 
102  self.div_phi_err = sympy.Matrix([Symbol('e10') , 0 , 0 , Symbol('e40') , Symbol('e50') , Symbol('e60') ])
103 
104  e = self.div_theta_err
105  J3 = - Symbol('e10')/e[0,2]
106  J2 = - e[1,2]*J3/e[1,1]
107  J1 = - (e[2,1]*J2 + e[2,2]*J3)/e[2,0]
108  J5 = - (Symbol('e40') + e[3,0]*J1 + e[3,1]*J2 + e[3,2]*J3)/e[3,4]
109  J4 = - (Symbol('e50') + e[4,0]*J1 + e[4,1]*J2 + e[4,4]*J5)/e[4,3]
110  J6 = - (Symbol('e60') + e[5,0]*J1 + e[5,1]*J2 + e[5,2]*J3 + e[5,3]*J4 + e[5,4]*J5)/ e[5,5]
111 
112  self.RJ = sympy.Matrix([J1,J2,J3,J4,J5,J6])
113  #self.redundancy_jacobian = self.div_theta_err.inv().transpose()*self.div_phi_err
114 
115 class PR2_Symbolic():
116  '''
117  This class provides a parametric representation of the kinematics of PR2 robot
118  The position, orientation and the Jacobian can be expressed in terms of the kinematic parameters of the robot
119  It uses sympy as a tool for symbols algebra
120  '''
121  def __init__(self):
122 
123  c = [Symbol('c' + str(i)) for i in range(7)]
124  s = [Symbol('s' + str(i)) for i in range(7)]
125  S = [Symbol('S' + str(i)) for i in range(7)]
126  C = [Symbol('C' + str(i)) for i in range(7)]
127  phi = [Symbol('p' + str(i)) for i in range(5)]
128 
129  a = [Symbol('a0'), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
130  d = [0.0, 0.0, Symbol('d2'), 0.0, Symbol('d4'), 0.0, 0.0]
131 
132  self.right_arm = armlib.PR2_Arm_Symbolic()
133 
134  '''
135  we compromize that capital letters are used for the base
136  so X,Y,Z represent the position of the base
137  and C,S represent sin(theta) and cos(theta) where theta is the rotation of base around z axis
138  '''
139  self.p_EFR_WR = numpy.array([0.0 , 0.0 , Symbol('d7')])
140  self.p_BO = numpy.array([Symbol('X') , Symbol('Y') , Symbol('Z')])
141  self.p_BR_BO = numpy.array([Symbol('b0') , Symbol('l0'), Symbol('h')])
142  self.p_BL_BO = numpy.array([Symbol('b0') ,- Symbol('l0'), Symbol('h')])
143  self.R_B = numpy.array([[ Symbol('C'), Symbol('S') , 0.0 ],
144  [-Symbol('S'), Symbol('C') , 0.0 ],
145  [ 0.0 , 0.0 , 1.0]])
146  '''
147  RRd and LRd represent the desired orientation of the right and left arm grippers respectively
148  '''
149 
150  T_EFR = numpy.array([[ Symbol('nx'), Symbol('sx') , Symbol('ax') , Symbol('xd') ],
151  [ Symbol('ny'), Symbol('sy') , Symbol('ay') , Symbol('yd') ],
152  [ Symbol('nz'), Symbol('sz') , Symbol('az') , Symbol('zd') ],
153  [ 0.0 , 0.0 , 0.0 , 1.0 ]])
154 
155  self.p_EFR = T_EFR[0:3, 3]
156  self.R_EFR = T_EFR[0:3, 0:3]
157 
158  self.p_WR_BR = - self.p_BR_BO + numpy.dot(self.R_B.T,(self.p_EFR - self.p_BO - numpy.dot(self.R_EFR, self.right_arm.p_EF_W)))
159  self.R_WR_B = numpy.dot(self.R_B.T, self.R_EFR)
160 
161  import sympy
162 
163  self.div_theta_e = sympy.Matrix([
164  [0 , 0 , -2*Symbol('d42')*s[3] , 0 , 0 , 0 , 0 , 0 , 0 ],
165  [0 , Symbol('e22') , Symbol('e23') , 0 , 0 , 0 , 0 , 0 , 0 ],
166  [Symbol('e31') , d[4]*Symbol('s321') , Symbol('e33') , 0 , 0 , 0 , 1 , 0 , 0 ],
167  [Symbol('e41') , Symbol('e42') , Symbol('e43') , 0 , - s[5] , 0 , 0 , 0 , 0 ],
168  [Symbol('e51') , Symbol('e52') , 0 , c[4]*s[5] , c[5]*s[4] , 0 , 0 , 0 , 0 ],
169  [Symbol('e61') , Symbol('e62') , Symbol('e63') , 0 , Symbol('c65') , - Symbol('s65') , 0 , 0 , 0 ],
170  [0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 ],
171  [0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 ],
172  [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ]])
173 
174  self.div_phi_e = sympy.Matrix([
175  [ Symbol('z11') , Symbol('z12') , -2*phi[3] , Symbol('z14') , 0 ],
176  [ 0 , Symbol('z22') , Symbol('z23') , 0 , 0 ],
177  [ 0 , 0 , 0 , 0 , 0 ],
178  [ Symbol('z41') , 0 , 0 , 0 , - Symbol('z41') ],
179  [ Symbol('z51') , 0 , 0 , 0 , - Symbol('z51') ],
180  [ Symbol('z61') , 0 , 0 , 0 , - Symbol('z61') ],
181  [ 0 , 0 , 1 , 0 , 0 ],
182  [ 0 , Symbol('z82') , 0 , Symbol('z84') , Symbol('z85') ],
183  [ 0 , Symbol('z92') , 0 , Symbol('z94') , Symbol('z95') ]])
184 
185  self.redundancy_jacobian = sympy.Matrix([
186  [Symbol('J' + str(j+1) + str(i+1)) for i in range(5)] for j in range(9)])
187