amino  1.0-beta2
Lightweight Robot Utility Library
scenegraph.py
Go to the documentation of this file.
1 # Copyright (c) 2020, Colorado School of Mines
2 # All rights reserved.
3 #
4 # Author(s): Neil T. Dantam <ndantam@mines.edu>
5 # Matthew A. Schack <mschack@mines.edu>
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 #
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 #
14 # * Redistributions in binary form must reproduce the above
15 # copyright notice, this list of conditions and the following
16 # disclaimer in the documentation and/or other materials provided
17 # with the distribution.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
20 # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
21 # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
24 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26 # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29 # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 # SUCH DAMAGE.
32 
33 
36 """Scene graphs"""
37 
38 import ctypes
39 from amino.lib import libamino
40 from amino.tf import Vec3, Quat, QuatTrans
41 from amino.mat import DVec, DMat
42 from amino.util import ensure_cstring, is_string
43 
44 
45 FRAME_ROOT = ctypes.c_long.in_dll(libamino, "aa_rx_frame_root").value
46 
47 
48 FRAME_NONE = ctypes.c_long.in_dll(libamino, "aa_rx_frame_none").value
49 
50 
51 CONFIG_NONE = ctypes.c_long.in_dll(libamino, "aa_rx_config_none").value
52 
53 
54 CONFIG_MULTI = ctypes.c_long.in_dll(libamino, "aa_rx_config_multi").value
55 
56 
57 class RxSg(ctypes.Structure):
58  """Opaque type for scenegraph pointer."""
59 
60 class RxSgSub(ctypes.Structure):
61  """Opaque type for sub-scenegraph pointer."""
62 
63 class RxGeom(ctypes.Structure):
64  """Opaque type for geometry pointer."""
65 
66 class RxGeomOpt(ctypes.Structure):
67  """Opaque type for geometry opts pointer."""
68 
69 class GeomOpt:
70  """Geometry options object.
71 
72  Attributes:
73 
74  """
75  __slots__ = ['_ptr']
76 
77  def __init__(self, options=None):
78  """Constructs object with default and specified options.
79 
80  Args:
81  options: A dictionary of options corresponding to GeomOpt attributes."""
82  self._ptr_ptr = libamino.aa_rx_geom_opt_create()
83  if options:
84  for key in options:
85  self.__setattr__(key, options[key])
86 
87  def __del__(self):
88  libamino.aa_rx_geom_opt_destroy(self._ptr_ptr)
89 
90  def _get_val(self, func):
91  return func(self._ptr_ptr).value
92 
93  def _get_val3(self, func0, func1, func2):
94  return [
95  self._get_val_get_val(func0),
96  self._get_val_get_val(func1),
97  self._get_val_get_val(func2)
98  ]
99 
100  def _get_bool(self, func):
101  v = self._get_val_get_val(func)
102  return bool(v)
103 
104  @property
105  def visual(self):
106  """Boolean indicating whether to use for visual geometry."""
107  return self._get_bool_get_bool(libamino.aa_rx_geom_opt_get_visual)
108 
109  @property
110  def collision(self):
111  """Boolean indicating whether to use for collision geometry."""
112  return self._get_bool_get_bool(libamino.aa_rx_geom_opt_get_collision)
113 
114  @property
115  def no_shadow(self):
116  """Boolean indicating to not display a shadow."""
117  return self._get_bool_get_bool(libamino.aa_rx_geom_opt_get_no_shadow)
118 
119  @property
120  def alpha(self):
121  """Float indicating alpha (transparency)."""
122  return self._get_val_get_val(libamino.aa_rx_geom_opt_get_alpha)
123 
124  @property
125  def scale(self):
126  """Float indicating how much to scale the geometry."""
127  return self._get_val_get_val(libamino.aa_rx_geom_opt_get_scale)
128 
129  @property
130  def color(self):
131  """Three floats, between 0 and 1, for color in red-blue-green order."""
132  return self._get_val3_get_val3(libamino.aa_rx_geom_opt_get_color_red,
133  libamino.aa_rx_geom_opt_get_color_blue,
134  libamino.aa_rx_geom_opt_get_color_green)
135 
136  @property
137  def specular(self):
138  """Three floats, between 0 and 1, for color in red-blue-green order."""
139  return self._get_val3_get_val3(libamino.aa_rx_geom_opt_get_specular_red,
140  libamino.aa_rx_geom_opt_get_specular_blue,
141  libamino.aa_rx_geom_opt_get_specular_green)
142 
143  @visual.setter
144  def visual(self, value):
145  libamino.aa_rx_geom_opt_set_visual(self._ptr_ptr, value)
146 
147  @collision.setter
148  def collision(self, value):
149  libamino.aa_rx_geom_opt_set_collision(self._ptr_ptr, value)
150 
151  @no_shadow.setter
152  def no_shadow(self, value):
153  libamino.aa_rx_geom_opt_set_no_shadow(self._ptr_ptr, value)
154 
155  @alpha.setter
156  def alpha(self, value):
157  libamino.aa_rx_geom_opt_set_alpha(self._ptr_ptr, value)
158 
159  @scale.setter
160  def scale(self, value):
161  libamino.aa_rx_geom_opt_set_scale(self._ptr_ptr, value)
162 
163  @color.setter
164  def color(self, value):
165  libamino.aa_rx_geom_opt_set_color3(self._ptr_ptr, value[0], value[1],
166  value[2])
167 
168  @specular.setter
169  def specular(self, value):
170  libamino.aa_rx_geom_opt_set_specular3(self._ptr_ptr, value[0], value[1],
171  value[2])
172 
173  @staticmethod
174  def ensure(thing):
175  """Ensures thing is a GeomOpt, converting dicts if necessary."""
176  if isinstance(thing, GeomOpt):
177  return thing
178  elif isinstance(thing, dict):
179  return GeomOpt(thing)
180  elif thing is None:
181  return GeomOpt()
182  else:
183  raise Exception()
184 
185 
186 class Geom:
187  """A geometry object."""
188 
189  __slots__ = ['_ptr']
190 
191  def __init__(self, _ptr):
192  self._ptr_ptr = _ptr
193 
194  @staticmethod
195  def box(opt, dimension):
196  """Creates a box geometry object."""
197  o = GeomOpt.ensure(opt)
198  return Geom(libamino.aa_rx_geom_box(o._ptr, Vec3.ensure(dimension)))
199 
200  @staticmethod
201  def sphere(opt, radius):
202  """Creates a sphere geometry object."""
203  o = GeomOpt.ensure(opt)
204  return Geom(libamino.aa_rx_geom_sphere(o._ptr, radius))
205 
206  @staticmethod
207  def cylinder(opt, height, radius):
208  """Creates a cylinder geometry object."""
209  o = GeomOpt.ensure(opt)
210  return Geom(libamino.aa_rx_geom_cylinder(o._ptr, height, radius))
211 
212  @staticmethod
213  def cone(opt, height, start_radius, end_radius):
214  """Creates a cone geometry object."""
215  o = GeomOpt.ensure(opt)
216  return Geom(
217  libamino.aa_rx_geom_cone(o._ptr, height, start_radius, end_radius))
218 
219  @staticmethod
220  def torus(opt, angle, major_radius, minor_radius):
221  """Creates a torus geometry object."""
222  o = GeomOpt.ensure(opt)
223  return Geom(
224  libamino.aa_rx_geom_torus(o._ptr, angle, major_radius,
225  minor_radius))
226 
227  @staticmethod
228  def grid(opt, dimension, delta, width):
229  """Creates a grid geometry object."""
230  o = GeomOpt.ensure(opt)
231  c_dimension = (ctypes.c_double * 2)(dimension[0], dimension[1])
232  c_delta = (ctypes.c_double * 2)(delta[0], delta[1])
233  # c_dimension[0] = dimension[0]
234  # c_dimension[1] = dimension[1]
235  # c_delta[0] = delta[0]
236  # c_delta[1] = delta[1]
237  return Geom(
238  libamino.aa_rx_geom_grid(o._ptr, c_dimension, c_delta, width))
239 
240 
241 libamino.aa_rx_geom_opt_create.argtypes = []
242 libamino.aa_rx_geom_opt_create.restype = ctypes.POINTER(RxGeomOpt)
243 libamino.aa_rx_geom_opt_destroy.argtypes = [ctypes.POINTER(RxGeomOpt)]
244 
245 libamino.aa_rx_geom_opt_set_no_shadow.argtypes = [
246  ctypes.POINTER(RxGeomOpt), ctypes.c_int
247 ]
248 
249 libamino.aa_rx_geom_opt_set_visual.argtypes = [
250  ctypes.POINTER(RxGeomOpt), ctypes.c_int
251 ]
252 
253 libamino.aa_rx_geom_opt_set_collision.argtypes = [
254  ctypes.POINTER(RxGeomOpt), ctypes.c_int
255 ]
256 
257 libamino.aa_rx_geom_opt_set_alpha.argtypes = [
258  ctypes.POINTER(RxGeomOpt), ctypes.c_double
259 ]
260 
261 libamino.aa_rx_geom_opt_set_color3.argtypes = [
262  ctypes.POINTER(RxGeomOpt), ctypes.c_double, ctypes.c_double,
263  ctypes.c_double
264 ]
265 
266 libamino.aa_rx_geom_opt_set_specular3.argtypes = [
267  ctypes.POINTER(RxGeomOpt), ctypes.c_double, ctypes.c_double,
268  ctypes.c_double
269 ]
270 
271 libamino.aa_rx_geom_opt_set_scale.argtypes = [
272  ctypes.POINTER(RxGeomOpt), ctypes.c_double
273 ]
274 
275 libamino.aa_rx_geom_opt_get_scale.argtypes = [ctypes.POINTER(RxGeomOpt)]
276 libamino.aa_rx_geom_opt_get_scale.restypes = ctypes.c_double
277 
278 libamino.aa_rx_geom_opt_get_alpha.argtypes = [ctypes.POINTER(RxGeomOpt)]
279 libamino.aa_rx_geom_opt_get_alpha.restypes = ctypes.c_double
280 
281 libamino.aa_rx_geom_opt_get_color_red.argtypes = [ctypes.POINTER(RxGeomOpt)]
282 libamino.aa_rx_geom_opt_get_color_red.restypes = ctypes.c_double
283 libamino.aa_rx_geom_opt_get_color_blue.argtypes = [ctypes.POINTER(RxGeomOpt)]
284 libamino.aa_rx_geom_opt_get_color_blue.restypes = ctypes.c_double
285 libamino.aa_rx_geom_opt_get_color_green.argtypes = [ctypes.POINTER(RxGeomOpt)]
286 libamino.aa_rx_geom_opt_get_color_green.restypes = ctypes.c_double
287 
288 libamino.aa_rx_geom_opt_get_specular_red.argtypes = [ctypes.POINTER(RxGeomOpt)]
289 libamino.aa_rx_geom_opt_get_specular_red.restypes = ctypes.c_double
290 libamino.aa_rx_geom_opt_get_specular_blue.argtypes = [
291  ctypes.POINTER(RxGeomOpt)
292 ]
293 libamino.aa_rx_geom_opt_get_specular_blue.restypes = ctypes.c_double
294 libamino.aa_rx_geom_opt_get_specular_green.argtypes = [
295  ctypes.POINTER(RxGeomOpt)
296 ]
297 libamino.aa_rx_geom_opt_get_specular_green.restypes = ctypes.c_double
298 
299 libamino.aa_rx_geom_box.argtypes = [
300  ctypes.POINTER(RxGeomOpt), ctypes.POINTER(Vec3)
301 ]
302 libamino.aa_rx_geom_box.restype = ctypes.POINTER(RxGeom)
303 
304 libamino.aa_rx_geom_sphere.argtypes = [
305  ctypes.POINTER(RxGeomOpt), ctypes.c_double
306 ]
307 libamino.aa_rx_geom_sphere.restype = ctypes.POINTER(RxGeom)
308 
309 libamino.aa_rx_geom_cylinder.argtypes = [
310  ctypes.POINTER(RxGeomOpt), ctypes.c_double, ctypes.c_double
311 ]
312 libamino.aa_rx_geom_cylinder.restype = ctypes.POINTER(RxGeom)
313 
314 libamino.aa_rx_geom_cone.argtypes = [
315  ctypes.POINTER(RxGeomOpt), ctypes.c_double, ctypes.c_double,
316  ctypes.c_double
317 ]
318 libamino.aa_rx_geom_cone.restype = ctypes.POINTER(RxGeom)
319 
320 libamino.aa_rx_geom_grid.argtypes = [
321  ctypes.POINTER(RxGeomOpt),
322  ctypes.POINTER(ctypes.c_double),
323  ctypes.POINTER(ctypes.c_double), ctypes.c_double
324 ]
325 libamino.aa_rx_geom_grid.restype = ctypes.POINTER(RxGeom)
326 
327 libamino.aa_rx_geom_torus.argtypes = [
328  ctypes.POINTER(RxGeomOpt), ctypes.c_double, ctypes.c_double,
329  ctypes.c_double
330 ]
331 libamino.aa_rx_geom_torus.restype = ctypes.POINTER(RxGeom)
332 
333 
334 class SceneGraph:
335  """A scene graph."""
336  __slots__ = ['_ptr']
337 
338  def __init__(self, ptr=None):
339  if ptr is None:
340  self._ptr_ptr = libamino.aa_rx_sg_create()
341  else:
342  self._ptr_ptr = ptr
343 
344  def __del__(self):
345  libamino.aa_rx_sg_destroy(self._ptr_ptr)
346 
347  def add_frame_fixed(self, parent, name, tf=QuatTrans.identity(),
348  geom=None):
349  """Adds a new fixed frame to the scene."""
350  E = QuatTrans.ensure(tf)
351  name = ensure_cstring(name)
352  parent = ensure_cstring(parent)
353  libamino.aa_rx_sg_add_frame_fixed(self._ptr_ptr, parent, name, E.quat,
354  E.trans)
355  self.attach_geomattach_geom(name, geom)
356 
357  def add_frame_revolute(self,
358  parent,
359  name,
360  tf=QuatTrans.identity(),
361  config_name=None,
362  axis=(0, 0, 1),
363  offset=0,
364  geom=None):
365  """Adds a new revolute frame to the scene."""
366  E = QuatTrans.ensure(tf)
367  if config_name is None:
368  config_name = name
369  name = ensure_cstring(name)
370  parent = ensure_cstring(parent)
371  config_name = ensure_cstring(config_name)
372  libamino.aa_rx_sg_add_frame_revolute(self._ptr_ptr, parent, name, E.quat,
373  E.trans, config_name,
374  Vec3.ensure(axis), offset)
375  self.attach_geomattach_geom(name, geom)
376 
377  def add_frame_prismatic(self,
378  parent,
379  name,
380  tf=QuatTrans.identity(),
381  config_name=None,
382  axis=(0, 0, 1),
383  offset=0,
384  geom=None,
385  limits=None):
386  """Adds a new prismatic frame to the scene."""
387  E = QuatTrans.ensure(tf)
388  if config_name is None:
389  config_name = name
390  name = ensure_cstring(name)
391  parent = ensure_cstring(parent)
392  config_name = ensure_cstring(config_name)
393  libamino.aa_rx_sg_add_frame_prismatic(self._ptr_ptr, parent, name, E.quat,
394  E.trans, config_name,
395  Vec3.ensure(axis), offset)
396  self.attach_geomattach_geom(name, geom)
397 
398  if limits != None:
399  libamino.aa_rx_sg_set_limit_pos(self._ptr_ptr, config_name, limits[0], limits[1])
400 
401  def remove_frame(self, name):
402  """Removes a frame from the scene"""
403  libamino.aa_rx_sg_rm_frame(self._ptr_ptr, ensure_cstring(name))
404 
405  def attach_geom(self, name, geom):
406  """Attaches geometry to the named frame."""
407  name = ensure_cstring(name)
408  if geom is None:
409  return
410  elif isinstance(geom, Geom):
411  libamino.aa_rx_geom_attach(self._ptr_ptr, name, geom._ptr)
412  elif isinstance(geom, (list, tuple)):
413  for elt in geom:
414  self.attach_geomattach_geom(name, elt)
415  else:
416  raise Exception("Invalid Geom config provided.")
417 
418  def reparent(self, new_parent, frame, rel_tf=QuatTrans.identity()):
419  """Change the parent of frame in the scenegraph."""
420  frame = ensure_cstring(frame)
421  new_parent = ensure_cstring(new_parent)
422  libamino.aa_rx_sg_reparent_name(self._ptr_ptr, new_parent, frame, rel_tf)
423 
424 
425  def load(self, filename, name, root=""):
426  """Loads a scene plugin into this scene.
427 
428  Args:
429  filname: plugin name, passed directly to dlopen().
430  name: scene name, as provided to the scene compiler.
431  root: parent frame for the loaded scene.
432 
433  Raises:
434  LookupError: the shared object or named scene could not be found.
435  """
436  root = ensure_cstring(root)
437  name = ensure_cstring(name)
438  filename = ensure_cstring(filename)
439  r = libamino.aa_rx_dl_sg_at(filename, name, self._ptr_ptr, root)
440  if r is None:
441  raise LookupError("Could not load scene %s:%s" % (filename, name))
442 
443  def init(self):
444  """Initializes the scene, must be called after all frames are added."""
445  libamino.aa_rx_sg_init(self._ptr_ptr)
446  return self
447 
448  def allow_collision(self, i, j, allowed=1):
449  """Set allowed collisions between frames id0 and id1."""
450  id0 = self.ensure_frame_idensure_frame_id(i)
451  id1 = self.ensure_frame_idensure_frame_id(j)
452  libamino.aa_rx_sg_allow_collision(self._ptr_ptr, id0, id1, allowed)
453 
454 
455  @property
456  def config_count(self):
457  """Number of configuration variables in the scene."""
458  return libamino.aa_rx_sg_config_count(self._ptr_ptr)
459 
460  @property
461  def frame_count(self):
462  """Number of frames in the scene."""
463  return libamino.aa_rx_sg_frame_count(self._ptr_ptr)
464 
465  def config_id(self, name):
466  """Returns the config id for string name."""
467  name = ensure_cstring(name)
468  return libamino.aa_rx_sg_config_id(self._ptr_ptr, name)
469 
470  def frame_id(self, name):
471  """Returns the frame id for string name."""
472  name = ensure_cstring(name)
473  return libamino.aa_rx_sg_frame_id(self._ptr_ptr, name)
474 
475  def config_name(self, i):
476  """Returns the config name for the id."""
477  name = libamino.aa_rx_sg_config_name(self._ptr_ptr, i)
478  return str(name, encoding="utf-8")
479 
480  def frame_name(self, i):
481  """Returns the frame name for the id.
482 
483  Raises:
484  IndexError: value is out of range.
485  """
486  if i >= self.frame_countframe_count or i < FRAME_NONE:
487  raise IndexError("Invalid frame id: %d" % i)
488 
489  name = libamino.aa_rx_sg_frame_name(self._ptr_ptr, i)
490  return str(name, encoding="utf-8")
491 
492  def ensure_config_id(self, value):
493  """Ensures value is a config id, converting strings if necessary.
494 
495  Raises:
496  IndexError: value is out range.
497  ValueError: config name is invalid.
498  """
499  if is_string(value):
500  if self.config_idconfig_id(value) == CONFIG_NONE:
501  raise ValueError("Invalid config name: %s" % value)
502  return self.config_idconfig_id(value)
503 
504  if value >= self.config_countconfig_count or value < 0:
505  raise IndexError("Invalid config id: %d" % value)
506  return value
507 
508  def ensure_config_name(self, value):
509  """Ensures value is a string config name, converting int ids if necessary.
510 
511  Raises:
512  IndexError: value is out of range.
513  ValueError: config name is invalid.
514  """
515  if is_string(value):
516  id = self.config_idconfig_id(value)
517  if id == CONFIG_NONE:
518  raise ValueError("Invalid config name: %s" % value)
519  return value
520 
521  if value >= self.config_countconfig_count or value < 0:
522  raise IndexError("Invalid config id: %d" % value)
523  return self.frame_nameframe_name(value)
524 
525  def ensure_frame_id(self, value):
526  """Ensures value is a frame id, converting strings if necessary.
527 
528  Raises:
529  IndexError: value is out range.
530  ValueError: frame name is invalid.
531  """
532  if is_string(value):
533  id = self.frame_idframe_id(value)
534  if id == FRAME_NONE:
535  raise ValueError("Invalid frame name: %s" % value)
536  return id
537 
538  if value >= self.frame_countframe_count or value <= FRAME_NONE:
539  raise IndexError("Invalid frame id: %d" % value)
540  return value
541 
542  def ensure_frame_id_actual(self, value):
543  """Ensures value is a frame id, converting strings if necessary.
544 
545  The difference between this function and ensure_frame_id() is
546  that this function throws errors if given reserved frame ids,
547  FRAME_ROOT and FRAME_NONE.
548 
549  Raises:
550  IndexError: value is out range.
551  """
552  r = self.ensure_frame_idensure_frame_id(value)
553  if r < 0:
554  raise IndexError("Invalid frame id: %d" % value)
555  return r
556 
557  def ensure_frame_name(self, value):
558  """Ensures value is a string frame name, converting int ids if necessary.
559 
560  Raises:
561  IndexError: value is out of range.
562  ValueError: frame name is invalid.
563  """
564  if is_string(value):
565  id = self.frame_idframe_id(value)
566  if id == FRAME_NONE:
567  raise ValueError("Invalid frame name: %s" % value)
568  return value
569 
570  if value >= self.frame_countframe_count or value <= FRAME_NONE:
571  raise IndexError("Invalid frame id: %d" % value)
572  return self.frame_nameframe_name(value)
573 
574  def config_vector(self, config, vector=None):
575  """Create or convert to a configuration vector.
576 
577  Raises:
578  IndexError: provided vector is the wrong size"""
579  if isinstance(config, dict):
580  if vector is None:
581  vector = DVec(self.config_countconfig_count)
582  vector.set(0)
583  elif len(vector) != self.config_countconfig_count:
584  raise IndexError()
585  for key in config:
586  vector[self.config_idconfig_id(key)] = config[key]
587  return vector
588  elif vector is None:
589  return DVec.ensure(config)
590  else:
591  vector.copy_from(config)
592  return vector
593 
594  def copy_config(self, config):
595  """Copy configuration as a vector."""
596  return self.config_vectorconfig_vector(config, DVec(self.config_countconfig_count))
597 
598  def config_dict(self, vector):
599  """Convert vector to a dict."""
600  d = {}
601  for i in range(0, self.config_countconfig_count):
602  d[self.config_nameconfig_name(i)] = vector[i]
603  return d
604 
605  def get_parent(self, frame):
606  """Get the name of the parent of the input frame"""
607  frame_id = self.ensure_frame_idensure_frame_id(frame)
608  parent = libamino.aa_rx_sg_frame_parent(self._ptr_ptr, frame_id)
609  return self.ensure_frame_nameensure_frame_name(parent)
610 
611  def __getitem__(self, key):
612  """Return a SubSceneGraph for the chain from root to tip.
613 
614  Args:
615  key: a slice starting at the root and ending at the tip.
616 
617  Raises:
618  LookupError: invalid slice or frames
619  """
620  if isinstance(key, slice):
621  if key.step is not None:
622  raise LookupError("Cannot step scenegraph")
623  root_key = "" if key.start is None else key.start
624  root = self.ensure_frame_idensure_frame_id(root_key)
625  tip = self.ensure_frame_idensure_frame_id(key.stop)
626  ptr = libamino.aa_rx_sg_chain_create(self._ptr_ptr, root, tip)
627  return SubSceneGraph(self, ptr)
628 
629  raise LookupError("Could not get scene graph items")
630 
631  def copy(self):
632  """Create a copy of the scenegraph"""
633  sg_copy = SceneGraph(libamino.aa_rx_sg_copy(self._ptr_ptr))
634  sg_copy.init()
635  return sg_copy
636 
637 
638 
639 libamino.aa_rx_sg_create.argtypes = []
640 libamino.aa_rx_sg_create.restype = ctypes.POINTER(RxSg)
641 libamino.aa_rx_sg_destroy.argtypes = [ctypes.POINTER(RxSg)]
642 libamino.aa_rx_sg_init.argtypes = [ctypes.POINTER(RxSg)]
643 
644 libamino.aa_rx_sg_config_count.argtypes = [ctypes.POINTER(RxSg)]
645 libamino.aa_rx_sg_config_count.restype = ctypes.c_size_t
646 
647 libamino.aa_rx_sg_frame_count.argtypes = [ctypes.POINTER(RxSg)]
648 libamino.aa_rx_sg_frame_count.restype = ctypes.c_size_t
649 
650 libamino.aa_rx_sg_config_id.argtypes = [ctypes.POINTER(RxSg), ctypes.c_char_p]
651 libamino.aa_rx_sg_config_id.restype = ctypes.c_int
652 
653 libamino.aa_rx_sg_frame_id.argtypes = [ctypes.POINTER(RxSg), ctypes.c_char_p]
654 libamino.aa_rx_sg_frame_id.restype = ctypes.c_int
655 
656 libamino.aa_rx_sg_frame_name.argtypes = [ctypes.POINTER(RxSg), ctypes.c_int]
657 libamino.aa_rx_sg_frame_name.restype = ctypes.c_char_p
658 
659 libamino.aa_rx_sg_config_name.argtypes = [ctypes.POINTER(RxSg), ctypes.c_int]
660 libamino.aa_rx_sg_config_name.restype = ctypes.c_char_p
661 
662 libamino.aa_rx_sg_reparent_name.argtypes = [ctypes.POINTER(RxSg), ctypes.c_char_p,
663  ctypes.c_char_p, ctypes.POINTER(QuatTrans)]
664 
665 libamino.aa_rx_sg_tf.argtypes = [ctypes.POINTER(RxSg), ctypes.c_size_t,
666  ctypes.POINTER(ctypes.c_double), ctypes.c_size_t,
667  ctypes.POINTER(ctypes.c_double), ctypes.c_size_t,
668  ctypes.POINTER(ctypes.c_double), ctypes.c_size_t]
669 
670 libamino.aa_rx_sg_frame_parent.argtypes = [ctypes.POINTER(RxSg), ctypes.c_int]
671 libamino.aa_rx_sg_frame_parent.restype = ctypes.c_int
672 
673 
674 libamino.aa_rx_sg_copy.argtypes = [ctypes.POINTER(RxSg)]
675 libamino.aa_rx_sg_copy.restype = ctypes.POINTER(RxSg)
676 
677 libamino.aa_rx_sg_allow_collision.argtypes = [ctypes.POINTER(RxSg), ctypes.c_int,
678  ctypes.c_int, ctypes.c_int]
679 
680 libamino.aa_rx_sg_set_limit_pos.argtypes = [ctypes.POINTER(RxSg), ctypes.c_char_p,
681  ctypes.c_double, ctypes.c_double]
682 
683 libamino.aa_rx_dl_sg_at.argtypes = [
684  ctypes.c_char_p, ctypes.c_char_p,
685  ctypes.POINTER(RxSg), ctypes.c_char_p
686 ]
687 libamino.aa_rx_dl_sg_at.restype = ctypes.POINTER(RxSg)
688 
689 libamino.aa_rx_sg_add_frame_fixed.argtypes = [
690  ctypes.POINTER(RxSg), ctypes.c_char_p, ctypes.c_char_p,
691  ctypes.POINTER(Quat),
692  ctypes.POINTER(Vec3)
693 ]
694 
695 libamino.aa_rx_sg_add_frame_revolute.argtypes = [
696  ctypes.POINTER(RxSg), ctypes.c_char_p, ctypes.c_char_p,
697  ctypes.POINTER(Quat),
698  ctypes.POINTER(Vec3), ctypes.c_char_p,
699  ctypes.POINTER(Vec3), ctypes.c_double
700 ]
701 
702 libamino.aa_rx_sg_add_frame_prismatic.argtypes = [
703  ctypes.POINTER(RxSg), ctypes.c_char_p, ctypes.c_char_p,
704  ctypes.POINTER(Quat),
705  ctypes.POINTER(Vec3), ctypes.c_char_p,
706  ctypes.POINTER(Vec3), ctypes.c_double
707 ]
708 
709 libamino.aa_rx_sg_rm_frame.argtypes = [ctypes.POINTER(RxSg), ctypes.c_char_p]
710 
711 libamino.aa_rx_geom_attach.argtypes = [
712  ctypes.POINTER(RxSg), ctypes.c_char_p,
713  ctypes.POINTER(RxGeom)
714 ]
715 
716 libamino.aa_rx_sg_fill_tf_abs.argtypes = [
717  ctypes.POINTER(RxSg),
718  ctypes.POINTER(DVec),
719  ctypes.POINTER(DMat)
720 ]
721 
722 
723 class SubSceneGraph:
724  """A subset of a scene graph"""
725 
726  __slots__ = ['_ptr', 'scenegraph']
727 
728  def __init__(self, scenegraph, _ptr):
729  """Initialize from a scenegraph and sub-scenegraph pointer."""
730  self.scenegraphscenegraph = scenegraph
731  self._ptr_ptr = _ptr
732 
733  def __del__(self):
734  libamino.aa_rx_sg_sub_destroy(self._ptr_ptr)
735 
736  # def jacobian(self, tf):
737  # rows = ctypes.c_size_t()
738  # cols = ctypes.c_size_t()
739  # libamino.aa_rx_sg_sub_jacobian_size(self._ptr,
740  # ctypes.byref(rows), ctypes.byref(cols))
741  # J = DMat.create(rows.value, cols.value)
742  # libamino.aa_rx_sg_sub_jacobian(self._ptr,
743  # tf.cols(), tf.data(), tf.ld(),
744  # J.data(), J.ld())
745  # return J
746 
747  @property
748  def config_count(self):
749  """Returns the number of configuration variables in the sub-scenegraph."""
750  return libamino.aa_rx_sg_sub_config_count(self._ptr_ptr)
751 
752  def scatter_config(self, config_sub, vector_all=None):
753  """Copy elements of a sub-scenegraph config into the full config vector."""
754  if isinstance(config_sub, dict):
755  return self.scenegraphscenegraph.config_vector(config_sub, vector_all)
756 
757  if vector_all is None:
758  vector_all = DVec(self.scenegraphscenegraph.config_count)
759 
760  libamino.aa_rx_sg_sub_config_scatter(self._ptr_ptr, config_sub, vector_all)
761  return vector_all
762 
763  def gather_config(self, config_all, vector_sub=None):
764  """Copy elements of a full config into the sub config vector."""
765  # TODO: convert dictionary
766  if vector_sub is None:
767  vector_sub = DVec(self.config_countconfig_count)
768  libamino.aa_rx_sg_sub_config_gather(self._ptr_ptr, config_all, vector_sub)
769  return vector_sub
770 
771  @property
772  def end_effector_id(self):
773  """Returns the frame id of the end-effector."""
774  return libamino.aa_rx_sg_sub_frame_ees(self._ptr_ptr)[0]
775 
776  def config_vector(self, config, vector=None):
777  """Convert config to a vector."""
778  # TODO: convert dictionary
779  if vector is None:
780  return DVec.ensure(config)
781  else:
782  vector.copy_from(config)
783  return vector
784 
785  # @staticmethod
786  # def chain(scenegraph, root, tip):
787  # root = scenegraph.ensure_frame_id(root)
788  # tip = scenegraph.ensure_frame_id(tip)
789  # ptr = libamino.aa_rx_sg_chain_create(scenegraph._ptr, root, tip)
790  # return SubSceneGraph( scenegraph, ptr )
791 
792 
793 libamino.aa_rx_sg_sub_destroy.argtypes = [ctypes.POINTER(RxSgSub)]
794 
795 libamino.aa_rx_sg_sub_jacobian_size.argtypes = [
796  ctypes.POINTER(RxSgSub),
797  ctypes.POINTER(ctypes.c_size_t),
798  ctypes.POINTER(ctypes.c_size_t)
799 ]
800 
801 libamino.aa_rx_sg_sub_jacobian.argtypes = [
802  ctypes.POINTER(RxSgSub), ctypes.c_size_t,
803  ctypes.POINTER(ctypes.c_double), ctypes.c_size_t,
804  ctypes.POINTER(ctypes.c_double), ctypes.c_size_t
805 ]
806 
807 
808 libamino.aa_rx_sg_sub_config_count.argtypes = [ctypes.POINTER(RxSgSub)]
809 libamino.aa_rx_sg_sub_config_count.restype = ctypes.c_size_t
810 
811 libamino.aa_rx_sg_sub_config_scatter.argtypes = [
812  ctypes.POINTER(RxSgSub),
813  ctypes.POINTER(DVec),
814  ctypes.POINTER(DVec)
815 ]
816 
817 libamino.aa_rx_sg_sub_config_gather.argtypes = [
818  ctypes.POINTER(RxSgSub),
819  ctypes.POINTER(DVec),
820  ctypes.POINTER(DVec)
821 ]
822 
823 libamino.aa_rx_sg_chain_create.argtypes = [
824  ctypes.POINTER(RxSg), ctypes.c_int, ctypes.c_int
825 ]
826 libamino.aa_rx_sg_chain_create.restype = ctypes.POINTER(RxSgSub)
827 
828 libamino.aa_rx_sg_sub_frame_ees.argtypes = [ctypes.POINTER(RxSgSub)]
829 libamino.aa_rx_sg_sub_frame_ees.restype = ctypes.POINTER(ctypes.c_int)
830 
831 libamino.aa_rx_sg_sub_frame_ee.argtypes = [ctypes.POINTER(RxSgSub)]
832 libamino.aa_rx_sg_sub_frame_ee.restype = ctypes.c_int
Vector of double floats.
Definition: mat.py:49
def no_shadow(self)
Boolean indicating to not display a shadow.
Definition: scenegraph.py:116
def specular(self)
Three floats, between 0 and 1, for color in red-blue-green order.
Definition: scenegraph.py:138
def visual(self)
Boolean indicating whether to use for visual geometry.
Definition: scenegraph.py:106
def collision(self)
Boolean indicating whether to use for collision geometry.
Definition: scenegraph.py:111
def _get_val(self, func)
Definition: scenegraph.py:90
def color(self)
Three floats, between 0 and 1, for color in red-blue-green order.
Definition: scenegraph.py:131
def scale(self)
Float indicating how much to scale the geometry.
Definition: scenegraph.py:126
def _get_val3(self, func0, func1, func2)
Definition: scenegraph.py:93
def ensure(thing)
Ensures thing is a GeomOpt, converting dicts if necessary.
Definition: scenegraph.py:175
def alpha(self)
Float indicating alpha (transparency).
Definition: scenegraph.py:121
def _get_bool(self, func)
Definition: scenegraph.py:100
def __init__(self, options=None)
Constructs object with default and specified options.
Definition: scenegraph.py:81
A geometry object.
Definition: scenegraph.py:187
def box(opt, dimension)
Creates a box geometry object.
Definition: scenegraph.py:196
def cylinder(opt, height, radius)
Creates a cylinder geometry object.
Definition: scenegraph.py:208
def torus(opt, angle, major_radius, minor_radius)
Creates a torus geometry object.
Definition: scenegraph.py:221
def sphere(opt, radius)
Creates a sphere geometry object.
Definition: scenegraph.py:202
def grid(opt, dimension, delta, width)
Creates a grid geometry object.
Definition: scenegraph.py:229
def cone(opt, height, start_radius, end_radius)
Creates a cone geometry object.
Definition: scenegraph.py:214
Geometry options object.
Definition: scenegraph.py:67
Opaque type for geometry opts pointer.
Definition: scenegraph.py:64
Opaque type for geometry pointer.
Definition: scenegraph.py:61
def allow_collision(self, i, j, allowed=1)
Set allowed collisions between frames id0 and id1.
Definition: scenegraph.py:449
def init(self)
Initializes the scene, must be called after all frames are added.
Definition: scenegraph.py:444
def ensure_frame_id_actual(self, value)
Ensures value is a frame id, converting strings if necessary.
Definition: scenegraph.py:551
def add_frame_prismatic(self, parent, name, tf=QuatTrans.identity(), config_name=None, axis=(0, 0, 1), offset=0, geom=None, limits=None)
Adds a new prismatic frame to the scene.
Definition: scenegraph.py:386
def ensure_config_name(self, value)
Ensures value is a string config name, converting int ids if necessary.
Definition: scenegraph.py:514
def copy(self)
Create a copy of the scenegraph.
Definition: scenegraph.py:632
def add_frame_revolute(self, parent, name, tf=QuatTrans.identity(), config_name=None, axis=(0, 0, 1), offset=0, geom=None)
Adds a new revolute frame to the scene.
Definition: scenegraph.py:365
def frame_name(self, i)
Returns the frame name for the id.
Definition: scenegraph.py:485
def config_count(self)
Number of configuration variables in the scene.
Definition: scenegraph.py:457
def ensure_frame_id(self, value)
Ensures value is a frame id, converting strings if necessary.
Definition: scenegraph.py:531
def copy_config(self, config)
Copy configuration as a vector.
Definition: scenegraph.py:595
def load(self, filename, name, root="")
Loads a scene plugin into this scene.
Definition: scenegraph.py:435
def config_vector(self, config, vector=None)
Create or convert to a configuration vector.
Definition: scenegraph.py:578
def get_parent(self, frame)
Get the name of the parent of the input frame.
Definition: scenegraph.py:606
def frame_count(self)
Number of frames in the scene.
Definition: scenegraph.py:462
def attach_geom(self, name, geom)
Attaches geometry to the named frame.
Definition: scenegraph.py:406
def ensure_frame_name(self, value)
Ensures value is a string frame name, converting int ids if necessary.
Definition: scenegraph.py:563
def config_name(self, i)
Returns the config name for the id.
Definition: scenegraph.py:476
def remove_frame(self, name)
Removes a frame from the scene.
Definition: scenegraph.py:402
def frame_id(self, name)
Returns the frame id for string name.
Definition: scenegraph.py:471
def add_frame_fixed(self, parent, name, tf=QuatTrans.identity(), geom=None)
Adds a new fixed frame to the scene.
Definition: scenegraph.py:349
def config_id(self, name)
Returns the config id for string name.
Definition: scenegraph.py:466
def ensure_config_id(self, value)
Ensures value is a config id, converting strings if necessary.
Definition: scenegraph.py:498
def reparent(self, new_parent, frame, rel_tf=QuatTrans.identity())
Change the parent of frame in the scenegraph.
Definition: scenegraph.py:419
def config_dict(self, vector)
Convert vector to a dict.
Definition: scenegraph.py:599
def __getitem__(self, key)
Return a SubSceneGraph for the chain from root to tip.
Definition: scenegraph.py:619
A subset of a scene graph.
Definition: scenegraph.py:724
def end_effector_id(self)
Returns the frame id of the end-effector.
Definition: scenegraph.py:773
def gather_config(self, config_all, vector_sub=None)
Copy elements of a full config into the sub config vector.
Definition: scenegraph.py:764
def config_count(self)
Returns the number of configuration variables in the sub-scenegraph.
Definition: scenegraph.py:749
def scatter_config(self, config_sub, vector_all=None)
Copy elements of a sub-scenegraph config into the full config vector.
Definition: scenegraph.py:753
def config_vector(self, config, vector=None)
Convert config to a vector.
Definition: scenegraph.py:777
def __init__(self, scenegraph, _ptr)
Initialize from a scenegraph and sub-scenegraph pointer.
Definition: scenegraph.py:729
Definition: lib.py:1
Definition: mat.py:1
Definition: tf.py:1