FCL  0.6.0
Flexible Collision Library
broadphase_dynamic_AABB_tree_array-inl.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011-2014, Willow Garage, Inc.
5  * Copyright (c) 2014-2016, Open Source Robotics Foundation
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
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  * * Neither the name of Open Source Robotics Foundation nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
38 #ifndef FCL_BROAD_PHASE_DYNAMIC_AABB_TREE_ARRAY_INL_H
39 #define FCL_BROAD_PHASE_DYNAMIC_AABB_TREE_ARRAY_INL_H
40 
41 #include "fcl/broadphase/broadphase_dynamic_AABB_tree_array.h"
42 
43 #if FCL_HAVE_OCTOMAP
44 #include "fcl/geometry/octree/octree.h"
45 #endif
46 
47 namespace fcl
48 {
49 
50 //==============================================================================
51 extern template
52 class DynamicAABBTreeCollisionManager_Array<double>;
53 
54 namespace detail
55 {
56 
57 namespace dynamic_AABB_tree_array
58 {
59 
60 #if FCL_HAVE_OCTOMAP
61 
62 //==============================================================================
63 template <typename S>
64 bool collisionRecurse_(
65  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes1,
66  size_t root1_id,
67  const OcTree<S>* tree2,
68  const typename OcTree<S>::OcTreeNode* root2,
69  const AABB<S>& root2_bv,
70  const Transform3<S>& tf2,
71  void* cdata,
72  CollisionCallBack<S> callback)
73 {
74  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root1 = nodes1 + root1_id;
75  if(!root2)
76  {
77  if(root1->isLeaf())
78  {
79  CollisionObject<S>* obj1 = static_cast<CollisionObject<S>*>(root1->data);
80 
81  if(!obj1->isFree())
82  {
83  OBB<S> obb1, obb2;
84  convertBV(root1->bv, Transform3<S>::Identity(), obb1);
85  convertBV(root2_bv, tf2, obb2);
86 
87  if(obb1.overlap(obb2))
88  {
89  Box<S>* box = new Box<S>();
90  Transform3<S> box_tf;
91  constructBox(root2_bv, tf2, *box, box_tf);
92 
93  box->cost_density = tree2->getDefaultOccupancy();
94 
95  CollisionObject<S> obj2(std::shared_ptr<CollisionGeometry<S>>(box), box_tf);
96  return callback(obj1, &obj2, cdata);
97  }
98  }
99  }
100  else
101  {
102  if(collisionRecurse_<S>(nodes1, root1->children[0], tree2, nullptr, root2_bv, tf2, cdata, callback))
103  return true;
104  if(collisionRecurse_<S>(nodes1, root1->children[1], tree2, nullptr, root2_bv, tf2, cdata, callback))
105  return true;
106  }
107 
108  return false;
109  }
110  else if(root1->isLeaf() && !tree2->nodeHasChildren(root2))
111  {
112  CollisionObject<S>* obj1 = static_cast<CollisionObject<S>*>(root1->data);
113  if(!tree2->isNodeFree(root2) && !obj1->isFree())
114  {
115  OBB<S> obb1, obb2;
116  convertBV(root1->bv, Transform3<S>::Identity(), obb1);
117  convertBV(root2_bv, tf2, obb2);
118 
119  if(obb1.overlap(obb2))
120  {
121  Box<S>* box = new Box<S>();
122  Transform3<S> box_tf;
123  constructBox(root2_bv, tf2, *box, box_tf);
124 
125  box->cost_density = root2->getOccupancy();
126  box->threshold_occupied = tree2->getOccupancyThres();
127 
128  CollisionObject<S> obj2(std::shared_ptr<CollisionGeometry<S>>(box), box_tf);
129  return callback(obj1, &obj2, cdata);
130  }
131  else return false;
132  }
133  else return false;
134  }
135 
136  OBB<S> obb1, obb2;
137  convertBV(root1->bv, Transform3<S>::Identity(), obb1);
138  convertBV(root2_bv, tf2, obb2);
139 
140  if(tree2->isNodeFree(root2) || !obb1.overlap(obb2)) return false;
141 
142  if(!tree2->nodeHasChildren(root2) || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size())))
143  {
144  if(collisionRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, tf2, cdata, callback))
145  return true;
146  if(collisionRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, tf2, cdata, callback))
147  return true;
148  }
149  else
150  {
151  for(unsigned int i = 0; i < 8; ++i)
152  {
153  if(tree2->nodeChildExists(root2, i))
154  {
155  const typename OcTree<S>::OcTreeNode* child = tree2->getNodeChild(root2, i);
156  AABB<S> child_bv;
157  computeChildBV(root2_bv, i, child_bv);
158 
159  if(collisionRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback))
160  return true;
161  }
162  else
163  {
164  AABB<S> child_bv;
165  computeChildBV(root2_bv, i, child_bv);
166  if(collisionRecurse_<S>(nodes1, root1_id, tree2, nullptr, child_bv, tf2, cdata, callback))
167  return true;
168  }
169  }
170  }
171 
172  return false;
173 }
174 
175 //==============================================================================
176 template <typename S, typename Derived>
177 bool collisionRecurse_(
178  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes1,
179  size_t root1_id,
180  const OcTree<S>* tree2,
181  const typename OcTree<S>::OcTreeNode* root2,
182  const AABB<S>& root2_bv,
183  const Eigen::MatrixBase<Derived>& translation2,
184  void* cdata,
185  CollisionCallBack<S> callback)
186 {
187  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root1 = nodes1 + root1_id;
188  if(!root2)
189  {
190  if(root1->isLeaf())
191  {
192  CollisionObject<S>* obj1 = static_cast<CollisionObject<S>*>(root1->data);
193 
194  if(!obj1->isFree())
195  {
196  const AABB<S>& root_bv_t = translate(root2_bv, translation2);
197  if(root1->bv.overlap(root_bv_t))
198  {
199  Box<S>* box = new Box<S>();
200  Transform3<S> box_tf;
201  Transform3<S> tf2 = Transform3<S>::Identity();
202  tf2.translation() = translation2;
203  constructBox(root2_bv, tf2, *box, box_tf);
204 
205  box->cost_density = tree2->getDefaultOccupancy();
206 
207  CollisionObject<S> obj2(std::shared_ptr<CollisionGeometry<S>>(box), box_tf);
208  return callback(obj1, &obj2, cdata);
209  }
210  }
211  }
212  else
213  {
214  if(collisionRecurse_<S>(nodes1, root1->children[0], tree2, nullptr, root2_bv, translation2, cdata, callback))
215  return true;
216  if(collisionRecurse_<S>(nodes1, root1->children[1], tree2, nullptr, root2_bv, translation2, cdata, callback))
217  return true;
218  }
219 
220  return false;
221  }
222  else if(root1->isLeaf() && !tree2->nodeHasChildren(root2))
223  {
224  CollisionObject<S>* obj1 = static_cast<CollisionObject<S>*>(root1->data);
225  if(!tree2->isNodeFree(root2) && !obj1->isFree())
226  {
227  const AABB<S>& root_bv_t = translate(root2_bv, translation2);
228  if(root1->bv.overlap(root_bv_t))
229  {
230  Box<S>* box = new Box<S>();
231  Transform3<S> box_tf;
232  Transform3<S> tf2 = Transform3<S>::Identity();
233  tf2.translation() = translation2;
234  constructBox(root2_bv, tf2, *box, box_tf);
235 
236  box->cost_density = root2->getOccupancy();
237  box->threshold_occupied = tree2->getOccupancyThres();
238 
239  CollisionObject<S> obj2(std::shared_ptr<CollisionGeometry<S>>(box), box_tf);
240  return callback(obj1, &obj2, cdata);
241  }
242  else return false;
243  }
244  else return false;
245  }
246 
247  const AABB<S>& root_bv_t = translate(root2_bv, translation2);
248  if(tree2->isNodeFree(root2) || !root1->bv.overlap(root_bv_t)) return false;
249 
250  if(!tree2->nodeHasChildren(root2) || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size())))
251  {
252  if(collisionRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, translation2, cdata, callback))
253  return true;
254  if(collisionRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, translation2, cdata, callback))
255  return true;
256  }
257  else
258  {
259  for(unsigned int i = 0; i < 8; ++i)
260  {
261  if(tree2->nodeChildExists(root2, i))
262  {
263  const typename OcTree<S>::OcTreeNode* child = tree2->getNodeChild(root2, i);
264  AABB<S> child_bv;
265  computeChildBV(root2_bv, i, child_bv);
266 
267  if(collisionRecurse_(nodes1, root1_id, tree2, child, child_bv, translation2, cdata, callback))
268  return true;
269  }
270  else
271  {
272  AABB<S> child_bv;
273  computeChildBV(root2_bv, i, child_bv);
274  if(collisionRecurse_<S>(nodes1, root1_id, tree2, nullptr, child_bv, translation2, cdata, callback))
275  return true;
276  }
277  }
278  }
279 
280  return false;
281 }
282 
283 //==============================================================================
284 template <typename S>
285 bool distanceRecurse_(typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes1, size_t root1_id, const OcTree<S>* tree2, const typename OcTree<S>::OcTreeNode* root2, const AABB<S>& root2_bv, const Transform3<S>& tf2, void* cdata, DistanceCallBack<S> callback, S& min_dist)
286 {
287  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root1 = nodes1 + root1_id;
288  if(root1->isLeaf() && !tree2->nodeHasChildren(root2))
289  {
290  if(tree2->isNodeOccupied(root2))
291  {
292  Box<S>* box = new Box<S>();
293  Transform3<S> box_tf;
294  constructBox(root2_bv, tf2, *box, box_tf);
295  CollisionObject<S> obj(std::shared_ptr<CollisionGeometry<S>>(box), box_tf);
296  return callback(static_cast<CollisionObject<S>*>(root1->data), &obj, cdata, min_dist);
297  }
298  else return false;
299  }
300 
301  if(!tree2->isNodeOccupied(root2)) return false;
302 
303  if(!tree2->nodeHasChildren(root2) || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size())))
304  {
305  AABB<S> aabb2;
306  convertBV(root2_bv, tf2, aabb2);
307 
308  S d1 = aabb2.distance((nodes1 + root1->children[0])->bv);
309  S d2 = aabb2.distance((nodes1 + root1->children[1])->bv);
310 
311  if(d2 < d1)
312  {
313  if(d2 < min_dist)
314  {
315  if(distanceRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
316  return true;
317  }
318 
319  if(d1 < min_dist)
320  {
321  if(distanceRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
322  return true;
323  }
324  }
325  else
326  {
327  if(d1 < min_dist)
328  {
329  if(distanceRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
330  return true;
331  }
332 
333  if(d2 < min_dist)
334  {
335  if(distanceRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
336  return true;
337  }
338  }
339  }
340  else
341  {
342  for(unsigned int i = 0; i < 8; ++i)
343  {
344  if(tree2->nodeChildExists(root2, i))
345  {
346  const typename OcTree<S>::OcTreeNode* child = tree2->getNodeChild(root2, i);
347  AABB<S> child_bv;
348  computeChildBV(root2_bv, i, child_bv);
349 
350  AABB<S> aabb2;
351  convertBV(child_bv, tf2, aabb2);
352  S d = root1->bv.distance(aabb2);
353 
354  if(d < min_dist)
355  {
356  if(distanceRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback, min_dist))
357  return true;
358  }
359  }
360  }
361  }
362 
363  return false;
364 }
365 
366 //==============================================================================
367 template <typename S, typename Derived>
368 bool distanceRecurse_(
369  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes1,
370  size_t root1_id,
371  const OcTree<S>* tree2,
372  const typename OcTree<S>::OcTreeNode* root2,
373  const AABB<S>& root2_bv,
374  const Eigen::MatrixBase<Derived>& translation2,
375  void* cdata,
376  DistanceCallBack<S> callback,
377  S& min_dist)
378 {
379  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root1 = nodes1 + root1_id;
380  if(root1->isLeaf() && !tree2->nodeHasChildren(root2))
381  {
382  if(tree2->isNodeOccupied(root2))
383  {
384  Box<S>* box = new Box<S>();
385  Transform3<S> box_tf;
386  Transform3<S> tf2 = Transform3<S>::Identity();
387  tf2.translation() = translation2;
388  constructBox(root2_bv, tf2, *box, box_tf);
389  CollisionObject<S> obj(std::shared_ptr<CollisionGeometry<S>>(box), box_tf);
390  return callback(static_cast<CollisionObject<S>*>(root1->data), &obj, cdata, min_dist);
391  }
392  else return false;
393  }
394 
395  if(!tree2->isNodeOccupied(root2)) return false;
396 
397  if(!tree2->nodeHasChildren(root2) || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size())))
398  {
399  const AABB<S>& aabb2 = translate(root2_bv, translation2);
400 
401  S d1 = aabb2.distance((nodes1 + root1->children[0])->bv);
402  S d2 = aabb2.distance((nodes1 + root1->children[1])->bv);
403 
404  if(d2 < d1)
405  {
406  if(d2 < min_dist)
407  {
408  if(distanceRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, translation2, cdata, callback, min_dist))
409  return true;
410  }
411 
412  if(d1 < min_dist)
413  {
414  if(distanceRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, translation2, cdata, callback, min_dist))
415  return true;
416  }
417  }
418  else
419  {
420  if(d1 < min_dist)
421  {
422  if(distanceRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, translation2, cdata, callback, min_dist))
423  return true;
424  }
425 
426  if(d2 < min_dist)
427  {
428  if(distanceRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, translation2, cdata, callback, min_dist))
429  return true;
430  }
431  }
432  }
433  else
434  {
435  for(unsigned int i = 0; i < 8; ++i)
436  {
437  if(tree2->nodeChildExists(root2, i))
438  {
439  const typename OcTree<S>::OcTreeNode* child = tree2->getNodeChild(root2, i);
440  AABB<S> child_bv;
441  computeChildBV(root2_bv, i, child_bv);
442 
443  const AABB<S>& aabb2 = translate(child_bv, translation2);
444  S d = root1->bv.distance(aabb2);
445 
446  if(d < min_dist)
447  {
448  if(distanceRecurse_(nodes1, root1_id, tree2, child, child_bv, translation2, cdata, callback, min_dist))
449  return true;
450  }
451  }
452  }
453  }
454 
455  return false;
456 }
457 
458 
459 #endif
460 
461 //==============================================================================
462 template <typename S>
463 bool collisionRecurse(typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes1, size_t root1_id,
464  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes2, size_t root2_id,
465  void* cdata, CollisionCallBack<S> callback)
466 {
467  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root1 = nodes1 + root1_id;
468  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root2 = nodes2 + root2_id;
469  if(root1->isLeaf() && root2->isLeaf())
470  {
471  if(!root1->bv.overlap(root2->bv)) return false;
472  return callback(static_cast<CollisionObject<S>*>(root1->data), static_cast<CollisionObject<S>*>(root2->data), cdata);
473  }
474 
475  if(!root1->bv.overlap(root2->bv)) return false;
476 
477  if(root2->isLeaf() || (!root1->isLeaf() && (root1->bv.size() > root2->bv.size())))
478  {
479  if(collisionRecurse(nodes1, root1->children[0], nodes2, root2_id, cdata, callback))
480  return true;
481  if(collisionRecurse(nodes1, root1->children[1], nodes2, root2_id, cdata, callback))
482  return true;
483  }
484  else
485  {
486  if(collisionRecurse(nodes1, root1_id, nodes2, root2->children[0], cdata, callback))
487  return true;
488  if(collisionRecurse(nodes1, root1_id, nodes2, root2->children[1], cdata, callback))
489  return true;
490  }
491  return false;
492 }
493 
494 //==============================================================================
495 template <typename S>
496 bool collisionRecurse(typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes, size_t root_id, CollisionObject<S>* query, void* cdata, CollisionCallBack<S> callback)
497 {
498  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root = nodes + root_id;
499  if(root->isLeaf())
500  {
501  if(!root->bv.overlap(query->getAABB())) return false;
502  return callback(static_cast<CollisionObject<S>*>(root->data), query, cdata);
503  }
504 
505  if(!root->bv.overlap(query->getAABB())) return false;
506 
507  int select_res = implementation_array::select(query->getAABB(), root->children[0], root->children[1], nodes);
508 
509  if(collisionRecurse(nodes, root->children[select_res], query, cdata, callback))
510  return true;
511 
512  if(collisionRecurse(nodes, root->children[1-select_res], query, cdata, callback))
513  return true;
514 
515  return false;
516 }
517 
518 //==============================================================================
519 template <typename S>
520 bool selfCollisionRecurse(typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes, size_t root_id, void* cdata, CollisionCallBack<S> callback)
521 {
522  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root = nodes + root_id;
523  if(root->isLeaf()) return false;
524 
525  if(selfCollisionRecurse(nodes, root->children[0], cdata, callback))
526  return true;
527 
528  if(selfCollisionRecurse(nodes, root->children[1], cdata, callback))
529  return true;
530 
531  if(collisionRecurse(nodes, root->children[0], nodes, root->children[1], cdata, callback))
532  return true;
533 
534  return false;
535 }
536 
537 //==============================================================================
538 template <typename S>
539 bool distanceRecurse(typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes1, size_t root1_id,
540  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes2, size_t root2_id,
541  void* cdata, DistanceCallBack<S> callback, S& min_dist)
542 {
543  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root1 = nodes1 + root1_id;
544  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root2 = nodes2 + root2_id;
545  if(root1->isLeaf() && root2->isLeaf())
546  {
547  CollisionObject<S>* root1_obj = static_cast<CollisionObject<S>*>(root1->data);
548  CollisionObject<S>* root2_obj = static_cast<CollisionObject<S>*>(root2->data);
549  return callback(root1_obj, root2_obj, cdata, min_dist);
550  }
551 
552  if(root2->isLeaf() || (!root1->isLeaf() && (root1->bv.size() > root2->bv.size())))
553  {
554  S d1 = root2->bv.distance((nodes1 + root1->children[0])->bv);
555  S d2 = root2->bv.distance((nodes1 + root1->children[1])->bv);
556 
557  if(d2 < d1)
558  {
559  if(d2 < min_dist)
560  {
561  if(distanceRecurse(nodes1, root1->children[1], nodes2, root2_id, cdata, callback, min_dist))
562  return true;
563  }
564 
565  if(d1 < min_dist)
566  {
567  if(distanceRecurse(nodes1, root1->children[0], nodes2, root2_id, cdata, callback, min_dist))
568  return true;
569  }
570  }
571  else
572  {
573  if(d1 < min_dist)
574  {
575  if(distanceRecurse(nodes1, root1->children[0], nodes2, root2_id, cdata, callback, min_dist))
576  return true;
577  }
578 
579  if(d2 < min_dist)
580  {
581  if(distanceRecurse(nodes1, root1->children[1], nodes2, root2_id, cdata, callback, min_dist))
582  return true;
583  }
584  }
585  }
586  else
587  {
588  S d1 = root1->bv.distance((nodes2 + root2->children[0])->bv);
589  S d2 = root1->bv.distance((nodes2 + root2->children[1])->bv);
590 
591  if(d2 < d1)
592  {
593  if(d2 < min_dist)
594  {
595  if(distanceRecurse(nodes1, root1_id, nodes2, root2->children[1], cdata, callback, min_dist))
596  return true;
597  }
598 
599  if(d1 < min_dist)
600  {
601  if(distanceRecurse(nodes1, root1_id, nodes2, root2->children[0], cdata, callback, min_dist))
602  return true;
603  }
604  }
605  else
606  {
607  if(d1 < min_dist)
608  {
609  if(distanceRecurse(nodes1, root1_id, nodes2, root2->children[0], cdata, callback, min_dist))
610  return true;
611  }
612 
613  if(d2 < min_dist)
614  {
615  if(distanceRecurse(nodes1, root1_id, nodes2, root2->children[1], cdata, callback, min_dist))
616  return true;
617  }
618  }
619  }
620 
621  return false;
622 }
623 
624 //==============================================================================
625 template <typename S>
626 bool distanceRecurse(typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes, size_t root_id, CollisionObject<S>* query, void* cdata, DistanceCallBack<S> callback, S& min_dist)
627 {
628  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root = nodes + root_id;
629  if(root->isLeaf())
630  {
631  CollisionObject<S>* root_obj = static_cast<CollisionObject<S>*>(root->data);
632  return callback(root_obj, query, cdata, min_dist);
633  }
634 
635  S d1 = query->getAABB().distance((nodes + root->children[0])->bv);
636  S d2 = query->getAABB().distance((nodes + root->children[1])->bv);
637 
638  if(d2 < d1)
639  {
640  if(d2 < min_dist)
641  {
642  if(distanceRecurse(nodes, root->children[1], query, cdata, callback, min_dist))
643  return true;
644  }
645 
646  if(d1 < min_dist)
647  {
648  if(distanceRecurse(nodes, root->children[0], query, cdata, callback, min_dist))
649  return true;
650  }
651  }
652  else
653  {
654  if(d1 < min_dist)
655  {
656  if(distanceRecurse(nodes, root->children[0], query, cdata, callback, min_dist))
657  return true;
658  }
659 
660  if(d2 < min_dist)
661  {
662  if(distanceRecurse(nodes, root->children[1], query, cdata, callback, min_dist))
663  return true;
664  }
665  }
666 
667  return false;
668 }
669 
670 //==============================================================================
671 template <typename S>
672 bool selfDistanceRecurse(typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes, size_t root_id, void* cdata, DistanceCallBack<S> callback, S& min_dist)
673 {
674  typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* root = nodes + root_id;
675  if(root->isLeaf()) return false;
676 
677  if(selfDistanceRecurse(nodes, root->children[0], cdata, callback, min_dist))
678  return true;
679 
680  if(selfDistanceRecurse(nodes, root->children[1], cdata, callback, min_dist))
681  return true;
682 
683  if(distanceRecurse(nodes, root->children[0], nodes, root->children[1], cdata, callback, min_dist))
684  return true;
685 
686  return false;
687 }
688 
689 
690 #if FCL_HAVE_OCTOMAP
691 
692 //==============================================================================
693 template <typename S>
694 bool collisionRecurse(typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes1, size_t root1_id, const OcTree<S>* tree2, const typename OcTree<S>::OcTreeNode* root2, const AABB<S>& root2_bv, const Transform3<S>& tf2, void* cdata, CollisionCallBack<S> callback)
695 {
696  if(tf2.linear().isIdentity())
697  return collisionRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2.translation(), cdata, callback);
698  else
699  return collisionRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2, cdata, callback);
700 }
701 
702 //==============================================================================
703 template <typename S>
704 bool distanceRecurse(typename DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBNode* nodes1, size_t root1_id, const OcTree<S>* tree2, const typename OcTree<S>::OcTreeNode* root2, const AABB<S>& root2_bv, const Transform3<S>& tf2, void* cdata, DistanceCallBack<S> callback, S& min_dist)
705 {
706  if(tf2.linear().isIdentity())
707  return distanceRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2.translation(), cdata, callback, min_dist);
708  else
709  return distanceRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2, cdata, callback, min_dist);
710 }
711 
712 #endif
713 
714 } // namespace dynamic_AABB_tree_array
715 
716 } // namespace detail
717 
718 //==============================================================================
719 template <typename S>
720 DynamicAABBTreeCollisionManager_Array<S>::DynamicAABBTreeCollisionManager_Array()
721  : tree_topdown_balance_threshold(dtree.bu_threshold),
722  tree_topdown_level(dtree.topdown_level)
723 {
724  max_tree_nonbalanced_level = 10;
725  tree_incremental_balance_pass = 10;
726  tree_topdown_balance_threshold = 2;
727  tree_topdown_level = 0;
728  tree_init_level = 0;
729  setup_ = false;
730 
731  // from experiment, this is the optimal setting
732  octree_as_geometry_collide = true;
733  octree_as_geometry_distance = false;
734 }
735 
736 //==============================================================================
737 template <typename S>
739  const std::vector<CollisionObject<S>*>& other_objs)
740 {
741  if(other_objs.empty()) return;
742 
743  if(size() > 0)
744  {
746  }
747  else
748  {
749  DynamicAABBNode* leaves = new DynamicAABBNode[other_objs.size()];
750  table.rehash(other_objs.size());
751  for(size_t i = 0, size = other_objs.size(); i < size; ++i)
752  {
753  leaves[i].bv = other_objs[i]->getAABB();
754  leaves[i].parent = dtree.NULL_NODE;
755  leaves[i].children[1] = dtree.NULL_NODE;
756  leaves[i].data = other_objs[i];
757  table[other_objs[i]] = i;
758  }
759 
760  int n_leaves = other_objs.size();
761 
762  dtree.init(leaves, n_leaves, tree_init_level);
763 
764  setup_ = true;
765  }
766 }
767 
768 //==============================================================================
769 template <typename S>
771 {
772  size_t node = dtree.insert(obj->getAABB(), obj);
773  table[obj] = node;
774 }
775 
776 //==============================================================================
777 template <typename S>
779 {
780  size_t node = table[obj];
781  table.erase(obj);
782  dtree.remove(node);
783 }
784 
785 //==============================================================================
786 template <typename S>
788 {
789  if(!setup_)
790  {
791  int num = dtree.size();
792  if(num == 0)
793  {
794  setup_ = true;
795  return;
796  }
797 
798  int height = dtree.getMaxHeight();
799 
800 
801  if(height - std::log((S)num) / std::log(2.0) < max_tree_nonbalanced_level)
802  dtree.balanceIncremental(tree_incremental_balance_pass);
803  else
804  dtree.balanceTopdown();
805 
806  setup_ = true;
807  }
808 }
809 
810 //==============================================================================
811 template <typename S>
813 {
814  for(auto it = table.cbegin(), end = table.cend(); it != end; ++it)
815  {
816  const CollisionObject<S>* obj = it->first;
817  size_t node = it->second;
818  dtree.getNodes()[node].bv = obj->getAABB();
819  }
820 
821  dtree.refit();
822  setup_ = false;
823 
824  setup();
825 }
826 
827 //==============================================================================
828 template <typename S>
830 {
831  const auto it = table.find(updated_obj);
832  if(it != table.end())
833  {
834  size_t node = it->second;
835  if(!dtree.getNodes()[node].bv.equal(updated_obj->getAABB()))
836  dtree.update(node, updated_obj->getAABB());
837  }
838  setup_ = false;
839 }
840 
841 //==============================================================================
842 template <typename S>
844 {
845  update_(updated_obj);
846  setup();
847 }
848 
849 //==============================================================================
850 template <typename S>
852 {
853  for(size_t i = 0, size = updated_objs.size(); i < size; ++i)
854  update_(updated_objs[i]);
855  setup();
856 }
857 
858 //==============================================================================
859 template <typename S>
861 {
862  dtree.clear();
863  table.clear();
864 }
865 
866 //==============================================================================
867 template <typename S>
869 {
870  objs.resize(this->size());
871  std::transform(table.begin(), table.end(), objs.begin(), std::bind(&DynamicAABBTable::value_type::first, std::placeholders::_1));
872 }
873 
874 //==============================================================================
875 template <typename S>
877 {
878  if(size() == 0) return;
879  switch(obj->collisionGeometry()->getNodeType())
880  {
881 #if FCL_HAVE_OCTOMAP
882  case GEOM_OCTREE:
883  {
884  if(!octree_as_geometry_collide)
885  {
886  const OcTree<S>* octree = static_cast<const OcTree<S>*>(obj->collisionGeometry().get());
887  detail::dynamic_AABB_tree_array::collisionRecurse(dtree.getNodes(), dtree.getRoot(), octree, octree->getRoot(), octree->getRootBV(), obj->getTransform(), cdata, callback);
888  }
889  else
890  detail::dynamic_AABB_tree_array::collisionRecurse(dtree.getNodes(), dtree.getRoot(), obj, cdata, callback);
891  }
892  break;
893 #endif
894  default:
895  detail::dynamic_AABB_tree_array::collisionRecurse(dtree.getNodes(), dtree.getRoot(), obj, cdata, callback);
896  }
897 }
898 
899 //==============================================================================
900 template <typename S>
902 {
903  if(size() == 0) return;
904  S min_dist = std::numeric_limits<S>::max();
905  switch(obj->collisionGeometry()->getNodeType())
906  {
907 #if FCL_HAVE_OCTOMAP
908  case GEOM_OCTREE:
909  {
910  if(!octree_as_geometry_distance)
911  {
912  const OcTree<S>* octree = static_cast<const OcTree<S>*>(obj->collisionGeometry().get());
913  detail::dynamic_AABB_tree_array::distanceRecurse(dtree.getNodes(), dtree.getRoot(), octree, octree->getRoot(), octree->getRootBV(), obj->getTransform(), cdata, callback, min_dist);
914  }
915  else
916  detail::dynamic_AABB_tree_array::distanceRecurse(dtree.getNodes(), dtree.getRoot(), obj, cdata, callback, min_dist);
917  }
918  break;
919 #endif
920  default:
921  detail::dynamic_AABB_tree_array::distanceRecurse(dtree.getNodes(), dtree.getRoot(), obj, cdata, callback, min_dist);
922  }
923 }
924 
925 //==============================================================================
926 template <typename S>
928 {
929  if(size() == 0) return;
930  detail::dynamic_AABB_tree_array::selfCollisionRecurse(dtree.getNodes(), dtree.getRoot(), cdata, callback);
931 }
932 
933 //==============================================================================
934 template <typename S>
936 {
937  if(size() == 0) return;
938  S min_dist = std::numeric_limits<S>::max();
939  detail::dynamic_AABB_tree_array::selfDistanceRecurse(dtree.getNodes(), dtree.getRoot(), cdata, callback, min_dist);
940 }
941 
942 //==============================================================================
943 template <typename S>
945 {
946  DynamicAABBTreeCollisionManager_Array* other_manager = static_cast<DynamicAABBTreeCollisionManager_Array*>(other_manager_);
947  if((size() == 0) || (other_manager->size() == 0)) return;
948  detail::dynamic_AABB_tree_array::collisionRecurse(dtree.getNodes(), dtree.getRoot(), other_manager->dtree.getNodes(), other_manager->dtree.getRoot(), cdata, callback);
949 }
950 
951 //==============================================================================
952 template <typename S>
954 {
955  DynamicAABBTreeCollisionManager_Array* other_manager = static_cast<DynamicAABBTreeCollisionManager_Array*>(other_manager_);
956  if((size() == 0) || (other_manager->size() == 0)) return;
957  S min_dist = std::numeric_limits<S>::max();
958  detail::dynamic_AABB_tree_array::distanceRecurse(dtree.getNodes(), dtree.getRoot(), other_manager->dtree.getNodes(), other_manager->dtree.getRoot(), cdata, callback, min_dist);
959 }
960 
961 //==============================================================================
962 template <typename S>
964 {
965  return dtree.empty();
966 }
967 
968 //==============================================================================
969 template <typename S>
971 {
972  return dtree.size();
973 }
974 
975 //==============================================================================
976 template <typename S>
979 {
980  return dtree;
981 }
982 
983 } // namespace fcl
984 
985 #endif
Class for hierarchy tree structure.
Definition: hierarchy_tree_array.h:61
void getObjects(std::vector< CollisionObject< S > * > &objs) const
return the objects managed by the manager
Definition: broadphase_dynamic_AABB_tree_array-inl.h:868
void convertBV(const BV1 &bv1, const Transform3< typename BV1::S > &tf1, BV2 &bv2)
Convert a bounding volume of type BV1 in configuration tf1 to bounding volume of type BV2 in identity...
Definition: utility-inl.h:934
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
void registerObject(CollisionObject< S > *obj)
add one object to the manager
Definition: broadphase_dynamic_AABB_tree_array-inl.h:770
void clear()
clear the manager
Definition: broadphase_dynamic_AABB_tree_array-inl.h:860
AABB< S > translate(const AABB< S > &aabb, const Eigen::MatrixBase< Derived > &t)
translate the center of AABB by t
Definition: AABB-inl.h:345
size_t size() const
the number of objects managed by the manager
Definition: broadphase_dynamic_AABB_tree-inl.h:966
virtual void registerObjects(const std::vector< CollisionObject< S > * > &other_objs)
add objects to the manager
Definition: broadphase_collision_manager-inl.h:66
bool(*)(CollisionObject< S > *o1, CollisionObject< S > *o2, void *cdata) CollisionCallBack
Callback for collision between two objects. Return value is whether can stop now. ...
Definition: broadphase_collision_manager.h:53
bool(*)(CollisionObject< S > *o1, CollisionObject< S > *o2, void *cdata, S &dist) DistanceCallBack
Callback for distance between two objects, Return value is whether can stop now, also return the mini...
Definition: broadphase_collision_manager.h:60
void unregisterObject(CollisionObject< S > *obj)
remove one object from the manager
Definition: broadphase_dynamic_AABB_tree_array-inl.h:778
Definition: broadphase_dynamic_AABB_tree_array.h:55
void distance(CollisionObject< S > *obj, void *cdata, DistanceCallBack< S > callback) const
perform distance computation between one object and all the objects belonging to the manager ...
Definition: broadphase_dynamic_AABB_tree_array-inl.h:901
size_t size() const
the number of objects managed by the manager
Definition: broadphase_dynamic_AABB_tree_array-inl.h:970
const Transform3< S > & getTransform() const
get object&#39;s transform
Definition: collision_object-inl.h:170
const std::shared_ptr< const CollisionGeometry< S > > & collisionGeometry() const
get geometry from the object instance
Definition: collision_object-inl.h:243
const AABB< S > & getAABB() const
get the AABB in world space
Definition: collision_object-inl.h:111
Definition: node_base_array.h:53
the object for collision or distance computation, contains the geometry and the transform information...
Definition: collision_object.h:51
Base class for broad phase collision. It helps to accelerate the collision/distance between N objects...
Definition: broadphase_collision_manager.h:66
void collide(CollisionObject< S > *obj, void *cdata, CollisionCallBack< S > callback) const
perform collision test between one object and all the objects belonging to the manager ...
Definition: broadphase_dynamic_AABB_tree_array-inl.h:876
void registerObjects(const std::vector< CollisionObject< S > * > &other_objs)
add objects to the manager
Definition: broadphase_dynamic_AABB_tree_array-inl.h:738
bool empty() const
whether the manager is empty
Definition: broadphase_dynamic_AABB_tree_array-inl.h:963
void update()
update the condition of manager
Definition: broadphase_dynamic_AABB_tree_array-inl.h:812
void setup()
initialize the manager, related with the specific type of manager
Definition: broadphase_dynamic_AABB_tree-inl.h:783
void setup()
initialize the manager, related with the specific type of manager
Definition: broadphase_dynamic_AABB_tree_array-inl.h:787