traversal_recurse.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011-2014, Willow Garage, Inc.
5  * Copyright (c) 2014-2015, 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 
39 
40 #include <vector>
41 
42 namespace coal {
43 void collisionRecurse(CollisionTraversalNodeBase* node, unsigned int b1,
44  unsigned int b2, BVHFrontList* front_list,
45  CoalScalar& sqrDistLowerBound) {
46  CoalScalar sqrDistLowerBound1 = 0, sqrDistLowerBound2 = 0;
47  bool l1 = node->isFirstNodeLeaf(b1);
48  bool l2 = node->isSecondNodeLeaf(b2);
49  if (l1 && l2) {
50  updateFrontList(front_list, b1, b2);
51 
52  // if(node->BVDisjoints(b1, b2, sqrDistLowerBound)) return;
53  node->leafCollides(b1, b2, sqrDistLowerBound);
54  return;
55  }
56 
57  if (node->BVDisjoints(b1, b2, sqrDistLowerBound)) {
58  updateFrontList(front_list, b1, b2);
59  return;
60  }
61  if (node->firstOverSecond(b1, b2)) {
62  unsigned int c1 = (unsigned int)node->getFirstLeftChild(b1);
63  unsigned int c2 = (unsigned int)node->getFirstRightChild(b1);
64 
65  collisionRecurse(node, c1, b2, front_list, sqrDistLowerBound1);
66 
67  // early stop is disabled is front_list is used
68  if (node->canStop() && !front_list) return;
69 
70  collisionRecurse(node, c2, b2, front_list, sqrDistLowerBound2);
71  sqrDistLowerBound = std::min(sqrDistLowerBound1, sqrDistLowerBound2);
72  } else {
73  unsigned int c1 = (unsigned int)node->getSecondLeftChild(b2);
74  unsigned int c2 = (unsigned int)node->getSecondRightChild(b2);
75 
76  collisionRecurse(node, b1, c1, front_list, sqrDistLowerBound1);
77 
78  // early stop is disabled is front_list is used
79  if (node->canStop() && !front_list) return;
80 
81  collisionRecurse(node, b1, c2, front_list, sqrDistLowerBound2);
82  sqrDistLowerBound = std::min(sqrDistLowerBound1, sqrDistLowerBound2);
83  }
84 }
85 
86 void collisionNonRecurse(CollisionTraversalNodeBase* node,
87  BVHFrontList* front_list,
88  CoalScalar& sqrDistLowerBound) {
89  typedef std::pair<unsigned int, unsigned int> BVPair_t;
90  // typedef std::stack<BVPair_t, std::vector<BVPair_t> > Stack_t;
91  typedef std::vector<BVPair_t> Stack_t;
92 
93  Stack_t pairs;
94  pairs.reserve(1000);
95  sqrDistLowerBound = std::numeric_limits<CoalScalar>::infinity();
96  CoalScalar sdlb = std::numeric_limits<CoalScalar>::infinity();
97 
98  pairs.push_back(BVPair_t(0, 0));
99 
100  while (!pairs.empty()) {
101  unsigned int a = pairs.back().first, b = pairs.back().second;
102  pairs.pop_back();
103 
104  bool la = node->isFirstNodeLeaf(a);
105  bool lb = node->isSecondNodeLeaf(b);
106 
107  // Leaf / Leaf case
108  if (la && lb) {
109  updateFrontList(front_list, a, b);
110 
111  // TODO should we test the BVs ?
112  // if(node->BVDijsoints(a, b, sdlb)) {
113  // if (sdlb < sqrDistLowerBound) sqrDistLowerBound = sdlb;
114  // continue;
115  //}
116  node->leafCollides(a, b, sdlb);
117  if (sdlb < sqrDistLowerBound) sqrDistLowerBound = sdlb;
118  if (node->canStop() && !front_list) return;
119  continue;
120  }
121 
122  // TODO shouldn't we test the leaf triangle against BV is la != lb
123  // if (la && !lb) { // leaf triangle 1 against BV 2
124  // } else if (!la && lb) { // BV 1 against leaf triangle 2
125  // }
126 
127  // Check the BV
128  if (node->BVDisjoints(a, b, sdlb)) {
129  if (sdlb < sqrDistLowerBound) sqrDistLowerBound = sdlb;
130  updateFrontList(front_list, a, b);
131  continue;
132  }
133 
134  if (node->firstOverSecond(a, b)) {
135  unsigned int c1 = (unsigned int)node->getFirstLeftChild(a);
136  unsigned int c2 = (unsigned int)node->getFirstRightChild(a);
137  pairs.push_back(BVPair_t(c2, b));
138  pairs.push_back(BVPair_t(c1, b));
139  } else {
140  unsigned int c1 = (unsigned int)node->getSecondLeftChild(b);
141  unsigned int c2 = (unsigned int)node->getSecondRightChild(b);
142  pairs.push_back(BVPair_t(a, c2));
143  pairs.push_back(BVPair_t(a, c1));
144  }
145  }
146 }
147 
152 void distanceRecurse(DistanceTraversalNodeBase* node, unsigned int b1,
153  unsigned int b2, BVHFrontList* front_list) {
154  bool l1 = node->isFirstNodeLeaf(b1);
155  bool l2 = node->isSecondNodeLeaf(b2);
156 
157  if (l1 && l2) {
158  updateFrontList(front_list, b1, b2);
159 
160  node->leafComputeDistance(b1, b2);
161  return;
162  }
163 
164  unsigned int a1, a2, c1, c2;
165 
166  if (node->firstOverSecond(b1, b2)) {
167  a1 = (unsigned int)node->getFirstLeftChild(b1);
168  a2 = b2;
169  c1 = (unsigned int)node->getFirstRightChild(b1);
170  c2 = b2;
171  } else {
172  a1 = b1;
173  a2 = (unsigned int)node->getSecondLeftChild(b2);
174  c1 = b1;
175  c2 = (unsigned int)node->getSecondRightChild(b2);
176  }
177 
178  CoalScalar d1 = node->BVDistanceLowerBound(a1, a2);
179  CoalScalar d2 = node->BVDistanceLowerBound(c1, c2);
180 
181  if (d2 < d1) {
182  if (!node->canStop(d2))
183  distanceRecurse(node, c1, c2, front_list);
184  else
185  updateFrontList(front_list, c1, c2);
186 
187  if (!node->canStop(d1))
188  distanceRecurse(node, a1, a2, front_list);
189  else
190  updateFrontList(front_list, a1, a2);
191  } else {
192  if (!node->canStop(d1))
193  distanceRecurse(node, a1, a2, front_list);
194  else
195  updateFrontList(front_list, a1, a2);
196 
197  if (!node->canStop(d2))
198  distanceRecurse(node, c1, c2, front_list);
199  else
200  updateFrontList(front_list, c1, c2);
201  }
202 }
203 
205 struct COAL_LOCAL BVT {
208 
210  unsigned int b1, b2;
211 };
212 
214 struct COAL_LOCAL BVT_Comparer{bool operator()(const BVT& lhs, const BVT& rhs)
215  const {return lhs.d > rhs.d;
216 } // namespace coal
217 }
218 ;
219 
220 struct COAL_LOCAL BVTQ {
221  BVTQ() : qsize(2) {}
222 
223  bool empty() const { return pq.empty(); }
224 
225  size_t size() const { return pq.size(); }
226 
227  const BVT& top() const { return pq.top(); }
228 
229  void push(const BVT& x) { pq.push(x); }
230 
231  void pop() { pq.pop(); }
232 
233  bool full() const { return (pq.size() + 1 >= qsize); }
234 
235  std::priority_queue<BVT, std::vector<BVT>, BVT_Comparer> pq;
236 
238  unsigned int qsize;
239 };
240 
241 void distanceQueueRecurse(DistanceTraversalNodeBase* node, unsigned int b1,
242  unsigned int b2, BVHFrontList* front_list,
243  unsigned int qsize) {
244  BVTQ bvtq;
245  bvtq.qsize = qsize;
246 
247  BVT min_test;
248  min_test.b1 = b1;
249  min_test.b2 = b2;
250 
251  while (1) {
252  bool l1 = node->isFirstNodeLeaf(min_test.b1);
253  bool l2 = node->isSecondNodeLeaf(min_test.b2);
254 
255  if (l1 && l2) {
256  updateFrontList(front_list, min_test.b1, min_test.b2);
257 
258  node->leafComputeDistance(min_test.b1, min_test.b2);
259  } else if (bvtq.full()) {
260  // queue should not get two more tests, recur
261 
262  distanceQueueRecurse(node, min_test.b1, min_test.b2, front_list, qsize);
263  } else {
264  // queue capacity is not full yet
265  BVT bvt1, bvt2;
266 
267  if (node->firstOverSecond(min_test.b1, min_test.b2)) {
268  unsigned int c1 = (unsigned int)node->getFirstLeftChild(min_test.b1);
269  unsigned int c2 = (unsigned int)node->getFirstRightChild(min_test.b1);
270  bvt1.b1 = c1;
271  bvt1.b2 = min_test.b2;
272  bvt1.d = node->BVDistanceLowerBound(bvt1.b1, bvt1.b2);
273 
274  bvt2.b1 = c2;
275  bvt2.b2 = min_test.b2;
276  bvt2.d = node->BVDistanceLowerBound(bvt2.b1, bvt2.b2);
277  } else {
278  unsigned int c1 = (unsigned int)node->getSecondLeftChild(min_test.b2);
279  unsigned int c2 = (unsigned int)node->getSecondRightChild(min_test.b2);
280  bvt1.b1 = min_test.b1;
281  bvt1.b2 = c1;
282  bvt1.d = node->BVDistanceLowerBound(bvt1.b1, bvt1.b2);
283 
284  bvt2.b1 = min_test.b1;
285  bvt2.b2 = c2;
286  bvt2.d = node->BVDistanceLowerBound(bvt2.b1, bvt2.b2);
287  }
288 
289  bvtq.push(bvt1);
290  bvtq.push(bvt2);
291  }
292 
293  if (bvtq.empty())
294  break;
295  else {
296  min_test = bvtq.top();
297  bvtq.pop();
298 
299  if (node->canStop(min_test.d)) {
300  updateFrontList(front_list, min_test.b1, min_test.b2);
301  break;
302  }
303  }
304  }
305 }
306 
307 void propagateBVHFrontListCollisionRecurse(CollisionTraversalNodeBase* node,
308  const CollisionRequest& /*request*/,
309  CollisionResult& result,
310  BVHFrontList* front_list) {
311  CoalScalar sqrDistLowerBound = -1, sqrDistLowerBound1 = 0,
312  sqrDistLowerBound2 = 0;
313  BVHFrontList::iterator front_iter;
314  BVHFrontList append;
315  for (front_iter = front_list->begin(); front_iter != front_list->end();
316  ++front_iter) {
317  unsigned int b1 = front_iter->left;
318  unsigned int b2 = front_iter->right;
319  bool l1 = node->isFirstNodeLeaf(b1);
320  bool l2 = node->isSecondNodeLeaf(b2);
321 
322  if (l1 & l2) {
323  front_iter->valid = false; // the front node is no longer valid, in
324  // collideRecurse will add again.
325  collisionRecurse(node, b1, b2, &append, sqrDistLowerBound);
326  } else {
327  if (!node->BVDisjoints(b1, b2, sqrDistLowerBound)) {
328  front_iter->valid = false;
329  if (node->firstOverSecond(b1, b2)) {
330  unsigned int c1 = (unsigned int)node->getFirstLeftChild(b1);
331  unsigned int c2 = (unsigned int)node->getFirstRightChild(b1);
332 
333  collisionRecurse(node, c1, b2, front_list, sqrDistLowerBound1);
334  collisionRecurse(node, c2, b2, front_list, sqrDistLowerBound2);
335  sqrDistLowerBound = std::min(sqrDistLowerBound1, sqrDistLowerBound2);
336  } else {
337  unsigned int c1 = (unsigned int)node->getSecondLeftChild(b2);
338  unsigned int c2 = (unsigned int)node->getSecondRightChild(b2);
339 
340  collisionRecurse(node, b1, c1, front_list, sqrDistLowerBound1);
341  collisionRecurse(node, b1, c2, front_list, sqrDistLowerBound2);
342  sqrDistLowerBound = std::min(sqrDistLowerBound1, sqrDistLowerBound2);
343  }
344  }
345  }
346  result.updateDistanceLowerBound(sqrt(sqrDistLowerBound));
347  }
348 
349  // clean the old front list (remove invalid node)
350  for (front_iter = front_list->begin(); front_iter != front_list->end();) {
351  if (!front_iter->valid)
352  front_iter = front_list->erase(front_iter);
353  else
354  ++front_iter;
355  }
356 
357  for (front_iter = append.begin(); front_iter != append.end(); ++front_iter) {
358  front_list->push_back(*front_iter);
359  }
360 }
361 
362 } // namespace coal
coal::BVT
Bounding volume test structure.
Definition: traversal_recurse.cpp:205
coal::BVT_Comparer
Comparer between two BVT.
Definition: traversal_recurse.cpp:214
geometric_shapes.d1
float d1
Definition: scripts/geometric_shapes.py:31
coal::BVT::b1
unsigned int b1
bv indices for a pair of bvs in two models
Definition: traversal_recurse.cpp:210
coal::updateFrontList
void updateFrontList(BVHFrontList *front_list, unsigned int b1, unsigned int b2)
Add new front node into the front list.
Definition: coal/BVH/BVH_front.h:69
coal::BVTQ::top
const BVT & top() const
Definition: traversal_recurse.cpp:227
coal::propagateBVHFrontListCollisionRecurse
void propagateBVHFrontListCollisionRecurse(CollisionTraversalNodeBase *node, const CollisionRequest &, CollisionResult &result, BVHFrontList *front_list)
Definition: traversal_recurse.cpp:307
coal
Main namespace.
Definition: coal/broadphase/broadphase_bruteforce.h:44
coal::distanceRecurse
void distanceRecurse(DistanceTraversalNodeBase *node, unsigned int b1, unsigned int b2, BVHFrontList *front_list)
Definition: traversal_recurse.cpp:152
coal::BVTQ::qsize
unsigned int qsize
Queue size.
Definition: traversal_recurse.cpp:238
coal::BVTQ::BVTQ
BVTQ()
Definition: traversal_recurse.cpp:221
coal::BVTQ
Definition: traversal_recurse.cpp:220
coal::BVHFrontList
std::list< BVHFrontNode > BVHFrontList
BVH front list is a list of front nodes.
Definition: coal/BVH/BVH_front.h:66
coal::BVTQ::empty
bool empty() const
Definition: traversal_recurse.cpp:223
a
list a
coal::BVT::d
CoalScalar d
distance between bvs
Definition: traversal_recurse.cpp:207
coal::BVT_Comparer::operator()
bool operator()(const BVT &lhs, const BVT &rhs) const
Definition: traversal_recurse.cpp:214
coal::distanceQueueRecurse
void distanceQueueRecurse(DistanceTraversalNodeBase *node, unsigned int b1, unsigned int b2, BVHFrontList *front_list, unsigned int qsize)
Definition: traversal_recurse.cpp:241
traversal_recurse.h
coal::BVTQ::full
bool full() const
Definition: traversal_recurse.cpp:233
coal::CollisionResult
collision result
Definition: coal/collision_data.h:390
coal::CollisionRequest
request to the collision algorithm
Definition: coal/collision_data.h:311
x
x
coal::CollisionResult::updateDistanceLowerBound
void updateDistanceLowerBound(const CoalScalar &distance_lower_bound_)
Update the lower bound only if the distance is inferior.
Definition: coal/collision_data.h:424
l1
list l1
coal::collisionRecurse
void collisionRecurse(CollisionTraversalNodeBase *node, unsigned int b1, unsigned int b2, BVHFrontList *front_list, CoalScalar &sqrDistLowerBound)
Definition: traversal_recurse.cpp:43
coal::collisionNonRecurse
void collisionNonRecurse(CollisionTraversalNodeBase *node, BVHFrontList *front_list, CoalScalar &sqrDistLowerBound)
Definition: traversal_recurse.cpp:86
generate_distance_plot.b
float b
Definition: generate_distance_plot.py:7
coal::BVTQ::pop
void pop()
Definition: traversal_recurse.cpp:231
c2
c2
coal::BVTQ::pq
std::priority_queue< BVT, std::vector< BVT >, BVT_Comparer > pq
Definition: traversal_recurse.cpp:235
coal::BVTQ::push
void push(const BVT &x)
Definition: traversal_recurse.cpp:229
l2
l2
coal::BVTQ::size
size_t size() const
Definition: traversal_recurse.cpp:225
coal::CoalScalar
double CoalScalar
Definition: coal/data_types.h:76
coal::BVT::b2
unsigned int b2
Definition: traversal_recurse.cpp:210


hpp-fcl
Author(s):
autogenerated on Sat Nov 23 2024 03:44:59