amino  1.0-beta2
Lightweight Robot Utility Library
kinematics.py
Go to the documentation of this file.
1 # Copyright (c) 2019, Colorado School of Mines
2 # All rights reserved.
3 #
4 # Author(s): Neil T. Dantam <ndantam@mines.edu>
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 #
13 # * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials provided
16 # with the distribution.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
23 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25 # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
28 # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29 # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 # SUCH DAMAGE.
31 
32 
35 """Forward, differential, and inverse kinematics."""
36 
37 import ctypes
38 from amino.lib import libamino
39 from amino.tf import QuatTrans
40 from amino.mat import DVec, DMat
41 from amino.scenegraph import RxSg, RxSgSub
42 
43 
46 
47 
48 class RxFK(ctypes.Structure):
49  """Opaque type for fk result pointer"""
50 
51 class SceneFK:
52  """Forward Kinematics."""
53  __slots__ = ['_ptr', '_q', 'scenegraph']
54 
55  def __init__(self, scenegraph):
56  self.scenegraphscenegraph = scenegraph
57  self._ptr_ptr = libamino.aa_rx_fk_malloc(scenegraph._ptr)
58  self._q_q = DVec(scenegraph.config_count)
59 
60  def __del__(self):
61  libamino.aa_rx_fk_destroy(self._ptr_ptr)
62 
63  def __getitem__(self, key):
64  """Get a transform.
65 
66  Args:
67  key: a frame name/id or pair of frame names/ids.
68  """
69  E = QuatTrans()
70  if isinstance(key, tuple):
71  parent, child = key
72  parent = self.scenegraphscenegraph.ensure_frame_id(parent)
73  child = self.scenegraphscenegraph.ensure_frame_id(child)
74  libamino.aa_rx_fk_get_rel_qutr(self._ptr_ptr, parent, child, E)
75  else:
76  key = self.scenegraphscenegraph.ensure_frame_id(key)
77  libamino.aa_rx_fk_get_abs_qutr(self._ptr_ptr, key, E)
78  return E
79 
80  @property
81  def config(self):
82  """The current configuration."""
83  return self._q_q
84 
85  @config.setter
86  def config(self, config):
87  self.scenegraphscenegraph.config_vector(config, self._q_q)
88  libamino.aa_rx_fk_all(self._ptr_ptr, self._q_q)
89  return self._q_q
90 
91  def __len__(self):
92  """Number of frames."""
93  return libamino.aa_rx_fk_cnt(self._ptr_ptr)
94 
95  def _data_ptr(self):
96  """Return pointer to data."""
97  return libamino.aa_rx_fk_data(self._ptr_ptr)
98 
99  def _data_ld(self):
100  """Return leading dimension of data."""
101  return libamino.aa_rx_fk_ld(self._ptr_ptr)
102 
103 
104 libamino.aa_rx_fk_malloc.argtypes = [ctypes.POINTER(RxSg)]
105 libamino.aa_rx_fk_malloc.restype = ctypes.POINTER(RxFK)
106 
107 libamino.aa_rx_fk_destroy.argtypes = [ctypes.POINTER(RxFK)]
108 
109 libamino.aa_rx_fk_all.argtypes = [ctypes.POINTER(RxFK), ctypes.POINTER(DVec)]
110 
111 libamino.aa_rx_fk_get_abs_qutr.argtypes = [
112  ctypes.POINTER(RxFK), ctypes.c_int,
113  ctypes.POINTER(QuatTrans)
114 ]
115 
116 libamino.aa_rx_fk_get_rel_qutr.argtypes = [
117  ctypes.POINTER(RxFK), ctypes.c_int, ctypes.c_int,
118  ctypes.POINTER(QuatTrans)
119 ]
120 
121 libamino.aa_rx_fk_data.argtypes = [ctypes.POINTER(RxFK)]
122 libamino.aa_rx_fk_data.restype = ctypes.POINTER(ctypes.c_double)
123 
124 libamino.aa_rx_fk_ld.argtypes = [ctypes.POINTER(RxFK)]
125 libamino.aa_rx_fk_ld.restype = ctypes.c_size_t
126 
127 libamino.aa_rx_fk_cnt.argtypes = [ctypes.POINTER(RxFK)]
128 libamino.aa_rx_fk_cnt.restype = ctypes.c_size_t
129 
130 
133 
134 
135 class RxWkOpts(ctypes.Structure):
136  """Opaque type for workspace options result pointer"""
137 
138 class SceneDK:
139  """Differential Kinematics"""
140  __slots__ = [
141  "opts",
142  "ssg",
143  "fk",
144  "_tf_ref",
145  "_tf_vel_ref",
146  "_config_ref",
147  "dx",
148  ]
149 
150  def __init__(self, sub_scenegraph, scene_fk):
151  self.ssgssg = sub_scenegraph
152  self.fkfk = scene_fk
153  self.optsopts = libamino.aa_rx_wk_opts_create()
154  self._tf_ref_tf_ref = None
155  self._tf_vel_ref_tf_vel_ref = None
156  self._config_ref_config_ref = None
157  self.dxdx = DVec(6)
158 
159  def __del__(self):
160  libamino.aa_rx_wk_opts_destroy(self.optsopts)
161 
162  @property
163  def ref_tf(self):
164  """Reference pose."""
165  return self._tf_ref_tf_ref
166 
167  @ref_tf.setter
168  def ref_tf(self, tf):
169  self._tf_ref_tf_ref = QuatTrans(tf)
170 
171  @property
172  def ref_tf_vel(self):
173  """Reference pose velocity."""
174  # TODO: should we copy?
175  return self._tf_vel_ref_tf_vel_ref
176 
177  @ref_tf_vel.setter
178  def ref_tf_vel(self, dx):
179  # TODO: should we copy?
180  self._tf_vel_ref_tf_vel_ref = dx
181 
182  @property
183  def ref_config_all(self):
184  """Reference configuration."""
185  # TODO: should we to copy?
186  return self._config_ref_config_ref
187 
188  @ref_config_all.setter
189  def ref_config_all(self, value):
190  """Reference configuration."""
191  sg = self.ssgssg.scenegraph
192  self._config_ref_config_ref = sg.copy_config(value)
193 
194  def solve_vel(self, dq=None):
195  """Solve for velocity.
196 
197  Returns:
198  sub-scenegraph configuration velocity or None if no solution.
199  """
200  if (self._tf_ref_tf_ref is None) and (self._tf_vel_ref_tf_vel_ref is None):
201  raise Exception("No reference provided.")
202 
203  if dq is None:
204  dq = DVec(self.ssgssg.config_count)
205 
206  dx = self.dxdx
207 
208  # velocity reference
209  if self._tf_vel_ref_tf_vel_ref:
210  dx.copy_from(self._tf_vel_ref_tf_vel_ref)
211  else:
212  dx.zero()
213 
214  # position reference
215  if self._tf_ref_tf_ref:
216  tf_act = self.fkfk[self.ssgssg.end_effector_id]
217  libamino.aa_rx_wk_dx_pos(self.optsopts, tf_act, self._tf_ref_tf_ref, dx)
218 
219  # configuration reference
220  # TODO
221 
222  r = libamino.aa_rx_wk_dx2dq(self.ssgssg._ptr, self.optsopts, self.fkfk._ptr, dx,
223  dq)
224 
225  return dq if r == 0 else None
226 
227 
228 libamino.aa_rx_wk_opts_create.argtypes = []
229 libamino.aa_rx_wk_opts_create.restype = ctypes.POINTER(RxWkOpts)
230 libamino.aa_rx_wk_opts_destroy.argtypes = [ctypes.POINTER(RxWkOpts)]
231 
232 libamino.aa_rx_wk_dx2dq.argtypes = [
233  ctypes.POINTER(RxSgSub),
234  ctypes.POINTER(RxWkOpts),
235  ctypes.POINTER(RxFK),
236  ctypes.POINTER(DVec),
237  ctypes.POINTER(DVec)
238 ]
239 libamino.aa_rx_wk_dx2dq.restype = ctypes.c_int
240 
241 libamino.aa_rx_wk_dx_pos.argtypes = [
242  ctypes.POINTER(RxWkOpts),
243  ctypes.POINTER(QuatTrans),
244  ctypes.POINTER(QuatTrans),
245  ctypes.POINTER(DVec)
246 ]
247 
248 
251 
252 
253 class RxIK(ctypes.Structure):
254  """Opaque type for inverse kinematics context"""
255 
256 class RxIKParm(ctypes.Structure):
257  """Opaque type for inverse kinematics parameters"""
258 
259 class SceneIK:
260  """Inverse Kinematics"""
261  __slots__ = ["_ptr", "ik_parm", "ssg", "_tf_ref"]
262 
263  def __init__(self, sub_scenegraph):
264  self.ssgssg = sub_scenegraph
265  self._tf_ref_tf_ref = None
266  self.ik_parmik_parm = libamino.aa_rx_ik_parm_create()
267  self._ptr_ptr = libamino.aa_rx_ik_cx_create(self.ssgssg._ptr, self.ik_parmik_parm)
268 
269  def __del__(self):
270  libamino.aa_rx_ik_cx_destroy(self._ptr_ptr)
271  libamino.aa_rx_ik_parm_destroy(self.ik_parmik_parm)
272 
273  @property
274  def ref_tf(self):
275  """Reference transformation"""
276  return self._tf_ref_tf_ref
277 
278  @ref_tf.setter
279  def ref_tf(self, tf_ref):
280  """Set the reference transformation"""
281  self._tf_ref_tf_ref = QuatTrans(tf_ref)
282 
283  def set_seed(self, config_sub):
284  """Sets the optimization seed."""
285  q = self.ssgssg.config_vector(config_sub)
286  libamino.aa_rx_ik_set_seed(self._ptr_ptr, q)
287 
288  def set_seed_center(self):
289  """Sets the optimization seed to the joint center position."""
290  libamino.aa_rx_ik_set_seed_center(self._ptr_ptr)
291 
292  def set_seed_rand(self):
293  """Sets the optimization seed to a random position."""
294  libamino.aa_rx_ik_set_seed_rand(self._ptr_ptr)
295 
296  def set_obj(self, fun):
297  """Sets the objective function for optimization."""
298  libamino.aa_rx_ik_parm_set_obj(self.ik_parmik_parm, fun)
299 
300  def set_tol_angle(self, angle):
301  """Sets the angle error tolerance"""
302  libamino.aa_rx_ik_parm_set_tol_angle(self.ik_parmik_parm, angle)
303 
304  def set_tol_trans(self, trans):
305  """Sets the translational error tolerance"""
306  libamino.aa_rx_ik_parm_set_tol_trans(self.ik_parmik_parm, trans)
307 
308  @property
309  def restart_time(self):
310  """Maximum time limit for IK restarts."""
311  return libamino.aa_rx_ik_get_restart_time(self._ptr_ptr)
312 
313  @restart_time.setter
314  def restart_time(self, t):
315  libamino.aa_rx_ik_set_restart_time(self._ptr_ptr, t)
316 
317  def solve(self):
318  """
319  Solves the IK problem.
320 
321  Returns:
322  The sub-scenegraph configuration vector or None if no solution.
323  """
324  if self._tf_ref_tf_ref is None:
325  raise Exception("No reference provided.")
326 
327  M = DMat((len(self._tf_ref_tf_ref), 1))
328  M.col_vec(0).copy_from(self._tf_ref_tf_ref)
329 
330  q = DVec(self.ssgssg.config_count)
331 
332  r = libamino.aa_rx_ik_solve(self._ptr_ptr, M, q)
333 
334  return q if r == 0 else None
335 
336 
337 libamino.aa_rx_ik_parm_create.argtypes = []
338 libamino.aa_rx_ik_parm_create.restype = ctypes.POINTER(RxIKParm)
339 libamino.aa_rx_ik_parm_destroy.argtypes = [ctypes.POINTER(RxIKParm)]
340 
341 libamino.aa_rx_ik_cx_create.argtypes = [
342  ctypes.POINTER(RxSgSub), ctypes.POINTER(RxIKParm)
343 ]
344 libamino.aa_rx_ik_cx_create.restype = ctypes.POINTER(RxIK)
345 libamino.aa_rx_ik_cx_destroy.argtypes = [ctypes.POINTER(RxIK)]
346 
347 libamino.aa_rx_ik_solve.argtypes = [
348  ctypes.POINTER(RxIK),
349  ctypes.POINTER(DMat),
350  ctypes.POINTER(DVec)
351 ]
352 libamino.aa_rx_ik_solve.restype = ctypes.c_int
353 
354 libamino.aa_rx_ik_set_seed.argtypes = [
355  ctypes.POINTER(RxIK), ctypes.POINTER(DVec)
356 ]
357 libamino.aa_rx_ik_set_seed_center.argtypes = [ctypes.POINTER(RxIK)]
358 libamino.aa_rx_ik_set_seed_rand.argtypes = [ctypes.POINTER(RxIK)]
359 
360 libamino.aa_rx_ik_set_restart_time.argtypes = [
361  ctypes.POINTER(RxIK), ctypes.c_double
362 ]
363 
364 libamino.aa_rx_ik_parm_set_tol_angle.argtypes = [ctypes.POINTER(RxIKParm), ctypes.c_double]
365 libamino.aa_rx_ik_parm_set_tol_trans.argtypes = [ctypes.POINTER(RxIKParm), ctypes.c_double]
366 libamino.aa_rx_ik_get_restart_time.argtypes = [ctypes.POINTER(RxIK)]
367 libamino.aa_rx_ik_get_restart_time.restype = ctypes.c_double
Inverse Kinematics ##.
Definition: kinematics.py:258
Differential Kinematics ##.
Definition: kinematics.py:140
def ref_tf(self)
Reference pose.
Definition: kinematics.py:168
def solve_vel(self, dq=None)
Solve for velocity.
Definition: kinematics.py:203
def ref_config_all(self)
Reference configuration.
Definition: kinematics.py:188
def ref_tf_vel(self)
Reference pose velocity.
Definition: kinematics.py:177
def __len__(self)
Number of frames.
Definition: kinematics.py:92
def config(self)
The current configuration.
Definition: kinematics.py:82
def __getitem__(self, key)
Get a transform.
Definition: kinematics.py:68
def solve(self)
Solves the IK problem.
Definition: kinematics.py:327
def ref_tf(self)
Reference transformation.
Definition: kinematics.py:279
def set_obj(self, fun)
Sets the objective function for optimization.
Definition: kinematics.py:301
def set_seed_center(self)
Sets the optimization seed to the joint center position.
Definition: kinematics.py:293
def restart_time(self)
Maximum time limit for IK restarts.
Definition: kinematics.py:314
def set_seed_rand(self)
Sets the optimization seed to a random position.
Definition: kinematics.py:297
def set_tol_angle(self, angle)
Sets the angle error tolerance.
Definition: kinematics.py:305
def set_seed(self, config_sub)
Sets the optimization seed.
Definition: kinematics.py:288
def set_tol_trans(self, trans)
Sets the translational error tolerance.
Definition: kinematics.py:309
Matrix of double floats.
Definition: mat.py:272
Vector of double floats.
Definition: mat.py:49
Class for Quaternion-Translation.
Definition: tf.py:1092
Definition: lib.py:1
Definition: mat.py:1
Definition: tf.py:1