FCL  0.6.0
Flexible Collision Library
traversal_recurse-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_TRAVERSAL_RECURSE_INL_H
39 #define FCL_TRAVERSAL_RECURSE_INL_H
40 
41 #include "fcl/narrowphase/detail/traversal/traversal_recurse.h"
42 
43 #include <queue>
44 
45 namespace fcl
46 {
47 
48 namespace detail
49 {
50 
51 //==============================================================================
52 extern template
53 void collisionRecurse(CollisionTraversalNodeBase<double>* node, int b1, int b2, BVHFrontList* front_list);
54 
55 //==============================================================================
56 extern template
57 void collisionRecurse(MeshCollisionTraversalNodeOBB<double>* node, int b1, int b2, const Matrix3<double>& R, const Vector3<double>& T, BVHFrontList* front_list);
58 
59 //==============================================================================
60 extern template
61 void collisionRecurse(MeshCollisionTraversalNodeRSS<double>* node, int b1, int b2, const Matrix3<double>& R, const Vector3<double>& T, BVHFrontList* front_list);
62 
63 //==============================================================================
64 extern template
65 void selfCollisionRecurse(CollisionTraversalNodeBase<double>* node, int b, BVHFrontList* front_list);
66 
67 //==============================================================================
68 extern template
69 void distanceRecurse(DistanceTraversalNodeBase<double>* node, int b1, int b2, BVHFrontList* front_list);
70 
71 //==============================================================================
72 extern template
73 void distanceQueueRecurse(DistanceTraversalNodeBase<double>* node, int b1, int b2, BVHFrontList* front_list, int qsize);
74 
75 //==============================================================================
76 extern template
77 void propagateBVHFrontListCollisionRecurse(CollisionTraversalNodeBase<double>* node, BVHFrontList* front_list);
78 
79 //==============================================================================
80 template <typename S>
81 void collisionRecurse(CollisionTraversalNodeBase<S>* node, int b1, int b2, BVHFrontList* front_list)
82 {
83  bool l1 = node->isFirstNodeLeaf(b1);
84  bool l2 = node->isSecondNodeLeaf(b2);
85 
86  if(l1 && l2)
87  {
88  updateFrontList(front_list, b1, b2);
89 
90  if(node->BVTesting(b1, b2)) return;
91 
92  node->leafTesting(b1, b2);
93  return;
94  }
95 
96  if(node->BVTesting(b1, b2))
97  {
98  updateFrontList(front_list, b1, b2);
99  return;
100  }
101 
102  if(node->firstOverSecond(b1, b2))
103  {
104  int c1 = node->getFirstLeftChild(b1);
105  int c2 = node->getFirstRightChild(b1);
106 
107  collisionRecurse(node, c1, b2, front_list);
108 
109  // early stop is disabled is front_list is used
110  if(node->canStop() && !front_list) return;
111 
112  collisionRecurse(node, c2, b2, front_list);
113  }
114  else
115  {
116  int c1 = node->getSecondLeftChild(b2);
117  int c2 = node->getSecondRightChild(b2);
118 
119  collisionRecurse(node, b1, c1, front_list);
120 
121  // early stop is disabled is front_list is used
122  if(node->canStop() && !front_list) return;
123 
124  collisionRecurse(node, b1, c2, front_list);
125  }
126 }
127 
128 //==============================================================================
129 template <typename S>
130 void collisionRecurse(MeshCollisionTraversalNodeOBB<S>* node, int b1, int b2, const Matrix3<S>& R, const Vector3<S>& T, BVHFrontList* front_list)
131 {
132  bool l1 = node->isFirstNodeLeaf(b1);
133  bool l2 = node->isSecondNodeLeaf(b2);
134 
135  if(l1 && l2)
136  {
137  updateFrontList(front_list, b1, b2);
138 
139  if(node->BVTesting(b1, b2, R, T)) return;
140 
141  node->leafTesting(b1, b2, R, T);
142  return;
143  }
144 
145  if(node->BVTesting(b1, b2, R, T))
146  {
147  updateFrontList(front_list, b1, b2);
148  return;
149  }
150 
151  Vector3<S> temp;
152 
153  if(node->firstOverSecond(b1, b2))
154  {
155  int c1 = node->getFirstLeftChild(b1);
156  int c2 = node->getFirstRightChild(b1);
157 
158  const OBB<S>& bv1 = node->model1->getBV(c1).bv;
159 
160  Matrix3<S> Rc = R.transpose() * bv1.axis;
161  temp = T - bv1.To;
162  Vector3<S> Tc = temp.transpose() * bv1.axis;
163 
164  collisionRecurse(node, c1, b2, Rc, Tc, front_list);
165 
166  // early stop is disabled is front_list is used
167  if(node->canStop() && !front_list) return;
168 
169  const OBB<S>& bv2 = node->model1->getBV(c2).bv;
170 
171  Rc.noalias() = R.transpose() * bv2.axis;
172  temp = T - bv2.To;
173  Tc[0] = bv2.axis.col(0).dot(temp);
174  Tc[1] = bv2.axis.col(1).dot(temp);
175  Tc[2] = bv2.axis.col(2).dot(temp);
176 
177  collisionRecurse(node, c2, b2, Rc, Tc, front_list);
178  }
179  else
180  {
181  int c1 = node->getSecondLeftChild(b2);
182  int c2 = node->getSecondRightChild(b2);
183 
184  const OBB<S>& bv1 = node->model2->getBV(c1).bv;
185  Matrix3<S> Rc;
186  temp.noalias() = R * bv1.axis.col(0);
187  Rc(0, 0) = temp[0]; Rc(1, 0) = temp[1]; Rc(2, 0) = temp[2];
188  temp.noalias() = R * bv1.axis.col(1);
189  Rc(0, 1) = temp[0]; Rc(1, 1) = temp[1]; Rc(2, 1) = temp[2];
190  temp.noalias() = R * bv1.axis.col(2);
191  Rc(0, 2) = temp[0]; Rc(1, 2) = temp[1]; Rc(2, 2) = temp[2];
192  Vector3<S> Tc = R * bv1.To + T;
193 
194  collisionRecurse(node, b1, c1, Rc, Tc, front_list);
195 
196  // early stop is disabled is front_list is used
197  if(node->canStop() && !front_list) return;
198 
199  const OBB<S>& bv2 = node->model2->getBV(c2).bv;
200  temp.noalias() = R * bv2.axis.col(0);
201  Rc(0, 0) = temp[0]; Rc(1, 0) = temp[1]; Rc(2, 0) = temp[2];
202  temp.noalias() = R * bv2.axis.col(1);
203  Rc(0, 1) = temp[0]; Rc(1, 1) = temp[1]; Rc(2, 1) = temp[2];
204  temp.noalias() = R * bv2.axis.col(2);
205  Rc(0, 2) = temp[0]; Rc(1, 2) = temp[1]; Rc(2, 2) = temp[2];
206  Tc = T;
207  Tc.noalias() += R * bv2.To;
208 
209  collisionRecurse(node, b1, c2, Rc, Tc, front_list);
210  }
211 }
212 
213 //==============================================================================
214 template <typename S>
215 void collisionRecurse(MeshCollisionTraversalNodeRSS<S>* node, int b1, int b2, const Matrix3<S>& R, const Vector3<S>& T, BVHFrontList* front_list)
216 {
217  // Do nothing
218 }
219 
220 //==============================================================================
224 template <typename S>
225 void selfCollisionRecurse(CollisionTraversalNodeBase<S>* node, int b, BVHFrontList* front_list)
226 {
227  bool l = node->isFirstNodeLeaf(b);
228 
229  if(l) return;
230 
231  int c1 = node->getFirstLeftChild(b);
232  int c2 = node->getFirstRightChild(b);
233 
234  selfCollisionRecurse(node, c1, front_list);
235  if(node->canStop() && !front_list) return;
236 
237  selfCollisionRecurse(node, c2, front_list);
238  if(node->canStop() && !front_list) return;
239 
240  collisionRecurse(node, c1, c2, front_list);
241 }
242 
243 //==============================================================================
244 template <typename S>
245 void distanceRecurse(DistanceTraversalNodeBase<S>* node, int b1, int b2, BVHFrontList* front_list)
246 {
247  bool l1 = node->isFirstNodeLeaf(b1);
248  bool l2 = node->isSecondNodeLeaf(b2);
249 
250  if(l1 && l2)
251  {
252  updateFrontList(front_list, b1, b2);
253 
254  node->leafTesting(b1, b2);
255  return;
256  }
257 
258  int a1, a2, c1, c2;
259 
260  if(node->firstOverSecond(b1, b2))
261  {
262  a1 = node->getFirstLeftChild(b1);
263  a2 = b2;
264  c1 = node->getFirstRightChild(b1);
265  c2 = b2;
266  }
267  else
268  {
269  a1 = b1;
270  a2 = node->getSecondLeftChild(b2);
271  c1 = b1;
272  c2 = node->getSecondRightChild(b2);
273  }
274 
275  S d1 = node->BVTesting(a1, a2);
276  S d2 = node->BVTesting(c1, c2);
277 
278  if(d2 < d1)
279  {
280  if(!node->canStop(d2))
281  distanceRecurse(node, c1, c2, front_list);
282  else
283  updateFrontList(front_list, c1, c2);
284 
285  if(!node->canStop(d1))
286  distanceRecurse(node, a1, a2, front_list);
287  else
288  updateFrontList(front_list, a1, a2);
289  }
290  else
291  {
292  if(!node->canStop(d1))
293  distanceRecurse(node, a1, a2, front_list);
294  else
295  updateFrontList(front_list, a1, a2);
296 
297  if(!node->canStop(d2))
298  distanceRecurse(node, c1, c2, front_list);
299  else
300  updateFrontList(front_list, c1, c2);
301  }
302 }
303 
304 //==============================================================================
306 template <typename S>
307 struct BVT
308 {
310  S d;
311 
313  int b1, b2;
314 };
315 
316 //==============================================================================
318 template <typename S>
320 {
321  bool operator() (const BVT<S>& lhs, const BVT<S>& rhs) const
322  {
323  return lhs.d > rhs.d;
324  }
325 };
326 
327 //==============================================================================
328 template <typename S>
329 struct BVTQ
330 {
331  BVTQ() : qsize(2) {}
332 
333  bool empty() const
334  {
335  return pq.empty();
336  }
337 
338  size_t size() const
339  {
340  return pq.size();
341  }
342 
343  const BVT<S>& top() const
344  {
345  return pq.top();
346  }
347 
348  void push(const BVT<S>& x)
349  {
350  pq.push(x);
351  }
352 
353  void pop()
354  {
355  pq.pop();
356  }
357 
358  bool full() const
359  {
360  return (pq.size() + 1 >= qsize);
361  }
362 
363  std::priority_queue<BVT<S>, std::vector<BVT<S>>, BVT_Comparer<S>> pq;
364 
366  unsigned int qsize;
367 };
368 
369 //==============================================================================
370 template <typename S>
371 void distanceQueueRecurse(DistanceTraversalNodeBase<S>* node, int b1, int b2, BVHFrontList* front_list, int qsize)
372 {
373  BVTQ<S> bvtq;
374  bvtq.qsize = qsize;
375 
376  BVT<S> min_test;
377  min_test.b1 = b1;
378  min_test.b2 = b2;
379 
380  while(1)
381  {
382  bool l1 = node->isFirstNodeLeaf(min_test.b1);
383  bool l2 = node->isSecondNodeLeaf(min_test.b2);
384 
385  if(l1 && l2)
386  {
387  updateFrontList(front_list, min_test.b1, min_test.b2);
388 
389  node->leafTesting(min_test.b1, min_test.b2);
390  }
391  else if(bvtq.full())
392  {
393  // queue should not get two more tests, recur
394 
395  distanceQueueRecurse(node, min_test.b1, min_test.b2, front_list, qsize);
396  }
397  else
398  {
399  // queue capacity is not full yet
400  BVT<S> bvt1, bvt2;
401 
402  if(node->firstOverSecond(min_test.b1, min_test.b2))
403  {
404  int c1 = node->getFirstLeftChild(min_test.b1);
405  int c2 = node->getFirstRightChild(min_test.b1);
406  bvt1.b1 = c1;
407  bvt1.b2 = min_test.b2;
408  bvt1.d = node->BVTesting(bvt1.b1, bvt1.b2);
409 
410  bvt2.b1 = c2;
411  bvt2.b2 = min_test.b2;
412  bvt2.d = node->BVTesting(bvt2.b1, bvt2.b2);
413  }
414  else
415  {
416  int c1 = node->getSecondLeftChild(min_test.b2);
417  int c2 = node->getSecondRightChild(min_test.b2);
418  bvt1.b1 = min_test.b1;
419  bvt1.b2 = c1;
420  bvt1.d = node->BVTesting(bvt1.b1, bvt1.b2);
421 
422  bvt2.b1 = min_test.b1;
423  bvt2.b2 = c2;
424  bvt2.d = node->BVTesting(bvt2.b1, bvt2.b2);
425  }
426 
427  bvtq.push(bvt1);
428  bvtq.push(bvt2);
429  }
430 
431  if(bvtq.empty())
432  break;
433  else
434  {
435  min_test = bvtq.top();
436  bvtq.pop();
437 
438  if(node->canStop(min_test.d))
439  {
440  updateFrontList(front_list, min_test.b1, min_test.b2);
441  break;
442  }
443  }
444  }
445 }
446 
447 //==============================================================================
448 template <typename S>
449 void propagateBVHFrontListCollisionRecurse(CollisionTraversalNodeBase<S>* node, BVHFrontList* front_list)
450 {
451  BVHFrontList::iterator front_iter;
452  BVHFrontList append;
453  for(front_iter = front_list->begin(); front_iter != front_list->end(); ++front_iter)
454  {
455  int b1 = front_iter->left;
456  int b2 = front_iter->right;
457  bool l1 = node->isFirstNodeLeaf(b1);
458  bool l2 = node->isSecondNodeLeaf(b2);
459 
460  if(l1 & l2)
461  {
462  front_iter->valid = false; // the front node is no longer valid, in collideRecurse will add again.
463  collisionRecurse(node, b1, b2, &append);
464  }
465  else
466  {
467  if(!node->BVTesting(b1, b2))
468  {
469  front_iter->valid = false;
470 
471  if(node->firstOverSecond(b1, b2))
472  {
473  int c1 = node->getFirstLeftChild(b1);
474  int c2 = node->getFirstRightChild(b1);
475 
476  collisionRecurse(node, c1, b2, front_list);
477  collisionRecurse(node, c2, b2, front_list);
478  }
479  else
480  {
481  int c1 = node->getSecondLeftChild(b2);
482  int c2 = node->getSecondRightChild(b2);
483 
484  collisionRecurse(node, b1, c1, front_list);
485  collisionRecurse(node, b1, c2, front_list);
486  }
487  }
488  }
489  }
490 
491 
492  // clean the old front list (remove invalid node)
493  for(front_iter = front_list->begin(); front_iter != front_list->end();)
494  {
495  if(!front_iter->valid)
496  front_iter = front_list->erase(front_iter);
497  else
498  ++front_iter;
499  }
500 
501  for(front_iter = append.begin(); front_iter != append.end(); ++front_iter)
502  {
503  front_list->push_back(*front_iter);
504  }
505 }
506 
507 } // namespace detail
508 } // namespace fcl
509 
510 #endif
virtual S BVTesting(int b1, int b2) const
BV test between b1 and b2.
Definition: distance_traversal_node_base-inl.h:70
int b1
bv indices for a pair of bvs in two models
Definition: traversal_recurse-inl.h:313
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
virtual bool BVTesting(int b1, int b2) const
BV test between b1 and b2.
Definition: collision_traversal_node_base-inl.h:70
Bounding volume test structure.
Definition: traversal_recurse-inl.h:307
S d
distance between bvs
Definition: traversal_recurse-inl.h:310
virtual bool isFirstNodeLeaf(int b) const
Whether b is a leaf node in the first BVH tree.
Definition: traversal_node_base-inl.h:76
Comparer between two BVT.
Definition: traversal_recurse-inl.h:319
virtual bool firstOverSecond(int b1, int b2) const
Traverse the subtree of the node in the first tree first.
Definition: traversal_node_base-inl.h:90
Node structure encoding the information required for collision traversal.
Definition: collision_traversal_node_base.h:52
Node structure encoding the information required for distance traversal.
Definition: distance_traversal_node_base.h:53
virtual bool canStop(S c) const
Check whether the traversal can stop.
Definition: distance_traversal_node_base-inl.h:84
virtual int getFirstRightChild(int b) const
Get the right child of the node b in the first tree.
Definition: traversal_node_base-inl.h:104
virtual void leafTesting(int b1, int b2) const
Leaf test between node b1 and b2, if they are both leafs.
Definition: distance_traversal_node_base-inl.h:77
virtual bool isSecondNodeLeaf(int b) const
Whether b is a leaf node in the second BVH tree.
Definition: traversal_node_base-inl.h:83
virtual int getSecondLeftChild(int b) const
Get the left child of the node b in the second tree.
Definition: traversal_node_base-inl.h:111
virtual int getSecondRightChild(int b) const
Get the right child of the node b in the second tree.
Definition: traversal_node_base-inl.h:118
virtual int getFirstLeftChild(int b) const
Get the left child of the node b in the first tree.
Definition: traversal_node_base-inl.h:97
unsigned int qsize
Queue size.
Definition: traversal_recurse-inl.h:366
Definition: traversal_recurse-inl.h:329