20 import numpy, math, time, copy, pickle
21 import general_python
as genpy
26 from magiks.magiks_core import inverse_kinematics
as iklib, log_manager
as loglib, manipulator_library
as manlib
30 def generate_my_default_kin_manager() :
32 the name of method says that it creates somthing , but that it sets values, "massively"
37 'PP': 'Pose Projection', # Inverse Kinematics for a single pose
38 'TG': 'Trajectory Generation', # Constant Target Kinematic Control
39 'TP': 'Trajectory Projection', # Variable Target Kinematic Control
41 all_application_scenarios = [
'PPS',
'TGS',
'TPS']
46 'NA' :
'Not Applicable',
47 'AS' :
'Application Scenario',
48 'PPS' :
'Pose Projection Scenario',
49 'TGS' :
'Trajectory Generation Scenario',
50 'TPS' :
'Trajectory Projection Scenario',
53 'JI' :
'Jacobian Inverse',
54 'JT' :
'Jacobian Transpose',
55 'JPI' :
'Jacobian Pseudo Inverse',
56 'DLS(CDF)' :
'Damped Least Squares Method (Constant Damping Factor)',
57 'DLS(ADF)' :
'Damped Least Squares Method (Adaptive Damping Factor)',
58 'DLS(MADF)' :
'Damped Least Squares Method (Manipulability Adjusted Damping Factor)',
61 'MAN' :
'Manipulator',
62 'PUMA' :
'PUMA (6 DOF)',
63 'PA10' :
'Mitsubishi PA10 (7 DOF)',
64 'EXO' :
'DFKI Capio Exoskeleton (9 DOF)',
65 'PR2ARM' :
'Willowgarage PR2 Arm (7 DOF)',
67 'DiCaCo(xyz)' :
'Difference of Cartesian Coordinates x-y-z',
68 'DiCaCo(xy)' :
'Difference of Cartesian Coordinates x-y',
69 'DiCaCo(xz)' :
'Identical Cartesian Coordinates x-z',
70 'DiCaCo(yz)' :
'Identical Cartesian Coordinates y-z',
71 'DiCaCo(x)' :
'Identical Cartesian Coordinates x',
72 'DiCaCo(y)' :
'Identical Cartesian Coordinates y',
73 'DiCaCo(z)' :
'Identical Cartesian Coordinates z',
75 'AxInPr(ijk)' :
'Axis Inner Product (Aligned Axis i-j-k)',
76 'AxInPr(ij)' :
'Axis Inner Product (Aligned Axis i-j)',
77 'AxInPr(ik)' :
'Axis Inner Product (Aligned Axis i-k)',
78 'AxInPr(jk)' :
'Axis Inner Product (Aligned Axis j-k)',
79 'AxInPr(i)' :
'Axis Inner Product (Aligned Axis i)',
80 'AxInPr(j)' :
'Axis Inner Product (Aligned Axis j)',
81 'AxInPr(k)' :
'Axis Inner Product (Aligned Axis k)',
82 'ReRoMaTr' :
'Trace of Relative Rotation Matrix',
83 'ReRoMa' :
'Relative Rotation Matrix',
84 'DiAnAx' :
'Difference of Angle-Axis',
85 'DiUnQu' :
'Difference of Unit Quaternions',
86 'ReAnAx' :
'Relative Angle-Axis',
87 'ReUnQu' :
'Relative Unit Quaternion',
88 'DiNoQu' :
'Difference of Non-Redundant(Normalized) Quaternions',
89 'ReRoAn' :
'Relative Rotation Angle',
90 'ReOrVe(LIN)' :
'Relative Orientation Vector (Linear parametrization)',
91 'ReOrVe(IDTY)' :
'Relative Orientation Vector (Identity parametrization)',
92 'ReOrVe(CaGiRo)':
'Relative Orientation Vector (Cayley-Gibbs-Rodrigues parametrization)' ,
93 'ReOrVe(EXP)' :
'Relative Orientation Vector (Exponential parametrization)' ,
94 'ReOrVe(BaTr)' :
'Relative Orientation Vector (Bauchau-Trainelli parametrization)' ,
95 'DiRoMa' :
'Difference of Rotation Matrices',
96 'DiOrVe(IDTY)' :
'Difference of Orientation Vectors (Identity parametrization)',
97 'DiOrVe(LIN)' :
'Difference of Orientation Vectors (Linear parametrization)',
98 'DiOrVe(CaGiRo)':
'Difference of Orientation Vectors (Cayley-Gibbs-Rodrigues parametrization)' ,
99 'DiOrVe(EXP)' :
'Difference of Orientation Vectors (Exponential parametrization)' ,
100 'DiOrVe(BaTr)' :
'Difference of Orientation Vectors (Bauchau-Trainelli parametrization)' ,
102 'AxInPr + DiNoQu':
'Combined AxInPr and DiNoQu',
103 'ReRoAn + ReOrVe(LIN)':
'Combined Relative Angle and Vector (Linear Parametrization)',
107 'LM' :
'Linear Mapping',
108 'TM' :
'Trogonometric Mapping',
109 'MM' :
'Mechanism Mapping',
111 'WCTP' :
'Workspace Coverage for Target Poses',
112 'WCIC' :
'Workspace Coverage for Initial Configurations',
115 'KC' :
'Kinematic Constraints',
116 'PP' :
'Precision for Position (mm)',
117 'PO' :
'Precision for Orientation (deg)',
118 'PM' :
'Position Metric',
119 'OM' :
'Orientation Metric',
120 'JM' :
'Joint Mapping',
121 'DF' :
'Damping Factor',
122 'DFG' :
'Damping Factor Gain',
123 'MNI' :
'Maximum Number of Iterations',
126 'Application Scenario' :
'AS',
128 'Manipulator' :
'MAN',
129 'Kinematic Constraints' :
'KC',
130 'Precision for Position (mm)' :
'PP',
131 'Precision for Orientation (deg)' :
'PO',
132 'Position Metric' :
'PM',
133 'Orientation Metric' :
'OM',
134 'Join Mapping' :
'JM',
135 'Damping Factor' :
'DF',
136 'Damping Factor Gain' :
'DFG'
140 nkc_dic = {
'DiCaCo(xyz)':3,
'DiCaCo(xy)':2,
'DiCaCo(xz)':2,
'DiCaCo(yz)':2,
'DiCaCo(x)':1,
'DiCaCo(y)':1,
'DiCaCo(z)':1,
141 'AxInPr(ijk)':3,
'AxInPr(ij)':3,
'AxInPr(ik)':3,
'AxInPr(jk)':3,
'AxInPr(i)':2,
'AxInPr(j)':2,
'AxInPr(k)':2}
143 param_dic = {
'ReOrVe(IDTY)':
'identity',
'ReOrVe(LIN)':
'linear',
'ReOrVe(CaGiRo)' :
'cayley-gibbs-rodrigues',
'ReOrVe(EXP)' :
'exponential',
'ReOrVe(BaTr)' :
'bauchau-trainelli',
144 'DiOrVe(IDTY)':
'identity',
'DiOrVe(LIN)':
'linear',
'DiOrVe(CaGiRo)' :
'cayley-gibbs-rodrigues',
'DiOrVe(EXP)' :
'exponential',
'DiOrVe(BaTr)' :
'bauchau-trainelli'}
146 def generate_orientation_metric_settings(orientation_constraint):
148 if orientation_constraint[0:6] ==
'AxInPr':
150 ms = metriclib.Metric_Settings(metric_type =
'special', representation =
'AxInPr')
154 if orientation_constraint ==
'AxInPr(ij)':
155 ms.weight = numpy.array([[1, 0, 0], [0, 1, 0]] )
156 ms.power = numpy.array([1, 1, 0])
157 ms.required_identical_coordinate = [
True,
True,
False]
158 elif orientation_constraint ==
'AxInPr(jk)':
159 ms.weight = numpy.array([[0, 1, 0], [0, 0, 1]])
160 ms.power = numpy.array([0, 1, 1])
161 ms.required_identical_coordinate = [
False,
True,
True]
162 elif orientation_constraint ==
'AxInPr(ik)':
163 ms.weight = numpy.array([[1, 0, 0], [0, 0, 1]] )
164 ms.power = numpy.array([1, 0, 1])
165 ms.offset = numpy.array([-1.0, -1.0])
166 ms.required_identical_coordinate = [
True,
False,
True]
167 elif orientation_constraint ==
'AxInPr(i)':
168 ms.weight = numpy.array([[1, 0, 0]] )
169 ms.power = numpy.array([1, 0, 0])
170 ms.required_identical_coordinate = [
True,
False,
False]
171 elif orientation_constraint ==
'AxInPr(j)':
172 ms.weight = numpy.array([[0, 1, 0]] )
173 ms.power = numpy.array([0, 1, 0])
174 ms.required_identical_coordinate = [
False,
True,
False]
175 elif orientation_constraint ==
'AxInPr(k)':
176 ms.weight = numpy.array([[0, 0, 1]] )
177 ms.power = numpy.array([0, 0, 1])
178 ms.required_identical_coordinate = [
False,
False,
True]
180 if orientation_constraint ==
'AxInPr(ijk)':
181 ms.offset = - numpy.ones(3)
182 elif orientation_constraint
in [
'AxInPr(ij)',
'AxInPr(ik)',
'AxInPr(jk)']:
183 ms.offset = - numpy.ones(2)
184 elif orientation_constraint
in [
'AxInPr(i)',
'AxInPr(j)',
'AxInPr(k)']:
185 ms.offset = - numpy.ones(1)
189 elif orientation_constraint ==
'ReRoMaTr':
191 represents the orientation error by calculating the trace of relative rotation matrix minus three: Trace(R_a * R_d^T) - 3
194 ms = metriclib.Metric_Settings(metric_type =
'relative', representation =
'trace')
196 ms.weight = numpy.array([[1]])
198 ms.power = numpy.array([1])
199 ms.offset = numpy.array([- 3.0])
201 elif orientation_constraint ==
'ReRoAn':
202 ms = metriclib.Metric_Settings(metric_type =
'relative', representation =
'angle')
203 ms.weight = numpy.array([[1]])
204 ms.power = numpy.array([1])
205 ms.offset = numpy.array([0])
207 elif orientation_constraint
in [
'ReOrVe(IDTY)',
'ReOrVe(LIN)',
'ReOrVe(CaGiRo)',
'ReOrVe(EXP)',
'ReOrVe(BaTr)']:
208 ms = metriclib.Metric_Settings(metric_type =
'relative', representation =
'vector')
209 ms.parametrization = param_dic[orientation_constraint]
211 elif orientation_constraint
in [
'DiOrVe(IDTY)',
'DiOrVe(LIN)',
'DiOrVe(CaGiRo)',
'DiOrVe(EXP)',
'DiOrVe(BaTr)']:
212 ms = metriclib.Metric_Settings(metric_type =
'differential', representation =
'vector')
213 ms.parametrization = param_dic[orientation_constraint]
215 elif orientation_constraint ==
'DiNoQu':
216 ms = metriclib.Metric_Settings(metric_type =
'special', representation =
'DiNoQu')
217 ms.weight = numpy.eye(3)
218 ms.power = numpy.ones(3)
219 ms.offset = numpy.zeros(3)
221 elif orientation_constraint ==
'DiUnQu':
222 ms = metriclib.Metric_Settings(metric_type =
'differential', representation =
'quaternion')
223 ms.weight = numpy.eye(4)
224 ms.power = numpy.array([1, 1, 1, 1])
225 ms.offset = numpy.array([0, 0, 0, 0])
227 elif orientation_constraint ==
'DiAnAx':
228 ms = metriclib.Metric_Settings(metric_type =
'differential', representation =
'angle_axis')
229 ms.weight = numpy.eye(4)
230 ms.power = numpy.array([1, 1, 1, 1])
231 ms.offset = numpy.array([0, 0, 0, 0])
233 elif orientation_constraint ==
'DiRoMa':
234 ms = metriclib.Metric_Settings(metric_type =
'differential', representation =
'matrix')
235 ms.weight = numpy.eye(9)
236 ms.power = numpy.ones(9)
237 ms.offset = numpy.zeros(9)
239 elif orientation_constraint ==
'ReRoMa':
240 ms = metriclib.Metric_Settings(metric_type =
'relative', representation =
'matrix')
241 ms.weight = numpy.eye(9)
242 ms.power = numpy.ones(9)
243 ms.offset = - numpy.eye(3).flatten()
245 elif orientation_constraint ==
'ReUnQu':
246 ms = metriclib.Metric_Settings(metric_type =
'relative', representation =
'quaternion')
247 ms.weight = numpy.eye(4)
248 ms.power = numpy.ones(4)
249 ms.offset = numpy.array([- 1.0, 0.0, 0.0, 0.0])
251 elif orientation_constraint ==
'ReAnAx':
252 ms = metriclib.Metric_Settings(metric_type =
'relative', representation =
'angle_axis')
253 ms.weight = numpy.eye(4)
254 ms.power = numpy.array([1, 1, 1, 1])
255 ms.offset = numpy.array([0, 0, 0, 0])
258 elif orientation_constraint ==
'AxInPr(ijk) + DiNoQu':
259 ms = metriclib.Metric_Settings(metric_type =
'special', representation =
'AxInPr + DiNoQu')
260 ms.weight = numpy.eye(6)
261 ms.power = numpy.ones(6)
262 ms.offset = numpy.array([-1.0, -1.0, -1.0, 0.0, 0.0, 0.0])
264 elif orientation_constraint ==
'ReRoAn + ReOrVe(LIN)':
265 ms = metriclib.Metric_Settings(metric_type =
'special', representation =
'ReRoAn + ReOrVe')
266 ms.weight = numpy.eye(4)
267 ms.power = numpy.ones(4)
268 ms.offset = numpy.zeros(4)
269 ms.parametrization =
'linear'
271 assert False, func_name +
": " + orientation_constraint +
" is an unknown value for orientation_constraint"
275 def generate_position_metric_settings(position_constraint):
276 func_name =
".generate_position_metric_settings()"
277 if position_constraint ==
'DiCaCo(xyz)':
278 ms = metriclib.Metric_Settings()
279 elif position_constraint ==
'DiCaCo(xy)':
280 ms = metriclib.Metric_Settings()
281 ms.weight = numpy.array([[1, 0, 0], [0, 1, 0]] )
282 ms.power = numpy.array([1, 1, 0])
283 ms.offset = numpy.zeros(2)
284 ms.required_identical_coordinate = [
True,
True,
False]
285 elif position_constraint ==
'DiCaCo(xz)':
286 ms = metriclib.Metric_Settings()
287 ms.weight = numpy.array([[1, 0, 0], [0, 0, 1]] )
288 ms.power = numpy.array([1, 0, 1])
289 ms.constant_offset = numpy.zeros(2)
290 ms.required_identical_coordinate = [
True,
False,
True]
291 elif position_constraint ==
'DiCaCo(yz)':
292 ms = metriclib.Metric_Settings()
293 ms.constant_offset = numpy.zeros(2)
294 ms.weighting_matrix = numpy.array([[0, 1, 0], [0, 0, 1]])
295 ms.power_array = numpy.array([0, 1, 1])
296 ms.required_identical_coordinate = [
False,
True,
True]
297 elif position_constraint ==
'DiCaCo(x)':
298 ms = metriclib.Metric_Settings()
299 ms.weight = numpy.array([[1, 0, 0]] )
300 ms.power = numpy.array([1, 0, 0])
301 ms.offset = numpy.zeros(1)
302 ms.required_identical_coordinate = [
True,
False,
False]
303 elif position_constraint ==
'DiCaCo(y)':
304 ms = metriclib.Metric_Settings()
305 ms.weight = numpy.array([[0, 1, 0]] )
306 ms.power = numpy.array([0, 1, 0])
307 ms.offset = numpy.zeros(1)
308 ms.required_identical_coordinate = [
False,
True,
False]
309 elif position_constraint ==
'DiCaCo(z)':
310 ms = metriclib.Metric_Settings()
311 ms.weight = numpy.array([[0, 0, 1]] )
312 ms.power = numpy.array([0, 0, 1])
313 ms.offset = numpy.numpy.zeros(1)
314 ms.required_identical_coordinate = [
False,
False,
True]
316 assert False, __name__ + func_name +
": " + position_constraint +
" is an unknown value for position_constraint"
319 class Kinematic_Manager_Settings(object):
326 def __init__(self, manip_name):
329 err_head =
"Error from kinematic_manager.Kinematic_Manager_Settings."
332 self.str_parameter_set = [
'AS',
'AL',
'MAN',
'KC',
'MNI',
'PP',
'PO',
'PM',
'OM',
'JM',
'WCTP',
'WCIC',
'DF',
'DFG']
333 self.csv_parameter_set = [
'AS',
'AL',
'MAN',
'KC',
'MNI',
'PP',
'PO',
'PM',
'OM',
'JM',
'WCTP',
'WCIC',
'DF',
'DFG']
334 self.key_parameter_set = [
'AS',
'AL',
'MAN',
'KC',
'MNI',
'PM',
'OM',
'JM',
'WCTP',
'WCIC',
'PP',
'PO',
'DF',
'DFG']
337 self.geo_settings = manlib.manip_geo_settings(manip_name)
340 This value can reflect the number of endeffectors as well.
341 The value of this property has no influence in the model and is designed to be shown in the test key and the table of test specifications
344 self.num_position_ref = 1
345 self.num_orientation_ref = 1
347 self.application_scenario =
'PPS'
348 self.solution_class =
'Numeric'
350 self.orientation_constraint =
'AxInPr(jk)'
351 self.position_constraint =
'DiCaCo(xyz)'
356 self.config_settings = manlib.manip_config_settings(manip_name, joint_mapping =
'NM')
357 self.end_settings = endlib.Endeffector_Settings()
358 self.ik_settings = iklib.Inverse_Kinematics_Settings(algorithm =
"JPI", run_mode =
'normal_run', num_steps = 100)
360 self.ik_settings.ngp_active =
False
362 self.end_settings.precision_base_for_position =
"Coordinate Distance"
363 self.end_settings.precision_base_for_rotation =
"Axis Angle"
365 self.end_settings.precision_for_position = 0.01
366 self.end_settings.precision_for_rotation = 1.0
371 self.workspace_settings_ic = wslib.Workspace_Settings(number_of_search_items = 10)
372 self.workspace_settings_tp = wslib.Workspace_Settings(representation_of_orientation =
'Rotation Matrix')
380 path = os.path.join( os.getcwd(), manip_name+
'_results' )
382 if os.path.exists(path) ==
False:
383 print "path not found"
387 self.path_str = path +
'/'
390 if self.orientation_constraint[0:6] ==
'AxInPr':
391 noc = nkc_dic[self.orientation_constraint]
394 return self.num_position_ref*nkc_dic[self.position_constraint] + self.num_orientation_ref*noc
397 func_name =
'valid()'
399 vld = vld
and (self.application_scenario
in all_application_scenarios)
400 assert vld, self.__class__.err_head + func_name +
": The given application_scenario is not known!"
403 def __str__( self, parameter_set = None ) :
405 returns the algorithmic setting for the inverse kinematic evaluator
407 if parameter_set ==
None:
408 parameter_set = self.str_parameter_set
410 s +=
'Kinematic Manager Settings:' +
'\n' +
'\n'
411 for p
in parameter_set:
412 value = self.parameter_value(p)
414 if p
in [
'KC',
'PP',
'PO',
'DF',
'DFG',
'MNI',
'WCTP',
'WCIC']:
415 s += param +
" "*(45-len(param)) +
': ' + value +
'\n'
417 s += param +
" "*(45-len(param)) +
': ' + key_dic[value] +
'\n'
419 s += 'Application Scenario : ' + key_dic[self.application_scenario] + '\n'
420 s += 'Algorithm : ' + key_dic[self.ik_settings.algorithm] + '\n'
421 s += 'Manipulator : ' + self.manip_name + '\n'
422 s += 'Number of position references : ' + str(self.num_position_ref) + '\n'
423 s += 'Number of orientation references : ' + str(self.num_orientation_ref) + '\n'
424 s += 'Metric for position : ' + key_dic[self.position_constraint] + '\n'
425 s += 'Metric for orientation : ' + key_dic[self.orientation_constraint] + '\n'
426 s += 'Maximum number of iterations : ' + str(self.ik_settings.number_of_steps) + '\n' + '\n'
428 s += 'Initial Configuration Workspace: ' + '\n'
429 s += str(self.workspace_settings_ic) + '\n'
431 s += 'Target Pose Workspace: ' + '\n'
432 s += str(self.workspace_settings_tp) + '\n'
436 def parameter_value(self, parameter):
437 if parameter ==
'AS':
438 return self.application_scenario
439 elif parameter ==
'AL':
440 return self.ik_settings.algorithm
441 elif parameter ==
'MAN':
442 return self.geo_settings.name
443 elif parameter ==
'KC':
444 return str(self.NKC())
445 elif parameter ==
'MNI':
446 return str(self.ik_settings.number_of_steps)
447 elif parameter ==
'PP':
448 return str(1000*self.end_settings.precision_for_position)
449 elif parameter ==
'PO':
450 return str(self.end_settings.precision_for_rotation)
451 elif parameter ==
'PM':
452 if self.num_position_ref == 0:
455 return self.position_constraint
456 elif parameter ==
'OM':
457 if self.num_orientation_ref == 0:
460 return self.orientation_constraint
461 elif parameter ==
'JM':
462 if 'TM' in self.config_settings.joint_handling:
464 elif 'LM' in self.config_settings.joint_handling:
469 elif parameter ==
'DF':
470 if self.ik_settings.algorithm[0:3] ==
'DLS':
471 return str(self.ik_settings.initial_damping_factor)
474 elif parameter ==
'DFG':
475 if self.ik_settings.algorithm ==
'DLS(ADF)':
476 return str(self.ik_settings.df_gain)
477 elif self.ik_settings.algorithm ==
'DLS(MADF)':
478 return str(self.ik_settings.manipulability_threshold)
482 elif parameter ==
'WCTP':
483 return self.workspace_settings_tp.gen_key()
484 elif parameter ==
'WCIC':
485 return self.workspace_settings_ic.gen_key()
487 assert False, genpy.err_str(__name__, self.__class__.__name__,
'parameter_value', parameter +
' is an Unknown Setting Parameter')
489 def csv(self, header = True, parameter_set = None):
491 returns the algorithmic setting for the inverse kinematic evaluator
493 if parameter_set ==
None:
494 parameter_set = self.csv_parameter_set
497 s =
'Setting Parameter' +
',' +
'Parameter Key' +
',' +
'Value' +
',' +
'Interpretation' +
'\n'
501 for p
in parameter_set:
502 value = self.parameter_value(p)
503 s += key_dic[p] +
',' + p +
',' + value +
','
504 if not p
in [
'KC',
'PP',
'PO',
'DF',
'DFG',
'MNI',
'WCTP',
'WCIC']:
509 def latex(self, header = True, parameter_set = None):
511 returns the algorithmic setting for the inverse kinematic evaluator in latex format
513 lf =
'& \multicolumn{1}{l}{} & \multicolumn{1}{l}{} & \\ \n'
514 if parameter_set ==
None:
515 parameter_set = self.csv_parameter_set
517 s =
'\begin{table}[h]' +
'\n' +
'\begin{tabular}{lccl}' +
'\n' +
'\hline' +
'\n'
520 s +=
'\multicolumn{1}{c}{\textbf{Setting Parameter}}' +
'&' +
'\textbf{Parameter Key}' +
'&' +
'\textbf{Value}' +
'&' +
'\multicolumn{1}{c}{\textbf{Interpretation}}' +
'\\ \hline \n'
522 for p
in parameter_set:
523 value = self.parameter_value(p)
524 s += key_dic[p] +
'&' + p +
'&' + value +
'&'
525 if not p
in [
'KC',
'PP',
'PO',
'DF',
'DFG',
'MNI',
'WCTP',
'WCIC']:
529 s +=
'\hline \n \end{tabular} \n \end{table}'
532 def csv_horizontal_header(self, parameter_set = None, use_key = False):
533 if parameter_set ==
None:
534 parameter_set = self.csv_parameter_set
536 for p
in parameter_set:
540 s += key_dic[p] +
","
544 def csv_horizontal(self, parameter_set = None):
545 if parameter_set ==
None:
546 parameter_set = self.csv_parameter_set
548 for p
in parameter_set:
549 s += self.parameter_value(p) +
','
554 def generate_key( self, parameter_set = None):
556 returns the settings key string for the test evaluator
559 if parameter_set ==
None:
560 parameter_set = self.key_parameter_set
561 for p
in parameter_set:
562 if p
in [
'KC',
'PP',
'PO',
'DF',
'DFG',
'MNI',
'WCTP',
'WCIC']:
563 s += p +
':' + self.parameter_value(p) +
'_'
565 s += self.parameter_value(p) +
'_'
566 return s[0:len(s) - 1]
571 key_str = "AS:" + self.application_scenario
572 rg_str = self.manip_name
573 key_str += "_RG:" + rg_str
575 key_str += "_AL:" + self.ik_settings.algorithm
577 for i in range(0, self.num_position_ref):
579 for i in range(0, self.num_orientation_ref):
582 key_str += "_PRF:" + self.position_constraint + '-' + self.orientation_constraint
584 key_str += '_TP:' + self.workspace_settings_tp.gen_key()
585 key_str += '_IC:' + self.workspace_settings_ic.gen_key()+'-'+self.workspace_settings_ic.search_criteria_key()
589 print("Error from Kinematic_Manager_Settings.generate_key():Invalid Settings")
593 class Kinematic_Manager(object):
596 Kinematic_Manager is the kinematic manager of a manipulator.
597 contains a mathematical kinematic model of a chain of joints and links which can be referred to a robot or any mechanical manipulator,
598 the whole or parts of human or animal moving mechanism.
599 This class contains all kinematic properties of a manipulator like geometry, joint configuration, transfer matrices, endeffector(s) and the jacobians
600 plus other miscellaneous geometric and algorithmic parameters for forward and inverse kinematic computations.
601 It also has a method which evaluate the performance of inverse kinematic solver by evaluating it for a set of target poses in the
602 workspace generated from a jointspace grid.
605 def __init__(self, settings):
607 Predefined Class Properties :
609 self.settings = settings
610 self.km_log = loglib.Test_Log(settings)
616 if self.settings.workspace_settings_ic.search_criteria ==
'NCC':
617 self.settings.ik_settings.include_current_config =
True
619 self.settings.ik_settings.include_current_config =
False
622 self.inverse_kinematics = iklib.Inverse_Kinematics(self.settings.config_settings, self.settings.geo_settings, self.settings.end_settings, self.settings.ik_settings )
626 for tp
in self.inverse_kinematics.task_point:
627 tp.error.settings = generate_position_metric_settings(self.settings.position_constraint)
628 tp.error.settings.precision = self.inverse_kinematics.end_settings.precision_for_position
630 for tf
in self.inverse_kinematics.task_frame:
631 tf.error.settings = generate_orientation_metric_settings(self.settings.orientation_constraint)
632 tf.error.settings.precision = self.inverse_kinematics.end_settings.precision_for_rotation
634 self.inverse_kinematics.num_task_constraints()
638 if self.settings.num_position_ref == 0:
639 self.inverse_kinematics.endeffector.reference_positions = []
640 if self.settings.num_orientation_ref == 0:
641 self.inverse_kinematics.endeffector.reference_orientations = []
644 if settings.workspace_settings_ic.read_workspace:
645 print 'Reading Init Config Workspace ... '
646 self.workspace_ic = wslib.read_from_file(settings.path_str + settings.workspace_settings_ic.gen_file_name(geometry.name))
647 self.workspace_ic.settings = self.settings.workspace_settings_ic
648 print 'Reading Init Config Workspace Finished '
650 self.workspace_ic = wslib.Workspace(settings.config_settings, settings.geo_settings, settings.end_settings, settings.workspace_settings_ic)
651 self.workspace_ic.create()
653 if settings.workspace_settings_ic.write_workspace:
654 print 'Saving init config workspace to : ', settings.path_str + settings.workspace_settings_ic.gen_file_name(geometry.name) +
' ... '
655 self.workspace_ic.write_to_file(settings.path_str + settings.workspace_settings_ic.gen_file_name(geometry.name))
656 print 'Finished saving workspace.'
658 if settings.workspace_settings_tp.read_workspace:
659 print 'Reading Target Pose Workspace ... '
660 st = copy.copy(self.settings.workspace_settings_tp)
661 self.workspace_tp = wslib.read_from_file(settings.path_str + settings.workspace_settings_tp.gen_file_name(geometry.name))
662 self.workspace_tp.settings = self.settings.workspace_settings_tp
663 print 'Reading Target Pose Workspace Finished '
665 self.workspace_tp = wslib.Workspace(settings.config_settings, settings.geo_settings, settings.end_settings, settings.workspace_settings_tp)
666 self.workspace_tp.create()
667 if settings.workspace_settings_tp.write_workspace:
668 print 'Saving target pose workspace to : ', settings.path_str + settings.workspace_settings_tp.gen_file_name(geometry.name) +
' ... '
669 self.workspace_tp.write_to_file(settings.path_str + settings.workspace_settings_tp.gen_file_name(geometry.name))
670 print 'Finished saving workspace.'
676 def evaluate_ik_solver(self, verbose = False):
678 run for the whole grid
680 Evaluate the ik solver by implementing it for a number of target poses which are evenly distributed in the workspace of the manipulator
681 A grid(lattice) is created in the jointspace and the target poses are generated by computing the forward kinematics for those configurations
682 Therefore, each configuration makes a corresponding target pose
683 The ik solver is implemented for each target pose, from a constant initial configuration and a list of results is returned.
691 self.km_log.body = []
693 for pose_tuple
in self.workspace_tp.pose_list:
701 self.inverse_kinematics.configuration.q = numpy.copy(qq)
702 self.inverse_kinematics.forward_update()
704 for tp in self.inverse_kinematics.endeffector.reference_positions:
705 tp.rd = numpy.copy(tp.ra)
706 for tf in self.inverse_kinematics.endeffector.reference_orientations:
707 tf.rd = numpy.copy(tf.ra)
709 self.inverse_kinematics.tuple_to_pose(
'desired', pose_tuple, self.settings.workspace_settings_tp.representation_of_orientation)
714 start_kinematic_inversion = time.time()
718 self.inverse_kinematics.initial_config_list = self.workspace_ic.nearest_configs(self.inverse_kinematics)
721 self.inverse_kinematics.goto_target()
723 elapsed_kinematic_inversion = time.time() - start_kinematic_inversion
725 self.workspace_tp.config_list[cnt] = numpy.copy(self.inverse_kinematics.q)
727 (running_time, number_of_steps) = (self.inverse_kinematics.run_log.time_elapsed, len(self.inverse_kinematics.run_log.step))
729 if number_of_steps == 0:
731 average_step_time = running_time / number_of_steps
732 n_iters_total = n_iters_total + number_of_steps
734 if self.inverse_kinematics.in_target():
737 time_total = time_total + elapsed_kinematic_inversion
740 ik_initial = copy.deepcopy(self.inverse_kinematics)
741 assert ik_initial.set_config(self.inverse_kinematics.initial_config)
742 if ik_initial.in_target():
743 print "Already in Target!"
745 start_config_str = ik_initial.config_str()
746 start_pose_str = str(ik_initial)
748 final_config_str = self.inverse_kinematics.config_str()
749 final_pose_str = str(self.inverse_kinematics)
751 run_log = loglib.Single_Run_Log(cnt, success = self.inverse_kinematics.in_target(), config_in_range = self.inverse_kinematics.joints_in_range(self.inverse_kinematics.free_config(self.inverse_kinematics.q)))
752 run_log.num_trial = 1 + int(number_of_steps/self.inverse_kinematics.ik_settings.number_of_steps)
753 run_log.num_suc_til_now = n_suc
754 run_log.num_iter = number_of_steps
755 run_log.num_iter_til_now = n_iters_total
756 run_log.run_time = elapsed_kinematic_inversion
757 run_log.run_time_til_now = time_total
758 run_log.mean_stp_time = average_step_time
759 run_log.start_config_str = start_config_str
760 run_log.final_config_str = final_config_str
761 run_log.start_pose_str = start_pose_str
762 run_log.final_pose_str = final_pose_str
764 self.km_log.body.append(run_log)
770 print str(self.km_log.body[cnt - 1])
771 print 'Log: (Running Time, Number of Iterations)', (running_time, number_of_steps)
772 print "______________________________________________________________________________________________________________________________"
776 self.km_log.header = self.settings
777 self.km_log.footer.calculate_statistics(self.km_log.body)
780 def execute(self, save_evaluation_log = True, save_evaluation_results = False, save_evaluation_csv = True, verbose = False):
782 execute the evaluation according to the settings
789 result_info_detail = str()
791 test_key_str = self.settings.generate_key()
793 if self.settings.workspace_settings_ic.search_criteria ==
'NCC':
794 assert self.inverse_kinematics.ik_settings.include_current_config,
"Error todo"
796 assert not self.inverse_kinematics.ik_settings.include_current_config,
"Error todo"
798 self.evaluate_ik_solver(verbose = verbose)
800 if save_evaluation_csv:
801 self.km_log.write_csv(filename = self.settings.path_str + test_key_str +
'.csv')
803 if save_evaluation_log:
804 self.km_log.write_log(filename = self.settings.path_str + test_key_str +
'.log')
806 if save_evaluation_results:
807 self.km_log.write_self(filename = self.settings.path_str + test_key_str +
'.res')