18 Changes from last version:
19 1- a new task cost function added: Liegeois_Midrange_Deviance() used for Jacobian Nullspace Gradient Projection to avoid joint limits as a second-priority cost function
22 import numpy, math, copy, sys
23 import link_point
as lplib, task_reference
as trlib, cost_function
as cflib
24 import general_python
as genpy
37 If there are more than one endeffector,
38 precision settings can be set individually for each "position reference" (Task Point) and "orientation reference" (Task Frame)
39 You can change each one after the creation of class instance
50 This class contains all kinematic properties of the taskspace of a manipulator.
53 1- task_point: A list of operational points (Position References)
54 2- reference_orientation: A list of operational link frames (Orientation References)
55 3- The geometric Jacobian
57 5- The pose error vector and its norm
59 Method "update" calculates and update all these properties according to the given joint configuration.
61 def __init__(self, config_settings, geo_settings, end_settings):
62 super(Endeffector, self).
__init__(copy.deepcopy(config_settings), copy.copy(geo_settings))
67 The following code defines one task point by default for the link_segment model
68 This defined task point is the origin of the last link of the model (The defined endeffector by default)
74 last_link_number = geo_settings.nlink - 1
75 last_link_origin = lplib.Link_Point(last_link_number,1,[0,0,0])
76 endeffector_position_reference_by_default = trlib.Task_Point(self.config_settings, [last_link_origin])
83 The following code defines one task frame by default for the link_segment model
84 This defined task frame is the orientation of the last link of the model (The defined endeffector by default)
86 endeffector_orientation_reference_by_default = trlib.Task_Frame(self.config_settings, last_link_number)
87 self.
add_taskframe(endeffector_orientation_reference_by_default)
89 self.task_cost.append(cflib.Cost_Function(input_ref =
'Joint Values'))
90 self.
task_cost[0].function = flib.Zghal_Function(xl = numpy.copy(self.ql), xh = numpy.copy(self.qh))
91 self.
task_cost[0].abs_grad = numpy.zeros(self.config_settings.DOF)
94 self.task_cost.append(cflib.Cost_Function(input_ref = 'Joint Values'))
95 self.task_cost[1].function = flib.Liegeois_Midrange_Deviance(xl = numpy.copy(self.ql), xh = numpy.copy(self.qh))
96 # self.task_cost[1].purpose = 'Gradient Projection'
150 self.task_point.append(task_point)
153 self.
task_point[n_tp].error.settings.precision = self.end_settings.precision_for_position
154 self.
task_point[n_tp].error.settings.precision_base = self.end_settings.precision_base_for_position
159 self.task_frame.append(task_frame)
161 self.
task_frame[n_tf].error.settings.precision = self.end_settings.precision_for_rotation
162 self.
task_frame[n_tf].error.settings.precision_base = self.end_settings.precision_base_for_rotation
167 s +=
" Reference Position " + str(i) +
":" +
"\n" +
"\n"
172 s +=
" Reference Orientation " + str(i) +
":" +
"\n" +
"\n"
178 s += vecmat.vector_to_str(self.
pose_error()) +
"\n"
179 s +=
" Norm of Pose Error: "
189 cnt = cnt + tp.error.settings.weight.shape[0]
195 cnt = cnt + tf.error.settings.weight.shape[0]
198 return (self.
mp, self.
mo)
202 W = numpy.ones(self.config_settings.DOF)
204 if cf.purpose ==
'Joint Damping':
205 abs_grad = abs(cf.gradient(self))
206 delta = abs_grad - cf.abs_grad
207 for i
in range(self.config_settings.DOF):
209 W[i] += cf.weight*abs_grad[i]
210 cf.abs_grad[i] = abs_grad[i]
212 return numpy.diag(1.0/W)
217 Calculates and updates the actual positions and orientations of all task_points and task_frames according to the given configuration
224 H = self.transfer_matrices()
236 ori = tf.orientation(H).matrix()
247 Calculates and updates the current values of position and orientation errors between the actual and target poses of task_points and task_frames
248 Also updates the values of "pose_error" and "error_norm"
257 H = self.transfer_matrices()
259 ers =
"Target has not been set for some of the taskpoints"
260 assert tp.rd !=
None, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, ers)
264 tp_err = tp.error.value(tp.ra, tp.rd)
265 for k
in range(0,len(tp_err)):
271 ers =
"Target has not been set for some of the taskframes"
272 assert tf.rd !=
None, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, ers)
276 tf_err = tf.error.value(tf.ra, tf.rd)
277 for k
in range(0,len(tf_err)):
294 Calculates and updates the geometric jacobian of the endeffector according to the task_points and task_frames
300 self.
geo_jac = numpy.zeros((npos + nori, self.config_settings.DOF))
305 tp.update_geometric_jacobian(self.analytic_jacobian)
308 for j
in range(0, self.config_settings.DOF):
309 self.
geo_jac[3*i + k, j] = tp.geometric_jacobian.value[k,j]
314 tf.update_geometric_jacobian(self.H)
317 for j
in range(0, self.config_settings.DOF):
318 self.
geo_jac[npos + 3*i + k,j] = tf.geometric_jacobian.value[k,j]
325 Calculates and updates the error jacobian of the endeffector according to the actual and target poses of the task_points and task_frames and their corresponding metrics
329 self.
err_jac = numpy.zeros((self.
mp + self.
mo, self.config_settings.DOF))
330 H = self.transfer_matrices()
333 ers =
"Target has not been set for some of the taskpoints"
334 assert tp.rd !=
None, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, ers)
336 tp_ej = tp.error_jacobian(H, self.ajac)
338 tp_er = tp.error.value(tp.position(H), tp.rd)
340 for k
in range(0,len(tp_er)):
341 for j
in range(0, self.config_settings.DOF):
342 self.
err_jac[cnt,j] = self.jmc_c[j]*tp_ej[k,j]
346 ers =
"Target has not been set for some of the taskframes"
347 assert tf.rd !=
None, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, ers)
349 tf_ej = tf.error_jacobian(self.ajac)
350 tf_er = tf.error.value(tf.orientation(H), tf.rd)
352 for k
in range(0,len(tf_er)):
353 for j
in range(0, self.config_settings.DOF):
354 self.
err_jac[cnt,j] = self.jmc_c[j]*tf_ej[k,j]
361 self.
mu = math.sqrt(abs(numpy.linalg.det(numpy.dot(J, J.T))))
371 return the endeffector target pose as a concatenated tuple
373 assert pose_selection
in [
'actual',
'desired']
376 H = self.transfer_matrices()
378 if pose_selection ==
'actual':
380 elif pose_selection ==
'desired':
389 if pose_selection ==
'actual':
390 rm = tf.orientation(H)
391 elif pose_selection ==
'desired':
396 if parametrization ==
'Rotation Matrix':
399 pose_tpl += rm[
'matrix'][j][k],
401 ov = rm[parametrization]
409 get the pose as a concatenated tuple and change endeffector target
410 (inverse of "self.target_pose_to_tuple")
412 assert pose_selection
in [
'actual',
'desired']
413 actual = (pose_selection ==
'actual')
419 r[j] = pose_tuple[cnt]
424 tp.set_target(copy.copy(r))
427 if parametrization ==
'Rotation Matrix':
431 r[j][k] = pose_tuple[cnt]
436 tf.set_target(geolib.Orientation_3D(r, ori_velocity = numpy.zeros((3,3))))
440 ov = numpy.zeros((3))
442 ov[j] = pose_tuple[cnt]
446 tf.ra = rotation.rotation_matrix(ov, parametrization)
448 tf.rd = rotation.rotation_matrix(ov, parametrization)
468 assert len(orientation) <= len(self.
task_frame)
474 for o
in orientation:
475 o.set_velocity(numpy.zeros((3,3)), representation =
'matrix')
precision_base_for_position
def joint_damping_weights
all_task_frames_in_target
all_task_points_in_target
precision_base_for_rotation