hpp-fcl  3.0.0
HPP fork of FCL -- The Flexible Collision Library
traversal_node_bvh_shape.h
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 
38 #ifndef HPP_FCL_TRAVERSAL_NODE_MESH_SHAPE_H
39 #define HPP_FCL_TRAVERSAL_NODE_MESH_SHAPE_H
40 
42 
43 #include <hpp/fcl/collision_data.h>
49 #include <hpp/fcl/BVH/BVH_model.h>
51 
52 namespace hpp {
53 namespace fcl {
54 
57 
59 template <typename BV, typename S>
60 class BVHShapeCollisionTraversalNode : public CollisionTraversalNodeBase {
61  public:
62  BVHShapeCollisionTraversalNode(const CollisionRequest& request)
63  : CollisionTraversalNodeBase(request) {
64  model1 = NULL;
65  model2 = NULL;
66 
67  num_bv_tests = 0;
68  num_leaf_tests = 0;
69  query_time_seconds = 0.0;
70  }
71 
73  bool isFirstNodeLeaf(unsigned int b) const {
74  return model1->getBV(b).isLeaf();
75  }
76 
78  int getFirstLeftChild(unsigned int b) const {
79  return model1->getBV(b).leftChild();
80  }
81 
83  int getFirstRightChild(unsigned int b) const {
84  return model1->getBV(b).rightChild();
85  }
86 
87  const BVHModel<BV>* model1;
88  const S* model2;
89  BV model2_bv;
90 
91  mutable int num_bv_tests;
92  mutable int num_leaf_tests;
93  mutable FCL_REAL query_time_seconds;
94 };
95 
97 template <typename BV, typename S,
98  int _Options = RelativeTransformationIsIdentity>
99 class MeshShapeCollisionTraversalNode
100  : public BVHShapeCollisionTraversalNode<BV, S> {
101  public:
102  enum {
103  Options = _Options,
104  RTIsIdentity = _Options & RelativeTransformationIsIdentity
105  };
106 
107  MeshShapeCollisionTraversalNode(const CollisionRequest& request)
108  : BVHShapeCollisionTraversalNode<BV, S>(request) {
109  vertices = NULL;
110  tri_indices = NULL;
111 
112  nsolver = NULL;
113  }
114 
120  bool BVDisjoints(unsigned int b1, unsigned int /*b2*/,
121  FCL_REAL& sqrDistLowerBound) const {
122  if (this->enable_statistics) this->num_bv_tests++;
123  bool disjoint;
124  if (RTIsIdentity)
125  disjoint = !this->model1->getBV(b1).bv.overlap(
126  this->model2_bv, this->request, sqrDistLowerBound);
127  else
128  disjoint = !overlap(this->tf1.getRotation(), this->tf1.getTranslation(),
129  this->model1->getBV(b1).bv, this->model2_bv,
130  this->request, sqrDistLowerBound);
131  if (disjoint)
132  internal::updateDistanceLowerBoundFromBV(this->request, *this->result,
133  sqrDistLowerBound);
134  assert(!disjoint || sqrDistLowerBound > 0);
135  return disjoint;
136  }
137 
139  void leafCollides(unsigned int b1, unsigned int /*b2*/,
140  FCL_REAL& sqrDistLowerBound) const {
141  if (this->enable_statistics) this->num_leaf_tests++;
142  const BVNode<BV>& node = this->model1->getBV(b1);
143 
144  int primitive_id = node.primitiveId();
145 
146  const Triangle& tri_id = this->tri_indices[primitive_id];
147  const TriangleP tri(this->vertices[tri_id[0]], this->vertices[tri_id[1]],
148  this->vertices[tri_id[2]]);
149 
150  // When reaching this point, `this->solver` has already been set up
151  // by the CollisionRequest `this->request`.
152  // The only thing we need to (and can) pass to `ShapeShapeDistance` is
153  // whether or not penetration information is should be computed in case of
154  // collision.
155  const bool compute_penetration =
156  this->request.enable_contact || (this->request.security_margin < 0);
157  Vec3f c1, c2, normal;
159 
160  if (RTIsIdentity) {
161  static const Transform3f Id;
162  distance = internal::ShapeShapeDistance<TriangleP, S>(
163  &tri, Id, this->model2, this->tf2, this->nsolver, compute_penetration,
164  c1, c2, normal);
165  } else {
166  distance = internal::ShapeShapeDistance<TriangleP, S>(
167  &tri, this->tf1, this->model2, this->tf2, this->nsolver,
168  compute_penetration, c1, c2, normal);
169  }
170  const FCL_REAL distToCollision = distance - this->request.security_margin;
171 
172  internal::updateDistanceLowerBoundFromLeaf(this->request, *(this->result),
173  distToCollision, c1, c2, normal);
174 
175  if (distToCollision <= this->request.collision_distance_threshold) {
176  sqrDistLowerBound = 0;
177  if (this->result->numContacts() < this->request.num_max_contacts) {
178  this->result->addContact(Contact(this->model1, this->model2,
179  primitive_id, Contact::NONE, c1, c2,
180  normal, distance));
181  assert(this->result->isCollision());
182  }
183  } else {
184  sqrDistLowerBound = distToCollision * distToCollision;
185  }
186 
187  assert(this->result->isCollision() || sqrDistLowerBound > 0);
188  } // leafCollides
189 
190  Vec3f* vertices;
191  Triangle* tri_indices;
192 
193  const GJKSolver* nsolver;
194 };
195 
197 
200 
202 template <typename BV, typename S>
203 class BVHShapeDistanceTraversalNode : public DistanceTraversalNodeBase {
204  public:
205  BVHShapeDistanceTraversalNode() : DistanceTraversalNodeBase() {
206  model1 = NULL;
207  model2 = NULL;
208 
209  num_bv_tests = 0;
210  num_leaf_tests = 0;
211  query_time_seconds = 0.0;
212  }
213 
215  bool isFirstNodeLeaf(unsigned int b) const {
216  return model1->getBV(b).isLeaf();
217  }
218 
220  int getFirstLeftChild(unsigned int b) const {
221  return model1->getBV(b).leftChild();
222  }
223 
225  int getFirstRightChild(unsigned int b) const {
226  return model1->getBV(b).rightChild();
227  }
228 
230  FCL_REAL BVDistanceLowerBound(unsigned int b1, unsigned int /*b2*/) const {
231  return model1->getBV(b1).bv.distance(model2_bv);
232  }
233 
234  const BVHModel<BV>* model1;
235  const S* model2;
236  BV model2_bv;
237 
238  mutable int num_bv_tests;
239  mutable int num_leaf_tests;
240  mutable FCL_REAL query_time_seconds;
241 };
242 
244 template <typename S, typename BV>
245 class ShapeBVHDistanceTraversalNode : public DistanceTraversalNodeBase {
246  public:
247  ShapeBVHDistanceTraversalNode() : DistanceTraversalNodeBase() {
248  model1 = NULL;
249  model2 = NULL;
250 
251  num_bv_tests = 0;
252  num_leaf_tests = 0;
253  query_time_seconds = 0.0;
254  }
255 
257  bool isSecondNodeLeaf(unsigned int b) const {
258  return model2->getBV(b).isLeaf();
259  }
260 
262  int getSecondLeftChild(unsigned int b) const {
263  return model2->getBV(b).leftChild();
264  }
265 
267  int getSecondRightChild(unsigned int b) const {
268  return model2->getBV(b).rightChild();
269  }
270 
272  FCL_REAL BVDistanceLowerBound(unsigned int /*b1*/, unsigned int b2) const {
273  return model1_bv.distance(model2->getBV(b2).bv);
274  }
275 
276  const S* model1;
277  const BVHModel<BV>* model2;
278  BV model1_bv;
279 
280  mutable int num_bv_tests;
281  mutable int num_leaf_tests;
282  mutable FCL_REAL query_time_seconds;
283 };
284 
286 template <typename BV, typename S>
287 class MeshShapeDistanceTraversalNode
288  : public BVHShapeDistanceTraversalNode<BV, S> {
289  public:
290  MeshShapeDistanceTraversalNode() : BVHShapeDistanceTraversalNode<BV, S>() {
291  vertices = NULL;
292  tri_indices = NULL;
293 
294  rel_err = 0;
295  abs_err = 0;
296 
297  nsolver = NULL;
298  }
299 
301  void leafComputeDistance(unsigned int b1, unsigned int /*b2*/) const {
302  if (this->enable_statistics) this->num_leaf_tests++;
303 
304  const BVNode<BV>& node = this->model1->getBV(b1);
305 
306  int primitive_id = node.primitiveId();
307 
308  const Triangle& tri_id = tri_indices[primitive_id];
309  const TriangleP tri(this->vertices[tri_id[0]], this->vertices[tri_id[1]],
310  this->vertices[tri_id[2]]);
311 
312  Vec3f p1, p2, normal;
313  const FCL_REAL distance = internal::ShapeShapeDistance<TriangleP, S>(
314  &tri, this->tf1, this->model2, this->tf2, this->nsolver,
315  this->request.enable_signed_distance, p1, p2, normal);
316 
317  this->result->update(distance, this->model1, this->model2, primitive_id,
318  DistanceResult::NONE, p1, p2, normal);
319  }
320 
322  bool canStop(FCL_REAL c) const {
323  if ((c >= this->result->min_distance - abs_err) &&
324  (c * (1 + rel_err) >= this->result->min_distance))
325  return true;
326  return false;
327  }
328 
329  Vec3f* vertices;
330  Triangle* tri_indices;
331 
332  FCL_REAL rel_err;
333  FCL_REAL abs_err;
334 
335  const GJKSolver* nsolver;
336 };
337 
339 namespace details {
340 
341 template <typename BV, typename S>
342 void meshShapeDistanceOrientedNodeleafComputeDistance(
343  unsigned int b1, unsigned int /* b2 */, const BVHModel<BV>* model1,
344  const S& model2, Vec3f* vertices, Triangle* tri_indices,
345  const Transform3f& tf1, const Transform3f& tf2, const GJKSolver* nsolver,
346  bool enable_statistics, int& num_leaf_tests, const DistanceRequest& request,
347  DistanceResult& result) {
348  if (enable_statistics) num_leaf_tests++;
349 
350  const BVNode<BV>& node = model1->getBV(b1);
351  int primitive_id = node.primitiveId();
352 
353  const Triangle& tri_id = tri_indices[primitive_id];
354  const TriangleP tri(vertices[tri_id[0]], vertices[tri_id[1]],
355  vertices[tri_id[2]]);
356 
357  Vec3f p1, p2, normal;
358  const FCL_REAL distance = internal::ShapeShapeDistance<TriangleP, S>(
359  &tri, tf1, &model2, tf2, nsolver, request.enable_signed_distance, p1, p2,
360  normal);
361 
362  result.update(distance, model1, &model2, primitive_id, DistanceResult::NONE,
363  p1, p2, normal);
364 }
365 
366 template <typename BV, typename S>
367 static inline void distancePreprocessOrientedNode(
368  const BVHModel<BV>* model1, Vec3f* vertices, Triangle* tri_indices,
369  int init_tri_id, const S& model2, const Transform3f& tf1,
370  const Transform3f& tf2, const GJKSolver* nsolver,
371  const DistanceRequest& request, DistanceResult& result) {
372  const Triangle& tri_id = tri_indices[init_tri_id];
373  const TriangleP tri(vertices[tri_id[0]], vertices[tri_id[1]],
374  vertices[tri_id[2]]);
375 
376  Vec3f p1, p2, normal;
377  const FCL_REAL distance = internal::ShapeShapeDistance<TriangleP, S>(
378  &tri, tf1, &model2, tf2, nsolver, request.enable_signed_distance, p1, p2,
379  normal);
380  result.update(distance, model1, &model2, init_tri_id, DistanceResult::NONE,
381  p1, p2, normal);
382 }
383 
384 } // namespace details
385 
387 
390 template <typename S>
392  : public MeshShapeDistanceTraversalNode<RSS, S> {
393  public:
395  : MeshShapeDistanceTraversalNode<RSS, S>() {}
396 
397  void preprocess() {
398  details::distancePreprocessOrientedNode(
399  this->model1, this->vertices, this->tri_indices, 0, *(this->model2),
400  this->tf1, this->tf2, this->nsolver, this->request, *(this->result));
401  }
402 
403  void postprocess() {}
404 
405  FCL_REAL BVDistanceLowerBound(unsigned int b1, unsigned int /*b2*/) const {
406  if (this->enable_statistics) this->num_bv_tests++;
407  return distance(this->tf1.getRotation(), this->tf1.getTranslation(),
408  this->model2_bv, this->model1->getBV(b1).bv);
409  }
410 
411  void leafComputeDistance(unsigned int b1, unsigned int b2) const {
412  details::meshShapeDistanceOrientedNodeleafComputeDistance(
413  b1, b2, this->model1, *(this->model2), this->vertices,
414  this->tri_indices, this->tf1, this->tf2, this->nsolver,
415  this->enable_statistics, this->num_leaf_tests, this->request,
416  *(this->result));
417  }
418 };
419 
420 template <typename S>
422  : public MeshShapeDistanceTraversalNode<kIOS, S> {
423  public:
425  : MeshShapeDistanceTraversalNode<kIOS, S>() {}
426 
427  void preprocess() {
428  details::distancePreprocessOrientedNode(
429  this->model1, this->vertices, this->tri_indices, 0, *(this->model2),
430  this->tf1, this->tf2, this->nsolver, this->request, *(this->result));
431  }
432 
433  void postprocess() {}
434 
435  FCL_REAL BVDistanceLowerBound(unsigned int b1, unsigned int /*b2*/) const {
436  if (this->enable_statistics) this->num_bv_tests++;
437  return distance(this->tf1.getRotation(), this->tf1.getTranslation(),
438  this->model2_bv, this->model1->getBV(b1).bv);
439  }
440 
441  void leafComputeDistance(unsigned int b1, unsigned int b2) const {
442  details::meshShapeDistanceOrientedNodeleafComputeDistance(
443  b1, b2, this->model1, *(this->model2), this->vertices,
444  this->tri_indices, this->tf1, this->tf2, this->nsolver,
445  this->enable_statistics, this->num_leaf_tests, this->request,
446  *(this->result));
447  }
448 };
449 
450 template <typename S>
452  : public MeshShapeDistanceTraversalNode<OBBRSS, S> {
453  public:
455  : MeshShapeDistanceTraversalNode<OBBRSS, S>() {}
456 
457  void preprocess() {
458  details::distancePreprocessOrientedNode(
459  this->model1, this->vertices, this->tri_indices, 0, *(this->model2),
460  this->tf1, this->tf2, this->nsolver, this->request, *(this->result));
461  }
462 
463  void postprocess() {}
464 
465  FCL_REAL BVDistanceLowerBound(unsigned int b1, unsigned int /*b2*/) const {
466  if (this->enable_statistics) this->num_bv_tests++;
467  return distance(this->tf1.getRotation(), this->tf1.getTranslation(),
468  this->model2_bv, this->model1->getBV(b1).bv);
469  }
470 
471  void leafComputeDistance(unsigned int b1, unsigned int b2) const {
472  details::meshShapeDistanceOrientedNodeleafComputeDistance(
473  b1, b2, this->model1, *(this->model2), this->vertices,
474  this->tri_indices, this->tf1, this->tf2, this->nsolver,
475  this->enable_statistics, this->num_leaf_tests, this->request,
476  *(this->result));
477  }
478 };
479 
481 
482 } // namespace fcl
483 } // namespace hpp
484 
486 
487 #endif
Definition: traversal_node_bvh_shape.h:452
void postprocess()
Definition: traversal_node_bvh_shape.h:463
MeshShapeDistanceTraversalNodeOBBRSS()
Definition: traversal_node_bvh_shape.h:454
FCL_REAL BVDistanceLowerBound(unsigned int b1, unsigned int) const
Definition: traversal_node_bvh_shape.h:465
void leafComputeDistance(unsigned int b1, unsigned int b2) const
Definition: traversal_node_bvh_shape.h:471
void preprocess()
Definition: traversal_node_bvh_shape.h:457
Traversal node for distance between mesh and shape, when mesh BVH is one of the oriented node (RSS,...
Definition: traversal_node_bvh_shape.h:392
void postprocess()
Definition: traversal_node_bvh_shape.h:403
MeshShapeDistanceTraversalNodeRSS()
Definition: traversal_node_bvh_shape.h:394
FCL_REAL BVDistanceLowerBound(unsigned int b1, unsigned int) const
Definition: traversal_node_bvh_shape.h:405
void leafComputeDistance(unsigned int b1, unsigned int b2) const
Definition: traversal_node_bvh_shape.h:411
void preprocess()
Definition: traversal_node_bvh_shape.h:397
Definition: traversal_node_bvh_shape.h:422
FCL_REAL BVDistanceLowerBound(unsigned int b1, unsigned int) const
Definition: traversal_node_bvh_shape.h:435
void leafComputeDistance(unsigned int b1, unsigned int b2) const
Definition: traversal_node_bvh_shape.h:441
MeshShapeDistanceTraversalNodekIOS()
Definition: traversal_node_bvh_shape.h:424
void preprocess()
Definition: traversal_node_bvh_shape.h:427
void postprocess()
Definition: traversal_node_bvh_shape.h:433
FCL_REAL distance(const Matrix3f &R0, const Vec3f &T0, const kIOS &b1, const kIOS &b2, Vec3f *P=NULL, Vec3f *Q=NULL)
Approximate distance between two kIOS bounding volumes.
bool overlap(const Matrix3f &R0, const Vec3f &T0, const AABB &b1, const AABB &b2)
Check collision between two aabbs, b1 is in configuration (R0, T0) and b2 is in identity.
void updateDistanceLowerBoundFromLeaf(const CollisionRequest &, CollisionResult &res, const FCL_REAL &distance, const Vec3f &p0, const Vec3f &p1, const Vec3f &normal)
Definition: collision_data.h:1186
void updateDistanceLowerBoundFromBV(const CollisionRequest &, CollisionResult &res, const FCL_REAL sqrDistLowerBound)
Definition: collision_data.h:1177
Eigen::Matrix< FCL_REAL, 3, 1 > Vec3f
Definition: data_types.h:67
double FCL_REAL
Definition: data_types.h:66
Main namespace.
Definition: broadphase_bruteforce.h:44
static const int NONE
invalid contact primitive information
Definition: collision_data.h:109
static const int NONE
invalid contact primitive information
Definition: collision_data.h:1088