amino  1.0-beta2
Lightweight Robot Utility Library
collision.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 """Collision checking"""
36 
37 import ctypes
38 from amino.tf import Vec3
39 from amino.scenegraph import RxSg
40 from amino.kinematics import SceneFK, RxFK
41 
42 
43 LIBAMINOCL = ctypes.CDLL("libamino-collision.so")
44 
45 
46 class RxClSet(ctypes.Structure):
47  """Opaque type for struct aa_rx_cl_set."""
48 
49 class SceneCollisionSet:
50  """Set of frame pairs indicating collision between frames."""
51 
52  __slots__ = ["_ptr", "scenegraph"]
53 
54  def __init__(self, scenegraph):
55  self.scenegraphscenegraph = scenegraph
56  self._ptr_ptr = LIBAMINOCL.aa_rx_cl_set_create(self.scenegraphscenegraph._ptr)
57 
58  def __del__(self):
59  LIBAMINOCL.aa_rx_cl_set_destroy(self._ptr_ptr)
60 
61  def __getitem__(self, key):
62  """Returns the value for the frame pair indicated by key.
63 
64  Args:
65  key: A tuple of two frame names or ids.
66 
67  Raises:
68  IndexError: Invalid frame name or ID.
69  """
70  i, j = key
71  i = self.scenegraphscenegraph.ensure_frame_id_actual(i)
72  j = self.scenegraphscenegraph.ensure_frame_id_actual(j)
73  v = LIBAMINOCL.aa_rx_cl_set_get(self._ptr_ptr, i, j)
74  return bool(v)
75 
76  def __setitem__(self, key, item):
77  """Sets the value for the frame pair indicated by key.
78 
79  Args:
80  key: A tuple of two frame names or ids.
81  item: True or False
82 
83  Raises:
84  IndexError: Invalid frame ID.
85  """
86  i, j = key
87  i = self.scenegraphscenegraph.ensure_frame_id_actual(i)
88  j = self.scenegraphscenegraph.ensure_frame_id_actual(j)
89  v = 1 if item else 0
90  LIBAMINOCL.aa_rx_cl_set_set(self._ptr_ptr, i, j, v)
91 
92  def clear(self):
93  """Sets all entries to False."""
94  LIBAMINOCL.aa_rx_cl_set_clear(self._ptr_ptr)
95 
96  def fill(self, src):
97  """Fills self with all true entries in other."""
98  LIBAMINOCL.aa_rx_cl_set_fill(self._ptr_ptr, src._ptr)
99 
100 
101 LIBAMINOCL.aa_rx_cl_set_create.argtypes = [ctypes.POINTER(RxSg)]
102 LIBAMINOCL.aa_rx_cl_set_create.restype = ctypes.POINTER(RxClSet)
103 
104 LIBAMINOCL.aa_rx_cl_set_destroy.argtypes = [ctypes.POINTER(RxClSet)]
105 
106 LIBAMINOCL.aa_rx_cl_set_get.argtypes = [
107  ctypes.POINTER(RxClSet), ctypes.c_int, ctypes.c_int
108 ]
109 LIBAMINOCL.aa_rx_cl_set_get.restypes = ctypes.c_int
110 
111 LIBAMINOCL.aa_rx_cl_set_set.argtypes = [
112  ctypes.POINTER(RxClSet), ctypes.c_int, ctypes.c_int, ctypes.c_int
113 ]
114 
115 LIBAMINOCL.aa_rx_cl_set_clear.argtypes = [ctypes.POINTER(RxClSet)]
116 
117 LIBAMINOCL.aa_rx_cl_set_fill.argtypes = [
118  ctypes.POINTER(RxClSet), ctypes.POINTER(RxClSet)
119 ]
120 
121 
122 class RxCl(ctypes.Structure):
123  """Opaque type for struct aa_rx_cl."""
124 
125 class SceneCollision:
126  """Context object for collision detection."""
127 
128  __slots__ = ["_ptr", "scenegraph"]
129 
130  def __init__(self, scenegraph):
131  self.scenegraphscenegraph = scenegraph
132  LIBAMINOCL.aa_rx_sg_cl_init(self.scenegraphscenegraph._ptr)
133  self._ptr_ptr = LIBAMINOCL.aa_rx_cl_create(self.scenegraphscenegraph._ptr)
134 
135  def __del__(self):
136  LIBAMINOCL.aa_rx_cl_destroy(self._ptr_ptr)
137 
138  def allow(self, i, j):
139  """Allows collisions between frames i and j."""
140  i = self.scenegraphscenegraph.ensure_frame_id_actual(i)
141  j = self.scenegraphscenegraph.ensure_frame_id_actual(j)
142  LIBAMINOCL.aa_rx_cl_allow(self._ptr_ptr, i, j, 1)
143 
144  def allow_set(self, collision_set):
145  """Allows collisions between all frames in the collision set."""
146  LIBAMINOCL.aa_rx_cl_allow_set(self._ptr_ptr, collision_set._ptr)
147 
148  def allow_config(self, config):
149  """Allows collisions between all frames coliding at config."""
150  fk = SceneFK(self.scenegraphscenegraph)
151  fk.config = config
152  cl_set = SceneCollisionSet(self.scenegraphscenegraph)
153  self.checkcheck(fk, cl_set)
154  self.allow_setallow_set(cl_set)
155 
156  def check(self, scene_fk, collision_set=None):
157  """Checks for collisions and optionally outputs colliding frames.
158 
159  Args:
160  fk: A SceneFK updated with the configuration to check.
161  collision_set: If not None, a SceneCollisionSet that will
162  be filled with all detected, non-allowed collisions.
163 
164  Returns:
165  True if collisions are detected and False otherwise.
166 
167  """
168  cl_set_ptr = None
169  if collision_set:
170  collision_set.clear()
171  cl_set_ptr = collision_set._ptr
172  r = LIBAMINOCL.aa_rx_cl_check(self._ptr_ptr, len(scene_fk),
173  scene_fk._data_ptr(),
174  scene_fk._data_ld(), cl_set_ptr)
175  return bool(r)
176 
177  def collision_set(self):
178  """Creates a SceneCollisionSet."""
179  return SceneCollisionSet(self.scenegraphscenegraph)
180 
181  def collision_dist(self):
182  """Creates a SceneCollisionDist."""
183  return SceneCollisionDist(self)
184 
185 
186 LIBAMINOCL.aa_rx_sg_cl_init.argtypes = [ctypes.POINTER(RxSg)]
187 
188 
189 LIBAMINOCL.aa_rx_cl_create.argtypes = [ctypes.POINTER(RxSg)]
190 LIBAMINOCL.aa_rx_cl_create.restype = ctypes.POINTER(RxCl)
191 
192 LIBAMINOCL.aa_rx_cl_destroy.argtypes = [ctypes.POINTER(RxCl)]
193 
194 LIBAMINOCL.aa_rx_cl_allow.argtypes = [
195  ctypes.POINTER(RxCl), ctypes.c_int, ctypes.c_int, ctypes.c_int
196 ]
197 
198 LIBAMINOCL.aa_rx_cl_allow_set.argtypes = [
199  ctypes.POINTER(RxCl), ctypes.POINTER(RxClSet)
200 ]
201 
202 LIBAMINOCL.aa_rx_cl_check.argtypes = [
203  ctypes.POINTER(RxCl), ctypes.c_size_t,
204  ctypes.POINTER(ctypes.c_double), ctypes.c_size_t,
205  ctypes.POINTER(RxClSet)
206 ]
207 LIBAMINOCL.aa_rx_cl_check.restypes = ctypes.c_int
208 
209 
210 class RxClDist(ctypes.Structure):
211  """Opaque type for struct aa_rx_cl_dist."""
212 
213 
214 LIBAMINOCL.aa_rx_cl_dist_create.argtypes = [ctypes.POINTER(RxCl)]
215 LIBAMINOCL.aa_rx_cl_dist_create.restype = ctypes.POINTER(RxClDist)
216 
217 LIBAMINOCL.aa_rx_cl_dist_destroy.argtypes = [ctypes.POINTER(RxClDist)]
218 
219 LIBAMINOCL.aa_rx_cl_dist_check.argtypes = [
220  ctypes.POINTER(RxClDist), ctypes.POINTER(RxFK)
221 ]
222 LIBAMINOCL.aa_rx_cl_dist_check.restype = ctypes.c_int
223 
224 LIBAMINOCL.aa_rx_cl_dist_get_dist.argtypes = [
225  ctypes.POINTER(RxClDist), ctypes.c_int, ctypes.c_int
226 ]
227 LIBAMINOCL.aa_rx_cl_dist_get_dist.restype = ctypes.c_double
228 
229 LIBAMINOCL.aa_rx_cl_dist_get_points.argtypes = [
230  ctypes.POINTER(RxClDist), ctypes.c_int, ctypes.c_int,
231  ctypes.POINTER(Vec3),
232  ctypes.POINTER(Vec3)
233 ]
234 LIBAMINOCL.aa_rx_cl_dist_get_points.restype = ctypes.c_double
235 
236 
237 class SceneCollisionDist:
238  """Context object for separation distances."""
239 
240  class DistDesc():
241  """Descriptor for distance access."""
242  __slots__ = ["_cl_dist"]
243 
244  def __init__(self, cl_dist):
245  self._cl_dist_cl_dist = cl_dist
246 
247  def __getitem__(self, key):
248  """Returns the separation distance for the frames.
249 
250  Args:
251  key: a pair of frame names or ids
252  """
253  (i, j) = key
254  i = self._cl_dist_cl_dist._cl.scenegraph.ensure_frame_id_actual(i)
255  j = self._cl_dist_cl_dist._cl.scenegraph.ensure_frame_id_actual(j)
256  return LIBAMINOCL.aa_rx_cl_dist_get_dist(self._cl_dist_cl_dist._ptr, i, j)
257 
258  class PointsDesc():
259  """Descriptor for point access."""
260  __slots__ = ["_cl_dist"]
261 
262  def __init__(self, cl_dist):
263  self._cl_dist_cl_dist = cl_dist
264 
265  def __getitem__(self, key):
266  """Returns a tuple (distance, point0, point1) for the frames.
267 
268  Args:
269  key: a pair of frame names or ids
270  """
271  (i, j) = key
272  i = self._cl_dist_cl_dist._cl.scenegraph.ensure_frame_id_actual(i)
273  j = self._cl_dist_cl_dist._cl.scenegraph.ensure_frame_id_actual(j)
274  p_i = Vec3()
275  p_j = Vec3()
276  dist = LIBAMINOCL.aa_rx_cl_dist_get_points(self._cl_dist_cl_dist._ptr, i,
277  j, p_i, p_j)
278  return (dist, p_i, p_j)
279 
280  __slots__ = ["_ptr", "_cl", "_dist", "_points"]
281 
282  def __init__(self, cl):
283  self._cl = cl
284  self._ptr = LIBAMINOCL.aa_rx_cl_dist_create(cl._ptr)
285  self._dist = self.DistDesc(self)
286  self._points = self.PointsDesc(self)
287 
288  def __del__(self):
289  LIBAMINOCL.aa_rx_cl_dist_destroy(self._ptr)
290 
291  def check(self, scene_fk):
292  """Checks for collision distances from the given forward kinematics."""
293  LIBAMINOCL.aa_rx_cl_dist_check(self._ptr_ptr, scene_fk._ptr)
294 
295  @property
296  def dist(self):
297  """The DistDesc descriptor."""
298  return self._dist_dist
299 
300  @property
301  def points(self):
302  """The PointsDesc descriptor."""
303  return self._points_points
304 
305 LIBAMINOCL.aa_rx_sg_cl_init.argtypes = [ctypes.POINTER(RxSg)]
Opaque type for struct aa_rx_cl_dist.
Definition: collision.py:211
Opaque type for struct aa_rx_cl.
Definition: collision.py:123
Descriptor for distance access.
Definition: collision.py:241
def __getitem__(self, key)
Returns the separation distance for the frames.
Definition: collision.py:252
def __getitem__(self, key)
Returns a tuple (distance, point0, point1) for the frames.
Definition: collision.py:270
Context object for separation distances.
Definition: collision.py:238
def check(self, scene_fk)
Checks for collision distances from the given forward kinematics.
Definition: collision.py:292
def dist(self)
The DistDesc descriptor.
Definition: collision.py:297
def points(self)
The PointsDesc descriptor.
Definition: collision.py:302
def __getitem__(self, key)
Returns the value for the frame pair indicated by key.
Definition: collision.py:69
def clear(self)
Sets all entries to False.
Definition: collision.py:93
def __setitem__(self, key, item)
Sets the value for the frame pair indicated by key.
Definition: collision.py:85
def fill(self, src)
Fills self with all true entries in other.
Definition: collision.py:97
def allow_config(self, config)
Allows collisions between all frames coliding at config.
Definition: collision.py:149
def collision_dist(self)
Creates a SceneCollisionDist.
Definition: collision.py:182
def check(self, scene_fk, collision_set=None)
Checks for collisions and optionally outputs colliding frames.
Definition: collision.py:167
def collision_set(self)
Creates a SceneCollisionSet.
Definition: collision.py:178
def allow_set(self, collision_set)
Allows collisions between all frames in the collision set.
Definition: collision.py:145
def allow(self, i, j)
Allows collisions between frames i and j.
Definition: collision.py:139
Length-3 vectors.
Definition: tf.py:45
Definition: tf.py:1