WUT Velma robot API
velma_ik_geom.py
Go to the documentation of this file.
1 
4 
5 # Copyright (c) 2021, Robot Control and Pattern Recognition Group,
6 # Institute of Control and Computation Engineering
7 # Warsaw University of Technology
8 #
9 # All rights reserved.
10 #
11 # Redistribution and use in source and binary forms, with or without
12 # modification, are permitted provided that the following conditions are met:
13 # * Redistributions of source code must retain the above copyright
14 # notice, this list of conditions and the following disclaimer.
15 # * Redistributions in binary form must reproduce the above copyright
16 # notice, this list of conditions and the following disclaimer in the
17 # documentation and/or other materials provided with the distribution.
18 # * Neither the name of the Warsaw University of Technology nor the
19 # names of its contributors may be used to endorse or promote products
20 # derived from this software without specific prior written permission.
21 #
22 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 # DISCLAIMED. IN NO EVENT SHALL <COPYright HOLDER> BE LIABLE FOR ANY
26 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #
33 # Author: Dawid Seredynski
34 #
35 
36 import PyKDL
37 import math
38 
39 from urdf_parser_py.urdf import URDF
40 from pykdl_utils.kdl_parser import kdl_tree_from_urdf_model
41 
42 def wrapAngle(angle):
43  while angle > math.pi:
44  angle = angle - 2.0*math.pi
45  while angle < -math.pi:
46  angle = angle + 2.0*M_PI
47  return angle
48 
50  """!
51  Kinematics solver (FK, IK) for Kuka LWR 4+
52  """
53 
54  def __init__(self):
55  """!
56  Initialization.
57  """
58  self.__A = 0.078
59  self.__B = 0.39
60  self.__C = 0.2
61  self.__D = 0.3105
62  self.__arm_len_a = 2*self.__C
63  self.__arm_len_b = self.__B
64  self.__debug = {}
65 
66  self.m_lim_lo = [-2.96, -2.09, -2.96, -2.095, -2.96, -2.09, -2.96]
67  self.m_lim_up = [2.96, 2.09, 2.96, 2.095, 2.96, 2.09, 2.96]
68 
69  def getLimits(self):
70  return zip(self.m_lim_lo, self.m_lim_up)
71 
72  def getDebug(self, key):
73  """!
74  Get some debug information after solving inverse kinematics.
75 
76  @param key string: one of values: 'T_A0_A6d', 'pt_shoulder', 'elbow_pt'.
77 
78  @return Value for the given key or None, if the key does not exist.
79  """
80 
81  if key in self.__debug:
82  return self.__debug[key]
83  else:
84  return None
85 
86  def __calcQ3(self, dist):
87  a = self.__arm_len_a
88  b = self.__arm_len_b
89  acos_val = (a**2 + b**2 - dist**2) / (2*a*b)
90  if abs(acos_val) <= 1.0:
91  return math.pi - math.acos( acos_val )
92  else:
93  #print('ERROR: Could not compute arccos of {} = ({}**2 + {}**2 - {}**2) / (2*{}*{})'.format(acos_val, a, b, dist, a, b))
94  pass
95  # raise Exception('Could not compute arccos of {} = ({}**2 + {}**2 - {}**2) / (2*{}*{})'.format(acos_val, a, b, dist, a, b))
96  return None
97 
98  def __heronArea(self, a, b, c):
99  s = (a+b+c)/2.0
100  val = s*(s-a)*(s-b)*(s-c)
101  if val < 0:
102  raise Exception('Square root of negative number: {} = {}*({}-{})*({}-{})*({}-{})'.format(val, s, s, a, s, b, s, c))
103  return math.sqrt(val)
104 
105  def __calculateIkPart1(self, T_A0_A6d, elbow_circle_angle, flip_shoulder, flip_elbow):
106 
107  pt_shoulder = PyKDL.Vector(0, 0, self.__D)
108  dir_vec = T_A0_A6d.p - pt_shoulder;
109  dist = dir_vec.Norm()
110  q3 = self.__calcQ3(dist)
111 
112  if q3 is None:
113  return None, None, None, None
114 
115  area = self.__heronArea(dist, self.__arm_len_a, self.__arm_len_b)
116  height = area / (0.5*dist)
117  dist_a = math.sqrt( self.__arm_len_a**2 - height**2 )
118 
119  # The elbow circle angle is calculated wrt the axis of the first joint of the arm.
120  # This is the parameter for IK that deals with redundancy problem.
121 
122  shoulder_vec = pt_shoulder - PyKDL.Vector()
123  nz = dir_vec * 1.0
124  nx = shoulder_vec * 1.0
125  ny = nz*nx
126  nx = ny*nz
127  nx.Normalize()
128  ny.Normalize()
129  nz.Normalize()
130  shoulder_frame = PyKDL.Frame( PyKDL.Rotation(nx, ny, nz), pt_shoulder )
131  shoulder_frame_rot = shoulder_frame * PyKDL.Frame( PyKDL.Rotation.RotZ(elbow_circle_angle), PyKDL.Vector() )
132  elbow_pt = shoulder_frame_rot * PyKDL.Vector(height, 0, dist_a)
133  elbow_vec = elbow_pt - pt_shoulder
134  q0 = math.atan2(-elbow_pt.y(), -elbow_pt.x())
135 
136  q1 = -math.atan2(math.sqrt(elbow_vec.x()**2 + elbow_vec.y()**2), elbow_vec.z())
137 
138  # Calculate q2:
139  # Project dir_vec to frame of right_arm_2_link, and compute atan2(-dir_vec.y(), -dir_vec.x())
140 
141  nx = shoulder_vec * 1.0
142  nz = elbow_vec * 1.0
143  ny = nz*nx
144  nx = ny*nz
145  nx.Normalize()
146  ny.Normalize()
147  nz.Normalize()
148  T_A0_A2 = PyKDL.Frame( PyKDL.Rotation(nx, ny, nz), pt_shoulder )
149  dir_vec_A0 = dir_vec
150  dir_vec_A2 = T_A0_A2.Inverse().M * dir_vec_A0
151  q2 = math.atan2(-dir_vec_A2.y(), -dir_vec_A2.x())
152 
153  # There are two alternative angles for q3
154  if flip_elbow:
155  q0 = math.pi + q0
156  q1 = -q1
157  q3 = -q3
158 
159  if flip_shoulder:
160  q0 = math.pi + q0
161  q1 = -q1
162  q2 = math.pi + q2
163 
164  # These points are saved for debugging
165  self.__debug['pt_shoulder'] = pt_shoulder
166  self.__debug['elbow_pt'] = elbow_pt
167  #self.__debug['ee_pt'] = ee_pt
168 
169  q0 = wrapAngle(q0)
170  q1 = wrapAngle(q1)
171  q2 = wrapAngle(q2)
172  q3 = wrapAngle(q3)
173  if q0 < self.m_lim_lo[0] or q0 > self.m_lim_up[0] or\
174  q1 < self.m_lim_lo[1] or q1 > self.m_lim_up[1] or\
175  q2 < self.m_lim_lo[2] or q2 > self.m_lim_up[2] or\
176  q3 < self.m_lim_lo[3] or q3 > self.m_lim_up[3]:
177  return None, None, None, None
178 
179  # else
180  return q0, q1, q2, q3
181 
182  def __calculateIkPart2(self, T_A0_A7d, q0, q1, q2, q3, flip_ee):
183 
184  #print T_A0_A7d
185  s1 = math.sin(q0)
186  c1 = math.cos(q0)
187  s2 = math.sin(q1)
188  c2 = math.cos(q1)
189  s3 = math.sin(q2)
190  c3 = math.cos(q2)
191  s4 = math.sin(q3)
192  c4 = math.cos(q3)
193  nx = T_A0_A7d.M.UnitX()
194  ny = T_A0_A7d.M.UnitY()
195  nz = T_A0_A7d.M.UnitZ()
196  r11 = nx.x()
197  r21 = nx.y()
198  r31 = nx.z()
199  r12 = ny.x()
200  r22 = ny.y()
201  r32 = ny.z()
202  r13 = nz.x()
203  r23 = nz.y()
204  r33 = nz.z()
205  px = T_A0_A7d.p.x()
206  py = T_A0_A7d.p.y()
207  pz = T_A0_A7d.p.z()
208 
209 
210  m02 = r13*((-s1*s3 + c1*c2*c3)*c4 + s2*s4*c1) + r23*((s1*c2*c3 + s3*c1)*c4 + s1*s2*s4) + r33*(-s2*c3*c4 + s4*c2)
211  m12 = r13*(-s1*c3 - s3*c1*c2) + r23*(-s1*s3*c2 + c1*c3) + r33*s2*s3
212  m20 = r11*(-(-s1*s3 + c1*c2*c3)*s4 + s2*c1*c4) + r21*(-(s1*c2*c3 + s3*c1)*s4 + s1*s2*c4) + r31*(s2*s4*c3 + c2*c4)
213  m21 = r12*(-(-s1*s3 + c1*c2*c3)*s4 + s2*c1*c4) + r22*(-(s1*c2*c3 + s3*c1)*s4 + s1*s2*c4) + r32*(s2*s4*c3 + c2*c4)
214  m22 = r13*(-(-s1*s3 + c1*c2*c3)*s4 + s2*c1*c4) + r23*(-(s1*c2*c3 + s3*c1)*s4 + s1*s2*c4) + r33*(s2*s4*c3 + c2*c4)
215 
216  #tg7 = s7/c7 = -m[2,1]/m[2,0]
217  q6 = math.atan2(m21, -m20)
218 
219  #tg5 = s5/c5 = m[1,2]/m[0,2]
220  q4 = math.atan2(m12, m02)
221 
222  #tg6 = s6/c6 = m[2,1]/(s7*m[2,2])
223  q5 = math.atan2(m21, math.sin(q6)*m22)
224  if m21 < 0:
225  # This is tricky
226  q5 = q5 + math.pi
227 
228  if flip_ee:
229  q4 = q4 + math.pi
230  q5 = -q5
231  q6 = q6 + math.pi
232 
233  q4 = wrapAngle(q4)
234  q5 = wrapAngle(q5)
235  q6 = wrapAngle(q6)
236 
237  if q4 < self.m_lim_lo[4] or q4 > self.m_lim_up[4] or\
238  q5 < self.m_lim_lo[5] or q5 > self.m_lim_up[5] or\
239  q6 < self.m_lim_lo[6] or q6 > self.m_lim_up[6]:
240  return None, None, None
241  # else
242  return q4, q5, q6
243 
244  def calculateIk(self, T_A0_A7d, elbow_circle_angle, flip_shoulder, flip_elbow, flip_ee):
245  """!
246  Calculate inverse kinematics (IK) for Kuka LWR 4+.
247 
248  @param T_A0_A7d PyKDL.Frame: pose of the end-effector (the last link) wrt. the base of arm
249  (the first link).
250  @param elbow_circle_angle float: IK parameter.
251  @param flip_shoulder bool: IK parameter.
252  @param flip_elbow bool: IK parameter.
253  @param flip_ee bool: IK parameter.
254 
255  @return 7-tuple: arm configuration or a tuple of Nones, if the solution does not exist.
256  """
257 
258  self.__debug = {}
259  T_A6_A7 = PyKDL.Frame(PyKDL.Rotation(), PyKDL.Vector(0, 0, self.__A))
260  T_A7_A6 = T_A6_A7.Inverse()
261  T_A0_A6d = T_A0_A7d * T_A7_A6
262  self.__debug['T_A0_A6d'] = T_A0_A6d
263  q0, q1, q2, q3 = self.__calculateIkPart1(T_A0_A6d, elbow_circle_angle, flip_shoulder, flip_elbow)
264  if q0 is None:
265  return None, None, None, None, None, None, None
266  # else
267  q4, q5, q6 = self.__calculateIkPart2(T_A0_A7d, q0, q1, q2, q3, flip_ee)
268  if q4 is None:
269  return None, None, None, None, None, None, None
270  # else
271  return q0, q1, q2, q3, q4, q5, q6
272 
273  def calculateIkSet(self, T_A0_A7d, elbow_circle_angles):
274  """!
275  Calculate inverse kinematics (IK) for Kuka LWR 4+.
276 
277  @param T_A0_A7d PyKDL.Frame: pose of the end-effector (the last link) wrt. the base of arm
278  (the first link).
279  @param elbow_circle_angles list of float: list of values for IK parameter: elbow_circle_angle (@see calculateIk).
280 
281  @return list of 7-tuples: arm configurations.
282  """
283  flips = [(False, False, False), (False, False, True), (False, True, False),
284  (False, True, True), (True, False, False), (True, False, True), (True, True, False),
285  (True, True, True)]
286  solutions = []
287  for elbow_circle_angle in elbow_circle_angles:
288  for flip_shoulder, flip_elbow, flip_ee in flips:
289  q = self.calculateIk(T_A0_A7d, elbow_circle_angle, flip_shoulder, flip_elbow,
290  flip_ee)
291  print('calculateIkSet: {}, {}, {}, {}'.format(elbow_circle_angle, flip_shoulder,
292  flip_elbow, flip_ee))
293  print(' {}'.format(q))
294  if not q[0] is None:
295  solutions.append( q )
296  return solutions
297 
298  def calculateFk(self, q):
299  """!
300  Calculate forward kinematics (FK) for Kuka LWR 4+.
301 
302  @param q 7-tuple: arm configuration.
303 
304  @return PyKDL.Frame: pose of the last link wrt. the first link of the arm.
305  """
306  s1 = math.sin(q[0])
307  c1 = math.cos(q[0])
308  s2 = math.sin(q[1])
309  c2 = math.cos(q[1])
310  s3 = math.sin(q[2])
311  c3 = math.cos(q[2])
312  s4 = math.sin(q[3])
313  c4 = math.cos(q[3])
314  s5 = math.sin(q[4])
315  c5 = math.cos(q[4])
316  s6 = math.sin(q[5])
317  c6 = math.cos(q[5])
318  s7 = math.sin(q[6])
319  c7 = math.cos(q[6])
320 
321  A = self.__A
322  B = self.__B
323  C = self.__C
324  D = self.__D
325 
326  #m00 = -(((s4*s6 + c4*c5*c6)*c7 - s5*s7*c4)*s3 + (s5*c6*c7 + s7*c5)*c3)*s1 + (((s4*s6 + c4*c5*c6)*c7 - s5*s7*c4)*c2*c3 + ((s4*c5*c6 - s6*c4)*c7 - s4*s5*s7)*s2 - (s5*c6*c7 + s7*c5)*s3*c2)*c1
327  #m01 = -((-(s4*s6 + c4*c5*c6)*s7 - s5*c4*c7)*s3 + (-s5*s7*c6 + c5*c7)*c3)*s1 + ((-(s4*s6 + c4*c5*c6)*s7 - s5*c4*c7)*c2*c3 + (-(s4*c5*c6 - s6*c4)*s7 - s4*s5*c7)*s2 - (-s5*s7*c6 + c5*c7)*s3*c2)*c1
328  #m02 = -((-s4*c6 + s6*c4*c5)*s3 + s5*s6*c3)*s1 + ((-s4*c6 + s6*c4*c5)*c2*c3 + (s4*s6*c5 + c4*c6)*s2 - s3*s5*s6*c2)*c1
329  #m03 = -((-A*s4*c6 - B*s4 + A*s6*c4*c5)*s3 + A*s5*s6*c3)*s1 + ((-A*s4*c6 - B*s4 + A*s6*c4*c5)*c2*c3 + (A*s4*s6*c5 + A*c4*c6 + B*c4 + C)*s2 + C*s2 - A*s3*s5*s6*c2)*c1
330  #m10 = (((s4*s6 + c4*c5*c6)*c7 - s5*s7*c4)*s3 + (s5*c6*c7 + s7*c5)*c3)*c1 + (((s4*s6 + c4*c5*c6)*c7 - s5*s7*c4)*c2*c3 + ((s4*c5*c6 - s6*c4)*c7 - s4*s5*s7)*s2 - (s5*c6*c7 + s7*c5)*s3*c2)*s1
331  #m11 = ((-(s4*s6 + c4*c5*c6)*s7 - s5*c4*c7)*s3 + (-s5*s7*c6 + c5*c7)*c3)*c1 + ((-(s4*s6 + c4*c5*c6)*s7 - s5*c4*c7)*c2*c3 + (-(s4*c5*c6 - s6*c4)*s7 - s4*s5*c7)*s2 - (-s5*s7*c6 + c5*c7)*s3*c2)*s1
332  #m12 = ((-s4*c6 + s6*c4*c5)*s3 + s5*s6*c3)*c1 + ((-s4*c6 + s6*c4*c5)*c2*c3 + (s4*s6*c5 + c4*c6)*s2 - s3*s5*s6*c2)*s1
333  #m13 = ((-A*s4*c6 - B*s4 + A*s6*c4*c5)*s3 + A*s5*s6*c3)*c1 + ((-A*s4*c6 - B*s4 + A*s6*c4*c5)*c2*c3 + (A*s4*s6*c5 + A*c4*c6 + B*c4 + C)*s2 + C*s2 - A*s3*s5*s6*c2)*s1
334  #m20 = -((s4*s6 + c4*c5*c6)*c7 - s5*s7*c4)*s2*c3 + ((s4*c5*c6 - s6*c4)*c7 - s4*s5*s7)*c2 + (s5*c6*c7 + s7*c5)*s2*s3
335  #m21 = -(-(s4*s6 + c4*c5*c6)*s7 - s5*c4*c7)*s2*c3 + (-(s4*c5*c6 - s6*c4)*s7 - s4*s5*c7)*c2 + (-s5*s7*c6 + c5*c7)*s2*s3
336  #m22 = -(-s4*c6 + s6*c4*c5)*s2*c3 + (s4*s6*c5 + c4*c6)*c2 + s2*s3*s5*s6
337  #m23 = -(-A*s4*c6 - B*s4 + A*s6*c4*c5)*s2*c3 + (A*s4*s6*c5 + A*c4*c6 + B*c4 + C)*c2 + A*s2*s3*s5*s6 + C*c2 + D
338 
339  c4c5c6 = c4*c5*c6
340  c4c5s6 = s6*c4*c5
341  s4s6 = s4*s6
342  s5c6s7 = s5*s7*c6
343  c4s5s7 = s5*s7*c4
344  s4c6 = s4*c6
345  s5c6c7 = s5*c6*c7
346  c4s5c7 = s5*c4*c7
347  s4c5c6 = s4*c5*c6
348  s4s5c7 = s4*s5*c7
349  c5s7 = s7*c5
350  c4s6 = s6*c4
351  c3s5s6 = s5*s6*c3
352  s3s5s6 = s3*s5*s6
353  s2c3 = s2*c3
354  c5c7 = c5*c7
355  c2s3 = s3*c2
356  c4c6 = c4*c6
357  s4c5s6 = s4s6*c5
358  e1 = (s4s6 + c4c5c6)*c7
359  e2 = (s4s6 + c4c5c6)*s7
360  e3 = (s4c5c6 - c4s6)*s7
361  e4 = (s4c5c6 - c4s6)*c7
362  e6 = (-A*s4c6 - B*s4 + A*c4c5s6)
363  e8 = (A*s4c5s6 + A*c4c6 + B*c4 + C)
364  e9 = e6*c2*c3 + e8*s2 + C*s2 - A*s3s5s6*c2
365  m00 = -((e1 - c4s5s7)*s3 + (s5c6c7 + c5s7)*c3)*s1 + ((e1 - c4s5s7)*c2*c3 + (e4 - s4*s5*s7)*s2 - (s5c6c7 + c5s7)*c2s3)*c1
366  m01 = -((-e2 - c4s5c7)*s3 + (-s5c6s7 + c5c7)*c3)*s1 + ((-e2 - c4s5c7)*c2*c3 + (-e3 - s4s5c7)*s2 - (-s5c6s7 + c5c7)*c2s3)*c1
367  m02 = -((-s4c6 + c4c5s6)*s3 + c3s5s6)*s1 + ((-s4c6 + c4c5s6)*c2*c3 + (s4c5s6 + c4c6)*s2 - s3s5s6*c2)*c1
368  m03 = -(e6*s3 + A*c3s5s6)*s1 + e9*c1
369  m10 = ((e1 - c4s5s7)*s3 + (s5c6c7 + c5s7)*c3)*c1 + ((e1 - c4s5s7)*c2*c3 + (e4 - s4*s5*s7)*s2 - (s5c6c7 + c5s7)*c2s3)*s1
370  m11 = ((-e2 - c4s5c7)*s3 + (-s5c6s7 + c5c7)*c3)*c1 + ((-e2 - c4s5c7)*c2*c3 + (-e3 - s4s5c7)*s2 - (-s5c6s7 + c5c7)*c2s3)*s1
371  m12 = ((-s4c6 + c4c5s6)*s3 + c3s5s6)*c1 + ((-s4c6 + c4c5s6)*c2*c3 + (s4c5s6 + c4c6)*s2 - s3s5s6*c2)*s1
372  m13 = (e6*s3 + A*c3s5s6)*c1 + e9*s1
373  m20 = -(e1 - c4s5s7)*s2c3 + (e4 - s4*s5*s7)*c2 + (s5c6c7 + c5s7)*s2*s3
374  m21 = -(-e2 - c4s5c7)*s2c3 + (-e3 - s4s5c7)*c2 + (-s5c6s7 + c5c7)*s2*s3
375  m22 = -(-s4c6 + c4c5s6)*s2c3 + (s4c5s6 + c4c6)*c2 + s2*s3s5s6
376  m23 = -e6*s2c3 + e8*c2 + A*s2*s3s5s6 + C*c2 + D
377 
378  nx = PyKDL.Vector(m00, m10, m20)
379  ny = PyKDL.Vector(m01, m11, m21)
380  nz = PyKDL.Vector(m02, m12, m22)
381  return PyKDL.Frame( PyKDL.Rotation(nx, ny, nz), PyKDL.Vector(m03, m13, m23))
382 
383 
385  """!
386  Kinematics solver (FK, IK) for WUT Velma robot
387  """
388 
389  def __init__(self):
390  """!
391  Initialize.
392  """
393 
394  self.__robot = URDF.from_parameter_server()
395  self.__tree = kdl_tree_from_urdf_model(self.__robot)
396 
397  self.__chain_ar_base = self.__tree.getChain('torso_base', 'calib_right_arm_base_link')
398  self.__chain_al_base = self.__tree.getChain('torso_base', 'calib_left_arm_base_link')
399  self.__fk_kdl_ar_base = PyKDL.ChainFkSolverPos_recursive(self.__chain_ar_base)
400  self.__fk_kdl_al_base = PyKDL.ChainFkSolverPos_recursive(self.__chain_al_base)
401 
402  self.__T_Er_Gr = PyKDL.Frame( PyKDL.Rotation.RPY(0, math.pi/2, 0), PyKDL.Vector(0.235, 0, -0.078) )
403  self.__T_El_Gl = PyKDL.Frame( PyKDL.Rotation.RPY(0, -math.pi/2, 0), PyKDL.Vector(-0.235, 0, -0.078) )
404  self.__T_Er_Pr = PyKDL.Frame( PyKDL.Rotation.RPY(0, math.pi/2, 0), PyKDL.Vector(0.115, 0, -0.078) )
405  self.__T_El_Pl = PyKDL.Frame( PyKDL.Rotation.RPY(0, -math.pi/2, 0), PyKDL.Vector(-0.115, 0, -0.078) )
406  self.__T_Gr_Er = self.__T_Er_Gr.Inverse()
407  self.__T_Gl_El = self.__T_El_Gl.Inverse()
408  self.__T_Pr_Er = self.__T_Er_Pr.Inverse()
409  self.__T_Pl_El = self.__T_El_Pl.Inverse()
410 
412 
413  def getArmShoulderPosition(self, side_str, torso_angle):
414  """!
415  Calculate forward kinematics for shoulder.
416 
417  @param side_str string: either 'left' or 'right'.
418  @param torso_angle float: angle of torso joint.
419 
420  @return PyKDL.Frame: pose of the shoulder given by side_str.
421  """
422 
423  if side_str == 'left':
424  return self.getLeftArmShoulderPosition(torso_angle)
425  elif side_str == 'right':
426  return self.getRightArmShoulderPosition(torso_angle)
427  else:
428  raise Exception()
429 
430  def getLeftArmShoulderPosition(self, torso_angle):
431  """!
432  Calculate forward kinematics for left shoulder.
433 
434  @param torso_angle float: angle of torso joint.
435 
436  @return PyKDL.Frame: pose of the left shoulder.
437  """
438  T_B_A = self.getLeftArmBaseFk(torso_angle)
439  return T_B_A * PyKDL.Vector(0, 0, 0.2005+0.11)
440 
441  def getRightArmShoulderPosition(self, torso_angle):
442  """!
443  Calculate forward kinematics for right shoulder.
444 
445  @param torso_angle float: angle of torso joint.
446 
447  @return PyKDL.Frame: pose of the right shoulder.
448  """
449  T_B_A = self.getRightArmBaseFk(torso_angle)
450  return T_B_A * PyKDL.Vector(0, 0, 0.2005+0.11)
451 
452  def getArmBaseFk(self, side_str, torso_angle):
453  if side_str == 'left':
454  return self.getLeftArmBaseFk(torso_angle)
455  elif side_str == 'right':
456  return self.getRightArmBaseFk(torso_angle)
457  else:
458  raise Exception('Wrong side: "{}"'.format(side_str))
459 
460  def getLeftArmBaseFk(self, torso_angle):
461  """!
462  Calculate forward kinematics for left arm base.
463 
464  @param torso_angle float: angle of torso joint.
465 
466  @return PyKDL.Frame: pose of the left arm base.
467  """
468  T_B_AB = PyKDL.Frame()
469  q_kdl = PyKDL.JntArray(1)
470  q_kdl[0] = torso_angle
471  self.__fk_kdl_al_base.JntToCart(q_kdl, T_B_AB)
472  return T_B_AB
473 
474  # # FK for left ARM base
475  # s0 = math.sin(torso_angle)
476  # c0 = math.cos(torso_angle)
477  # m00 = -0.5*s0
478  # m01 = -c0
479  # m02 = -0.86602540378614*s0
480  # m03 = -0.000188676*s0
481  # m10 = 0.5*c0
482  # m11 = -s0
483  # m12 = 0.86602540378614*c0
484  # m13 = 0.000188676*c0
485  # m20 = -0.866025403786140
486  # m21 = 0.0
487  # m22 = 0.5
488  # m23 = 1.20335
489  # nx = PyKDL.Vector(m00, m10, m20)
490  # ny = PyKDL.Vector(m01, m11, m21)
491  # nz = PyKDL.Vector(m02, m12, m22)
492  # return PyKDL.Frame( PyKDL.Rotation(nx, ny, nz), PyKDL.Vector(m03, m13, m23) )
493 
494  def getRightArmBaseFk(self, torso_angle):
495  """!
496  Calculate forward kinematics for right arm base.
497 
498  @param torso_angle float: angle of torso joint.
499 
500  @return PyKDL.Frame: pose of the right arm base.
501  """
502 
503  T_B_AB = PyKDL.Frame()
504  q_kdl = PyKDL.JntArray(1)
505  q_kdl[0] = torso_angle
506  self.__fk_kdl_ar_base.JntToCart(q_kdl, T_B_AB)
507  return T_B_AB
508 
509  # # FK for right arm base
510  # s0 = math.sin(torso_angle)
511  # c0 = math.cos(torso_angle)
512  # m00 = -0.5*s0
513  # m01 = -c0
514  # m02 = 0.86602540378614*s0
515  # m03 = 0.000188676*s0
516  # m10 = 0.5*c0
517  # m11 = -s0
518  # m12 = -0.86602540378614*c0
519  # m13 = -0.000188676*c0
520  # m20 = 0.866025403786140
521  # m21 = 0.0
522  # m22 = 0.5
523  # m23 = 1.20335
524  # nx = PyKDL.Vector(m00, m10, m20)
525  # ny = PyKDL.Vector(m01, m11, m21)
526  # nz = PyKDL.Vector(m02, m12, m22)
527  # return PyKDL.Frame( PyKDL.Rotation(nx, ny, nz), PyKDL.Vector(m03, m13, m23) )
528 
529  def getArmFk(self, side_str, torso_angle, q):
530  if side_str == 'left':
531  return self.getLeftArmFk(torso_angle, q)
532  elif side_str == 'right':
533  return self.getRightArmFk(torso_angle, q)
534  else:
535  raise Exception('Wrong side: "{}"'.format(side_str))
536 
537  def getLeftArmFk(self, torso_angle, q):
538  """!
539  Calculate forward kinematics for left arm end-effector (the last link).
540 
541  @param torso_angle float: angle of torso joint.
542  @param q 7-tuple: arm configuration.
543 
544  @return PyKDL.Frame: pose of the left arm end-effector (the last link).
545  """
546 
547  T_B_AB = self.getLeftArmBaseFk(torso_angle)
548  T_AB_E = self.__ik_solver_lwr.calculateFk(q)
549  return T_B_AB * T_AB_E
550 
551  def getRightArmFk(self, torso_angle, q):
552  """!
553  Calculate forward kinematics for right arm end-effector (the last link).
554 
555  @param torso_angle float: angle of torso joint.
556  @param q 7-tuple: arm configuration.
557 
558  @return PyKDL.Frame: pose of the right arm end-effector (the last link).
559  """
560  T_B_AB = self.getRightArmBaseFk(torso_angle)
561  T_AB_E = self.__ik_solver_lwr.calculateFk(q)
562  return T_B_AB * T_AB_E
563 
564  def getLeft_T_E_G(self):
565  """!
566  Get constant transformation from the left end-effector (the last link, frame 'E') to the left grasp frame 'G' in the center of the left gripper.
567 
568  @return PyKDL.Frame: pose of frame 'G' wrt. frame 'E'.
569  """
570  return self.__T_El_Gl
571 
572  def getRight_T_E_G(self):
573  """!
574  Get constant transformation from the right end-effector (the last link, frame 'E') to the right grasp frame 'G' in the center of the right gripper.
575 
576  @return PyKDL.Frame: pose of frame 'G' wrt. frame 'E'.
577  """
578  return self.__T_Er_Gr
579 
580  def getT_E_G(self, side_str):
581  """!
582  Get constant transformation from the the end-effector (the last link, frame 'E') to the grasp frame ('G', in the center of the gripper).
583 
584  @param side_str str: either 'left' or 'right'.
585 
586  @return PyKDL.Frame: pose of frame 'E' wrt. frame 'G'.
587  """
588  if side_str == 'left':
589  return self.getLeft_T_E_G()
590  elif side_str == 'right':
591  return self.getRight_T_E_G()
592  # else:
593  raise Exception('Wrong side_str: "{}"'.format(side_str))
594 
595  def getLeft_T_E_P(self):
596  """!
597  Get constant transformation from the left end-effector (the last link, frame 'E') to the left palm link (frame 'P').
598 
599  @return PyKDL.Frame: pose of frame 'P' wrt. frame 'E'.
600  """
601  return self.__T_El_Pl
602 
603  def getRight_T_E_P(self):
604  """!
605  Get constant transformation from the right end-effector (the last link, frame 'E') to the right palm link (frame 'P').
606 
607  @return PyKDL.Frame: pose of frame 'P' wrt. frame 'E'.
608  """
609  return self.__T_Er_Pr
610 
611  def getT_E_P(self, side_str):
612  """!
613  Get constant transformation from the end-effector (the last link, frame 'E') to the left palm link (frame 'P').
614 
615  @param side_str str: either 'left' or 'right'.
616 
617  @return PyKDL.Frame: pose of frame 'P' wrt. frame 'E'.
618  """
619  if side_str == 'left':
620  return self.__T_El_Pl
621  elif side_str == 'right':
622  return self.__T_Er_Pr
623  # else:
624  raise Exception('Wrong value for side_str: "{}", expected "left" or "right"'.format(
625  side_str))
626 
627  def getLeft_T_G_E(self):
628  """!
629  Inverse of velma_kinematics.velma_ik_geom.KinematicsSolverVelma.getLeft_T_E_G.
630 
631  @return PyKDL.Frame: pose of frame 'E' wrt. frame 'G'.
632  """
633  return self.__T_Gl_El
634 
635  def getRight_T_G_E(self):
636  """!
637  Inverse of velma_kinematics.velma_ik_geom.KinematicsSolverVelma.getRight_T_E_G.
638 
639  @return PyKDL.Frame: pose of frame 'E' wrt. frame 'G'.
640  """
641  return self.__T_Gr_Er
642 
643  def getT_G_E(self, side_str):
644  """!
645  Get constant transformation from the grasp frame 'G' in the center of the gripper to the end-effector (the last link, frame 'E').
646 
647  @param side_str str: either 'left' or 'right'.
648 
649  @return PyKDL.Frame: pose of frame 'E' wrt. frame 'G'.
650  """
651  if side_str == 'left':
652  return self.getLeft_T_G_E()
653  elif side_str == 'right':
654  return self.getRight_T_G_E()
655  # else:
656  raise Exception('Wrong side_str: "{}"'.format(side_str))
657 
658  def getLeft_T_P_E(self):
659  """!
660  Inverse of velma_kinematics.velma_ik_geom.KinematicsSolverVelma.getLeft_T_E_P.
661 
662  @return PyKDL.Frame: pose of frame 'E' wrt. frame 'P'.
663  """
664  return self.__T_Pl_El
665 
666  def getRight_T_P_E(self):
667  """!
668  Inverse of velma_kinematics.velma_ik_geom.KinematicsSolverVelma.getRight_T_E_P.
669 
670  @return PyKDL.Frame: pose of frame 'E' wrt. frame 'P'.
671  """
672  return self.__T_Pr_Er
673 
674  def calculateIkRightArm(self, T_B_W, torso_angle, elbow_circle_angle, flip_shoulder,
675  flip_elbow, flip_ee):
676  """!
677  Calculate inverse kinematics (IK) for WUT Velma robot for right arm.
678  @see calculateIkArm
679  """
680  return self.calculateIkArm('right', T_B_W, torso_angle, elbow_circle_angle, flip_shoulder,
681  flip_elbow, flip_ee)
682 
683  def calculateIkLeftArm(self, T_B_Wr, torso_angle, elbow_circle_angle, flip_shoulder,
684  flip_elbow, flip_ee):
685  """!
686  Calculate inverse kinematics (IK) for WUT Velma robot for left arm.
687  @see calculateIkArm
688  """
689  return self.calculateIkArm('left', T_B_W, torso_angle, elbow_circle_angle, flip_shoulder,
690  flip_elbow, flip_ee)
691 
692  def calculateIkArm(self, side_str, T_B_W, torso_angle, elbow_circle_angle, flip_shoulder,
693  flip_elbow, flip_ee):
694  """!
695  Calculate inverse kinematics (IK) for WUT Velma robot arm.
696 
697  @param side_str string: either 'left' or 'right'.
698  @param T_B_W PyKDL.Frame: pose of the end-effector (the last link) wrt. the robot base.
699  @param torso_angle float: angle of the torso joint.
700  @param elbow_circle_angle float: IK parameter.
701  @param flip_shoulder bool: IK parameter.
702  @param flip_elbow bool: IK parameter.
703  @param flip_ee bool: IK parameter.
704 
705  @return 7-tuple: arm configuration or a tuple of Nones, if the solution does not exist.
706  """
707  assert isinstance(T_B_W, PyKDL.Frame)
708  assert isinstance(torso_angle, float)
709  assert isinstance(elbow_circle_angle, float)
710 
711  T_A0_A7d = self.getArmBaseFk(side_str, torso_angle).Inverse() * T_B_W
712  return self.__ik_solver_lwr.calculateIk(T_A0_A7d, elbow_circle_angle, flip_shoulder,
713  flip_elbow, flip_ee)
714 
715  def calculateIkSet(self, side_str, T_B_W, torso_angle, elbow_circle_angles):
716  """!
717  @see KinematicsSolverLWR4.calculateIkSet
718  """
719  assert side_str in ('left', 'right')
720  assert isinstance(T_B_W, PyKDL.Frame)
721  assert isinstance(torso_angle, float)
722 
723  T_A0_A7d = self.getArmBaseFk(side_str, torso_angle).Inverse() * T_B_W
724  return self.__ik_solver_lwr.calculateIkSet(T_A0_A7d, elbow_circle_angles)
725 
726  def getArmLimits(self):
727  return self.__ik_solver_lwr.getLimits()
728 
729  def getTorsoLimits(self):
730  return (-1.57, 1.57)
731 
732 
734  """!
735  Kinematics solver (FK) for BarrettHand gripper
736  """
737 
738  def __init__(self):
739  self.__T_P_G = PyKDL.Frame( PyKDL.Vector(0, 0, 0.12) )
740 
741  # joint_name, parent_link, child_link, joint_rpy, joint_xyz, joint_axis
742  self.__kin_parameters = [
743  ('_HandFingerThreeKnuckleTwoJoint',
744  '_HandPalmLink', '_HandFingerThreeKnuckleTwoLink',
745  (-1.57079632679, 0, -1.57079632679), (0, -0.05, 0.0754), (0, 0, -1)),
746  ('_HandFingerThreeKnuckleThreeJoint',
747  '_HandFingerThreeKnuckleTwoLink', '_HandFingerThreeKnuckleThreeLink',
748  (0, 0, -0.690452252), (0.07, 0, 0), (0, 0, -1)),
749  ('_HandFingerOneKnuckleOneJoint',
750  '_HandPalmLink', '_HandFingerOneKnuckleOneLink',
751  (0, 0, 1.57079632679), (0.02497, 0, 0.0587966), (0, 0, -1)),
752  ('_HandFingerOneKnuckleTwoJoint',
753  '_HandFingerOneKnuckleOneLink', '_HandFingerOneKnuckleTwoLink',
754  (-1.57079632679, 0, 0), (0.05, 0, 0.0166034), (0, 0, -1)),
755  ('_HandFingerOneKnuckleThreeJoint',
756  '_HandFingerOneKnuckleTwoLink', '_HandFingerOneKnuckleThreeLink',
757  (0, 0, -0.690452252), (0.07, 0, 0), (0, 0, -1)),
758  ('_HandFingerTwoKnuckleOneJoint',
759  '_HandPalmLink', '_HandFingerTwoKnuckleOneLink',
760  (0, 0, 1.57079632679), (-0.02497, 0, 0.0587966), (0, 0, 1)),
761  ('_HandFingerTwoKnuckleTwoJoint',
762  '_HandFingerTwoKnuckleOneLink', '_HandFingerTwoKnuckleTwoLink',
763  (-1.57079632679, 0, 0), (0.05, 0, 0.0166034), (0, 0, -1)),
764  ('_HandFingerTwoKnuckleThreeJoint',
765  '_HandFingerTwoKnuckleTwoLink', '_HandFingerTwoKnuckleThreeLink',
766  (0, 0, -0.690452252), (0.07, 0, 0), (0, 0, -1)),
767  ]
768 
769  def getT_P_G(self):
770  return self.__T_P_G
771 
772  def calculateFK(self, prefix, q):
773  if len(q) == 4:
774  f0a = q[0]
775  f0b = q[0] * 0.3333333
776  f1a = q[1]
777  f1b = q[1] * 0.3333333
778  f2a = q[2]
779  f2b = q[2] * 0.3333333
780  sp = q[3]
781  elif len(q) == 7:
782  f0a = q[0]
783  f0b = q[1]
784  f1a = q[2]
785  f1b = q[3]
786  f2a = q[4]
787  f2b = q[5]
788  sp = q[6]
789  else:
790  raise Exception('KinematicsSolverBarrettHand.calculateFK({}): '\
791  'Wrong number of joint angles'.format(q))
792 
793  q_map = {
794  '_HandFingerOneKnuckleTwoJoint':f0a,
795  '_HandFingerOneKnuckleThreeJoint':f0b,
796  '_HandFingerTwoKnuckleTwoJoint':f1a,
797  '_HandFingerTwoKnuckleThreeJoint':f1b,
798  '_HandFingerThreeKnuckleTwoJoint':f2a,
799  '_HandFingerThreeKnuckleThreeJoint':f2b,
800  '_HandFingerOneKnuckleOneJoint':sp,
801  '_HandFingerTwoKnuckleOneJoint':sp,
802  }
803 
804  fk = {'_HandPalmLink':PyKDL.Frame()}
805 
806  for joint_name, parent_link, child_link, joint_rpy, joint_xyz, joint_axis in self.__kin_parameters:
807  q = q_map[joint_name]
808  axis = PyKDL.Vector(joint_axis[0], joint_axis[1], joint_axis[2])
809 
810  fk[child_link] = fk[parent_link] *\
811  PyKDL.Frame(PyKDL.Rotation.RPY(joint_rpy[0], joint_rpy[1], joint_rpy[2]),
812  PyKDL.Vector(joint_xyz[0], joint_xyz[1], joint_xyz[2])) *\
813  PyKDL.Frame(PyKDL.Rotation.Rot(axis, q))
814 
815  result = {}
816  for link_name, q in fk.iteritems():
817  result[prefix+link_name] = q
818  return result
Kinematics solver (FK) for BarrettHand gripper.
def getArmBaseFk(self, side_str, torso_angle)
def getRightArmShoulderPosition(self, torso_angle)
Calculate forward kinematics for right shoulder.
def getRight_T_E_P(self)
Get constant transformation from the right end-effector (the last link, frame &#39;E&#39;) to the right palm ...
def calculateIk(self, T_A0_A7d, elbow_circle_angle, flip_shoulder, flip_elbow, flip_ee)
Calculate inverse kinematics (IK) for Kuka LWR 4+.
def calculateIkSet(self, T_A0_A7d, elbow_circle_angles)
Calculate inverse kinematics (IK) for Kuka LWR 4+.
def getLeftArmBaseFk(self, torso_angle)
Calculate forward kinematics for left arm base.
def getLeft_T_E_P(self)
Get constant transformation from the left end-effector (the last link, frame &#39;E&#39;) to the left palm li...
def calculateIkLeftArm(self, T_B_Wr, torso_angle, elbow_circle_angle, flip_shoulder, flip_elbow, flip_ee)
Calculate inverse kinematics (IK) for WUT Velma robot for left arm.
def getRight_T_G_E(self)
Inverse of velma_kinematics.velma_ik_geom.KinematicsSolverVelma.getRight_T_E_G.
def getRightArmFk(self, torso_angle, q)
Calculate forward kinematics for right arm end-effector (the last link).
def getRight_T_P_E(self)
Inverse of velma_kinematics.velma_ik_geom.KinematicsSolverVelma.getRight_T_E_P.
def getArmFk(self, side_str, torso_angle, q)
def getLeftArmFk(self, torso_angle, q)
Calculate forward kinematics for left arm end-effector (the last link).
def calculateFk(self, q)
Calculate forward kinematics (FK) for Kuka LWR 4+.
def calculateIkSet(self, side_str, T_B_W, torso_angle, elbow_circle_angles)
def getT_G_E(self, side_str)
Get constant transformation from the grasp frame &#39;G&#39; in the center of the gripper to the end-effector...
Kinematics solver (FK, IK) for WUT Velma robot.
def getLeftArmShoulderPosition(self, torso_angle)
Calculate forward kinematics for left shoulder.
def __calculateIkPart2(self, T_A0_A7d, q0, q1, q2, q3, flip_ee)
Kinematics solver (FK, IK) for Kuka LWR 4+.
def getT_E_P(self, side_str)
Get constant transformation from the end-effector (the last link, frame &#39;E&#39;) to the left palm link (f...
def calculateIkArm(self, side_str, T_B_W, torso_angle, elbow_circle_angle, flip_shoulder, flip_elbow, flip_ee)
Calculate inverse kinematics (IK) for WUT Velma robot arm.
def getLeft_T_P_E(self)
Inverse of velma_kinematics.velma_ik_geom.KinematicsSolverVelma.getLeft_T_E_P.
def getT_E_G(self, side_str)
Get constant transformation from the the end-effector (the last link, frame &#39;E&#39;) to the grasp frame (...
def getLeft_T_G_E(self)
Inverse of velma_kinematics.velma_ik_geom.KinematicsSolverVelma.getLeft_T_E_G.
def getRight_T_E_G(self)
Get constant transformation from the right end-effector (the last link, frame &#39;E&#39;) to the right grasp...
def getDebug(self, key)
Get some debug information after solving inverse kinematics.
def getLeft_T_E_G(self)
Get constant transformation from the left end-effector (the last link, frame &#39;E&#39;) to the left grasp f...
def __calculateIkPart1(self, T_A0_A6d, elbow_circle_angle, flip_shoulder, flip_elbow)
def calculateIkRightArm(self, T_B_W, torso_angle, elbow_circle_angle, flip_shoulder, flip_elbow, flip_ee)
Calculate inverse kinematics (IK) for WUT Velma robot for right arm.
def getArmShoulderPosition(self, side_str, torso_angle)
Calculate forward kinematics for shoulder.
def getRightArmBaseFk(self, torso_angle)
Calculate forward kinematics for right arm base.