MAGIKS  1.1
Manipulator General Inverse Kinematic Solver
 All Classes Namespaces Files Functions Variables Pages
jacobian.py
Go to the documentation of this file.
1 ## @file jacobian.py
2 # @brief This module provides three classes representing the geometric, analytic and error jacobians of a manipulator
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 4.0
13 #
14 # Last Revision: 11 January 2015
15 
16 
17 import numpy, math
18 
19 from math_tools.geometry import rotation
20 from math_tools.algebra import quaternions, vectors_and_matrices as vecmatlib
21 
22 ## This class contains the standard analytic jacobian of a manipulator with required methods for calculating it.
23 class Analytic_Jacobian(object):
24 
25  ## The Class Constructor:
26  # @param config_settings An instance of class
27  # \link magiks.jointspace.manipulator_configuration.Manipulator_Configuration_Settings Manipulator_Configuration_Settings \endlink
28  # containing the configuration settings of the manipulator
29  def __init__(self, config_settings):
30 
31 
32  self.config_settings = config_settings
33  self.clear()
34 
35 
36 # \cond
37  ## Clears the transfer matrices and their derivatives (properties \c H and \c U)
38  def clear(self):
39  ## A two dimensional list of <tt> 4 X 4 </tt> hemogeneous matrices.
40  # <tt> U[i][j] </tt> represents the partial derivative of <tt> T[i] </tt>
41  # (Transformation matrix of link \a i) with respect to the j-th joint variation (q[j])
42  self.U = [ None for i in range(0, self.config_settings.njoint) ]
43 
44  self.H = None
45 
46  ## Returns the analytic jacobian for a specified link
47  # @param link_number An integer specifying the link number for which the analytic Jacobian is required
48  def __getitem__(self, link_number):
49  if self.U[link_number] == None:
50  self.U[link_number] = [numpy.eye(4) for j in range(0, link_number + 1)]
51  j = 0
52  for jj in range(0, link_number + 1):
53  if self.config_settings.free[jj]:
54  if self.config_settings.prismatic[jj]:
55  self.U[link_number][j][0,0] = 0.00
56  self.U[link_number][j][1,1] = 0.00
57  self.U[link_number][j][2,2] = 0.00
58  if j==0:
59  U[link_number][j][2,3] = 1.00
60  else:
61  self.U[link_number][j][0,3] = self.H[jj-1][0,2]
62  self.U[link_number][j][1,3] = self.H[jj-1][1,2]
63  self.U[link_number][j][2,3] = self.H[jj-1][2,2]
64  else:
65  if j==0:
66  # pj_1: position of the origin of frame link "j-1"
67  pj_1 = [0,0,0]
68  # szj_1: skew of unit vector "z" of frame link "j-1"
69  szj_1 = numpy.array( [[0 , -1, 0 ],
70  [1 , 0, 0 ],
71  [0 , 0, 0 ]])
72  else:
73  pj_1 = self.H[jj-1][0:3,3]
74  szj_1 = rotation.skew(self.H[jj-1][0:3,2])
75 
76  # RRQJ: rond (partial der)/ rond of q_j (A multiplier which derivates in respect with q_j)
77  RRQJ = vecmatlib.extended_matrix(szj_1, - numpy.dot(szj_1,pj_1) )
78  self.U[link_number][j] = numpy.dot(RRQJ, self.H[link_number])
79  j = j + 1
80 
81  return self.U[link_number]
82 # \endcond
83 
84 ## Contains the Geometric jacobian of an end-effector that can be established of a number of reference positions (Task Points) or
85 # reference orientations (Task Frames) with methods for creating and calculating them.
86 class Geometric_Jacobian(object):
87 
88  ## The Class Constructor:
89  # @param config_settings An instance of class
90  # \link magiks.jointspace.manipulator_configuration.Manipulator_Configuration_Settings Manipulator_Configuration_Settings \endlink
91  # containing the configuration settings of the manipulator
92  def __init__(self, config_settings):
93  "Definition of the geometric jacobian matrix"
94  self.value = numpy.zeros((3 , config_settings.DOF))
95  self.config_settings = config_settings
96 
97 # \cond
98  def clear(self):
99  self.value = None
100 
101  def update_for_position(self, task_point, analytic_jacobian):
102  '''
103  Create and calculate the geometric jacobian for the given position references (reference_positions)
104  '''
105  # print "8 ****** ", numpy.sum(analytic_jacobian.U[task_point.lp[0].ln])
106  # print "9 ****** ", numpy.sum(analytic_jacobian[task_point.lp[0].ln][0])
107 
108  self.value = numpy.zeros((3, self.config_settings.DOF))
109  gj = [numpy.zeros((3)) for i in range(0, self.config_settings.DOF)]
110  for j in range(0, len(task_point.lp)):
111  k = 0
112  for kk in range(0,task_point.lp[j].ln + 1):
113  if self.config_settings.free[kk]:
114  x = numpy.dot(analytic_jacobian[task_point.lp[j].ln][k],vecmatlib.extend_vector(task_point.lp[j].pv))
115  gj[k] = gj[k] + task_point.lp[j].w * x[0:3]
116  k = k + 1
117  for i in range(0,3):
118  for j in range(0, self.config_settings.DOF):
119  self.value[i,j] = gj[j][i]
120 
121  def update_for_orientation(self, tskfrm, transfer_matrices):
122  '''
123  Create and calculate the geometric jacobian for the given orientation references (reference_orientations)
124  '''
125  self.value = numpy.zeros((3, self.config_settings.DOF))
126 
127  self.value[0,0] = 0
128  self.value[1,0] = 0
129  self.value[2,0] = 1
130 
131  for ii in range(0,tskfrm.ln + 1):
132  i = 0
133  if self.config_settings.free[ii]:
134  if self.config_settings.prismatic[i]:
135  v = numpy.zeros((3))
136  else:
137  if i == 0:
138  v = numpy.array([0,0,1])
139  else:
140  v = vecmatlib.uvect(transfer_matrices[ii-1],2)
141 
142  self.value[0,i] = v[0]
143  self.value[1,i] = v[1]
144  self.value[2,i] = v[2]
145  i = i + 1
146 # \endcond
147 
148 ## Contains the Error Jacobian of an end-effector established from one or more reference positions (Task Points)
149 # or reference orientations (Task Framess) with required methods for creating and calculating it
150 class Error_Jacobian(object):
151 # \cond
152  def __init__(self, config_settings):
153  self.config_settings = config_settings
154  #Creation of the error jacobian matrix
155  self.value = None
156 
157  def clear(self):
158  self.value = None
159 
160  def basis_error_jacobian_for_position(self, tskpnt, ajac):
161  '''
162  Calculate and return the error jacobian (Jf) according to the basis error function for position represented by: tskpnt.error.basis_error_function
163  In this version only one representation of position error is supported: "differential_cartesian_coordinates"
164  '''
165  if tskpnt.error.settings.representation == 'Cartesian Coordinates':
166  ''' Alternative
167  j = 0
168  for jj in range(0,self.config_settings.DOF):
169  if self.config_settings.free[jj]:
170  e = tskpnt.error.value
171  de = tskpnt.geometric_jacobian.value[:,j]
172  b = self.settings.power*de*(e**(self.settings.power - numpy.ones(4)))
173  if j == 0:
174  J = [b]
175  else:
176  J = np.append(J, [b], axis = 0)
177  j = j + 1
178  '''
179  p = 3
180  assert len(tskpnt.error.settings.power) == p
181  Jf = numpy.copy(tskpnt.geometric_jacobian(ajac))
182 
183  for k in range (0,p):
184  if (tskpnt.error.settings.power[k] != 0) and (tskpnt.error.settings.power[k] != 1):
185  err = tskpnt.error.power[k]*((tskpnt.r[k] - tskpnt.rd[k])**(tskpnt.error.settings.power[k] - 1))
186  j = 0
187  for jj in range(0,self.config_settings.DOF):
188  if self.config_settings.free[jj]:
189  Jf[k,j] = tskpnt.geometric_jacobian.value[k,j]*err
190  j = j + 1
191 
192  elif tskpnt.error.settings.representation == 'Cylindrical Coordinates':
193  assert False
194  elif tskpnt.error.settings.representation == 'Spherical Coordinates':
195  assert False
196  else:
197  assert False
198 
199  return Jf
200 
201  def basis_error_jacobian_for_orientation(self, tskfrm, ajac):
202  '''
203  Calculate and return the error jacobian (Jf) according to the basis error function for orientation represented by: tskfrm.error.basis_error_function
204  In this version six representations of orientation error are supported:
205  "Axis Inner Product" , "relative_rotation_matrix_trace_minus_three" , "differential_quaternions" , "relative_rotation_angle",
206  "relative_rotation_vector_Cayley_Gibbs_Rodrigues" and "differential_rotation_matrix"
207  '''
208  rpn = tskfrm.error.settings.representation
209  pwr = tskfrm.error.settings.power
210  if rpn == 'vector':
211  tskfrm.ra.set_parametrization( tskfrm.error.settings.parametrization )
212  tskfrm.rd.set_parametrization( tskfrm.error.settings.parametrization )
213  if tskfrm.error.settings.metric_type == 'relative':
214  p = len(pwr)
215  j = 0
216  for jj in range(0, tskfrm.ln + 1):
217  if self.config_settings.free[jj]:
218  ra = tskfrm.orientation(ajac.H)
219  ra.set_velocity(ajac[tskfrm.ln][j][0:3,0:3])
220  Oe = ra / tskfrm.rd
221  e = Oe[rpn]
222  de = Oe[rpn + '_velocity']
223  if rpn == 'matrix':
224  e = e.flatten()
225  de = de.flatten()
226  b = pwr*de*(e**(pwr - numpy.ones(p)))
227  if j == 0:
228  J = [b]
229  else:
230  J = numpy.append(J, [b], axis = 0)
231  j = j + 1
232 
233  elif tskfrm.error.settings.metric_type == 'differential':
234 
235  p = len(pwr)
236  j = 0
237  e = tskfrm.ra[rpn] - tskfrm.rd[rpn]
238  if rpn == 'matrix':
239  e = e.flatten()
240 
241  for jj in range(0,tskfrm.ln + 1):
242  if self.config_settings.free[jj]:
243  tskfrm.ra.set_velocity(ajac[tskfrm.ln][j][0:3,0:3])
244  de = tskfrm.ra[rpn + '_velocity']
245  if rpn == 'matrix':
246  de = de.flatten()
247  b = pwr*de*(e**(pwr - numpy.ones(p)))
248  if j == 0:
249  J = [b]
250  else:
251  J = numpy.append(J, [b], axis = 0)
252  j = j + 1
253 
254  elif tskfrm.error.settings.metric_type == 'special':
255 
256  if rpn == 'AxInPr':
257  p = 3
258  rd = tskfrm.rd['matrix']
259  Jf = numpy.zeros((p,self.config_settings.DOF))
260  for k in range (0,p):
261  if pwr[k] == 0:
262  err = 0
263  errp = 0
264  elif pwr[k] == 1:
265  err = 1
266  errp = 0
267  elif pwr[k] == 2:
268  err = 2*(numpy.dot(tskfrm.rd.frame_axis(k),tskfrm.ra.frame_axis(k)) - 1)
269  errp = 2
270  else:
271  err = tskfrm.error.power[k]*((numpy.dot(tskfrm.rd.frame_axis(k),tskfrm.ra.frame_axis(k)) - 1)**(tskfrm.error.power[k] - 1))
272  j = 0
273  for jj in range(0,tskfrm.ln + 1):
274  if self.config_settings.free[jj]:
275  jz1_k_j = numpy.dot(ajac[tskfrm.ln][j][0:3,k],rd[0:3,k])
276  Jf[k,j] = jz1_k_j*err
277  j = j + 1
278 
279  elif rpn == 'DiNoQu':
280  p = 3
281  Jf = numpy.zeros((p,self.config_settings.DOF))
282  j = 0
283  qnd = tskfrm.rd['quaternion']
284  for jj in range(0,tskfrm.ln + 1):
285  if self.config_settings.free[jj]:
286  uqns = quaternions.unit_quaternion_velocity(tskfrm.ra['matrix'], ajac[tskfrm.ln][j])
287  for k in range (0,3):
288  if pwr[k] != 0:
289  jz_k_j = qnd[k+1]*uqns[0] - qnd[0]*uqns[k+1]
290  if pwr[k] == 1:
291  Jf[k,j] = jz_k_j
292  else:
293  qn = tskfrm.ra['quaternion']
294  err = pwr[k]*((qnd[0]*qn[k+1] - qn[0]*qnd[k+1])**(pwr[k] - 1))
295  Jf[k,j] = jz_k_j*err
296  j = j + 1
297 
298  elif rpn == 'AxInPr + DiNoQu':
299  p = 6
300  Jf = numpy.zeros((p,self.config_settings.DOF))
301  for k in range (0,3):
302  if pwr[k] == 0:
303  err = 0
304  errp = 0
305  elif pwr[k] == 1:
306  err = 1
307  errp = 0
308  elif pwr[k] == 2:
309  err = 2*(numpy.dot(tskfrm.rd.frame_axis(k),tskfrm.ra.frame_axis(k)) - 1)
310  errp = 2
311  else:
312  err = tskfrm.error.power[k]*((numpy.dot(tskfrm.rd.frame_axis(k),tskfrm.ra.frame_axis(k)) - 1)**(tskfrm.error.power[k] - 1))
313  j = 0
314  for jj in range(0,tskfrm.ln + 1):
315  if self.config_settings.free[jj]:
316  jz1_k_j = numpy.dot(analytic.U[tskfrm.ln][j][0:3,k],tskfrm.rd.frame_axis(k))
317  Jf[k,j] = jz1_k_j*err
318  j = j + 1
319  j = 0
320  qnd = tskfrm.rd['quaternion']
321  for jj in range(0,tskfrm.ln + 1):
322  if self.config_settings.free[jj]:
323  uqns = quaternions.unit_quaternion_velocity(tskfrm.ra['matrix'], analytic.U[tskfrm.ln][j])
324  for k in range (3,6):
325  if pwr[k] != 0:
326  jz_k_j = qnd[k-2]*uqns[0] - qnd[0]*uqns[k-2]
327  if pwr[k] == 1:
328  Jf[k,j] = jz_k_j
329  else:
330  qn = tskfrm.ra['quaternion']
331  err = pwr[k]*((qnd[0]*qn[k-2] - qn[0]*qnd[k-2])**(pwr[k] - 1))
332  Jf[k,j] = jz_k_j*err
333  j = j + 1
334 
335  elif rpn == 'ReRoAn + ReOrVe':
336  p = 4
337  assert p == len(pwr)
338  e = numpy.zeros(p)
339  de = numpy.zeros(p)
340  j = 0
341  for jj in range(0, tskfrm.ln + 1):
342  if self.config_settings.free[jj]:
343  tskfrm.ra.set_velocity(analytic.U[tskfrm.ln][j][0:3,0:3])
344  Oe = tskfrm.ra / tskfrm.rd
345 
346  e[0] = Oe['angle']
347  e[1:4] = Oe['vector']
348  de[0] = Oe['angle_velocity']
349  de[1:4] = Oe['vector_velocity']
350  b = pwr*de*(e**(pwr - numpy.ones(p)))
351  if j == 0:
352  J = [b]
353  else:
354  J = numpy.append(J, [b], axis = 0)
355  j = j + 1
356  Jf = J.T
357 
358  else:
359  assert False
360  return Jf
361 
362  else:
363  assert False, gen.err_msg(__name__, "basis_error_jacobian_for_orientation", tskfrm.error.settings.metric_type + "is an invalid metric type")
364 
365  return J.T
366 
367  def update_for_position(self, tskpnt, ajac):
368  '''
369  Calculate and Update the error jacobian for position
370  First calculate the basis error jacobian and then multiplied by the weighting matrix
371  '''
372  bej = self.basis_error_jacobian_for_position(tskpnt, ajac)
373  self.value = numpy.dot(tskpnt.error.settings.weight, bej)
374 
375  def update_for_orientation(self, tskfrm, ajac):
376  '''
377  Calculate and Update the error jacobian for orientation
378  First calculate the basis error jacobian and then multiplied by the weighting matrix
379  '''
380  bej = self.basis_error_jacobian_for_orientation(tskfrm, ajac)
381  self.value = numpy.dot(tskfrm.error.settings.weight, bej)
382 
383 # \endcond
384 
385 
386 
Contains the Error Jacobian of an end-effector established from one or more reference positions (Task...
Definition: jacobian.py:148
def __init__
The Class Constructor:
Definition: jacobian.py:29
def __init__
The Class Constructor:
Definition: jacobian.py:91
This class contains the standard analytic jacobian of a manipulator with required methods for calcula...
Definition: jacobian.py:23
Contains the Geometric jacobian of an end-effector that can be established of a number of reference p...
Definition: jacobian.py:85