FCL  0.6.0
Flexible Collision Library
continuous_collision-inl.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2013-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_CONTINUOUS_COLLISION_INL_H
39 #define FCL_CONTINUOUS_COLLISION_INL_H
40 
41 #include "fcl/narrowphase/continuous_collision.h"
42 
43 #include "fcl/math/motion/translation_motion.h"
44 #include "fcl/math/motion/interp_motion.h"
45 #include "fcl/math/motion/screw_motion.h"
46 #include "fcl/math/motion/spline_motion.h"
47 #include "fcl/narrowphase/collision.h"
48 #include "fcl/narrowphase/collision_result.h"
49 #include "fcl/narrowphase/detail/traversal/collision_node.h"
50 
51 namespace fcl
52 {
53 
54 //==============================================================================
55 extern template
56 double continuousCollide(
57  const CollisionGeometry<double>* o1,
58  const MotionBase<double>* motion1,
59  const CollisionGeometry<double>* o2,
60  const MotionBase<double>* motion2,
61  const ContinuousCollisionRequest<double>& request,
62  ContinuousCollisionResult<double>& result);
63 
64 //==============================================================================
65 extern template
66 double continuousCollide(
67  const CollisionGeometry<double>* o1,
68  const Transform3<double>& tf1_beg,
69  const Transform3<double>& tf1_end,
70  const CollisionGeometry<double>* o2,
71  const Transform3<double>& tf2_beg,
72  const Transform3<double>& tf2_end,
73  const ContinuousCollisionRequest<double>& request,
74  ContinuousCollisionResult<double>& result);
75 
76 //==============================================================================
77 extern template
78 double continuousCollide(
79  const CollisionObject<double>* o1,
80  const Transform3<double>& tf1_end,
81  const CollisionObject<double>* o2,
82  const Transform3<double>& tf2_end,
83  const ContinuousCollisionRequest<double>& request,
84  ContinuousCollisionResult<double>& result);
85 
86 //==============================================================================
87 extern template
88 double collide(
89  const ContinuousCollisionObject<double>* o1,
90  const ContinuousCollisionObject<double>* o2,
91  const ContinuousCollisionRequest<double>& request,
92  ContinuousCollisionResult<double>& result);
93 
94 //==============================================================================
95 template<typename GJKSolver>
96 detail::ConservativeAdvancementFunctionMatrix<GJKSolver>&
97 getConservativeAdvancementFunctionLookTable()
98 {
99  static detail::ConservativeAdvancementFunctionMatrix<GJKSolver> table;
100  return table;
101 }
102 
103 //==============================================================================
104 template <typename S>
105 MotionBasePtr<S> getMotionBase(
106  const Transform3<S>& tf_beg,
107  const Transform3<S>& tf_end,
108  CCDMotionType motion_type)
109 {
110  switch(motion_type)
111  {
112  case CCDM_TRANS:
113  return MotionBasePtr<S>(new TranslationMotion<S>(tf_beg, tf_end));
114  break;
115  case CCDM_LINEAR:
116  return MotionBasePtr<S>(new InterpMotion<S>(tf_beg, tf_end));
117  break;
118  case CCDM_SCREW:
119  return MotionBasePtr<S>(new ScrewMotion<S>(tf_beg, tf_end));
120  break;
121  case CCDM_SPLINE:
122  return MotionBasePtr<S>(new SplineMotion<S>(tf_beg, tf_end));
123  break;
124  default:
125  return MotionBasePtr<S>();
126  }
127 }
128 
129 //==============================================================================
130 template <typename S>
131 S continuousCollideNaive(
132  const CollisionGeometry<S>* o1,
133  const MotionBase<S>* motion1,
134  const CollisionGeometry<S>* o2,
135  const MotionBase<S>* motion2,
136  const ContinuousCollisionRequest<S>& request,
137  ContinuousCollisionResult<S>& result)
138 {
139  std::size_t n_iter = std::min(request.num_max_iterations, (std::size_t)ceil(1 / request.toc_err));
140  Transform3<S> cur_tf1, cur_tf2;
141  for(std::size_t i = 0; i < n_iter; ++i)
142  {
143  S t = i / (S) (n_iter - 1);
144  motion1->integrate(t);
145  motion2->integrate(t);
146 
147  motion1->getCurrentTransform(cur_tf1);
148  motion2->getCurrentTransform(cur_tf2);
149 
150  CollisionRequest<S> c_request;
151  CollisionResult<S> c_result;
152 
153  if(collide(o1, cur_tf1, o2, cur_tf2, c_request, c_result))
154  {
155  result.is_collide = true;
156  result.time_of_contact = t;
157  result.contact_tf1 = cur_tf1;
158  result.contact_tf2 = cur_tf2;
159  return t;
160  }
161  }
162 
163  result.is_collide = false;
164  result.time_of_contact = S(1);
165  return result.time_of_contact;
166 }
167 
168 namespace detail
169 {
170 
171 //==============================================================================
172 template<typename BV>
173 typename BV::S continuousCollideBVHPolynomial(
174  const CollisionGeometry<typename BV::S>* o1_,
175  const TranslationMotion<typename BV::S>* motion1,
176  const CollisionGeometry<typename BV::S>* o2_,
177  const TranslationMotion<typename BV::S>* motion2,
178  const ContinuousCollisionRequest<typename BV::S>& request,
179  ContinuousCollisionResult<typename BV::S>& result)
180 {
181  using S = typename BV::S;
182 
183  const BVHModel<BV>* o1__ = static_cast<const BVHModel<BV>*>(o1_);
184  const BVHModel<BV>* o2__ = static_cast<const BVHModel<BV>*>(o2_);
185 
186  // ugly, but lets do it now.
187  BVHModel<BV>* o1 = const_cast<BVHModel<BV>*>(o1__);
188  BVHModel<BV>* o2 = const_cast<BVHModel<BV>*>(o2__);
189  std::vector<Vector3<S>> new_v1(o1->num_vertices);
190  std::vector<Vector3<S>> new_v2(o2->num_vertices);
191 
192  for(std::size_t i = 0; i < new_v1.size(); ++i)
193  new_v1[i] = o1->vertices[i] + motion1->getVelocity();
194  for(std::size_t i = 0; i < new_v2.size(); ++i)
195  new_v2[i] = o2->vertices[i] + motion2->getVelocity();
196 
197  o1->beginUpdateModel();
198  o1->updateSubModel(new_v1);
199  o1->endUpdateModel(true, true);
200 
201  o2->beginUpdateModel();
202  o2->updateSubModel(new_v2);
203  o2->endUpdateModel(true, true);
204 
205  MeshContinuousCollisionTraversalNode<BV> node;
206  CollisionRequest<S> c_request;
207 
208  motion1->integrate(0);
209  motion2->integrate(0);
210  Transform3<S> tf1;
211  Transform3<S> tf2;
212  motion1->getCurrentTransform(tf1);
213  motion2->getCurrentTransform(tf2);
214  if(!initialize<BV>(node, *o1, tf1, *o2, tf2, c_request))
215  return -1.0;
216 
217  collide(&node);
218 
219  result.is_collide = (node.pairs.size() > 0);
220  result.time_of_contact = node.time_of_contact;
221 
222  if(result.is_collide)
223  {
224  motion1->integrate(node.time_of_contact);
225  motion2->integrate(node.time_of_contact);
226  motion1->getCurrentTransform(tf1);
227  motion2->getCurrentTransform(tf2);
228  result.contact_tf1 = tf1;
229  result.contact_tf2 = tf2;
230  }
231 
232  return result.time_of_contact;
233 }
234 
235 } // namespace detail
236 
237 //==============================================================================
238 template <typename S>
239 S continuousCollideBVHPolynomial(
240  const CollisionGeometry<S>* o1,
241  const TranslationMotion<S>* motion1,
242  const CollisionGeometry<S>* o2,
243  const TranslationMotion<S>* motion2,
244  const ContinuousCollisionRequest<S>& request,
245  ContinuousCollisionResult<S>& result)
246 {
247  switch(o1->getNodeType())
248  {
249  case BV_AABB:
250  if(o2->getNodeType() == BV_AABB)
251  return detail::continuousCollideBVHPolynomial<AABB<S>>(o1, motion1, o2, motion2, request, result);
252  break;
253  case BV_OBB:
254  if(o2->getNodeType() == BV_OBB)
255  return detail::continuousCollideBVHPolynomial<OBB<S>>(o1, motion1, o2, motion2, request, result);
256  break;
257  case BV_RSS:
258  if(o2->getNodeType() == BV_RSS)
259  return detail::continuousCollideBVHPolynomial<RSS<S>>(o1, motion1, o2, motion2, request, result);
260  break;
261  case BV_kIOS:
262  if(o2->getNodeType() == BV_kIOS)
263  return detail::continuousCollideBVHPolynomial<kIOS<S>>(o1, motion1, o2, motion2, request, result);
264  break;
265  case BV_OBBRSS:
266  if(o2->getNodeType() == BV_OBBRSS)
267  return detail::continuousCollideBVHPolynomial<OBBRSS<S>>(o1, motion1, o2, motion2, request, result);
268  break;
269  case BV_KDOP16:
270  if(o2->getNodeType() == BV_KDOP16)
271  return detail::continuousCollideBVHPolynomial<KDOP<S, 16> >(o1, motion1, o2, motion2, request, result);
272  break;
273  case BV_KDOP18:
274  if(o2->getNodeType() == BV_KDOP18)
275  return detail::continuousCollideBVHPolynomial<KDOP<S, 18> >(o1, motion1, o2, motion2, request, result);
276  break;
277  case BV_KDOP24:
278  if(o2->getNodeType() == BV_KDOP24)
279  return detail::continuousCollideBVHPolynomial<KDOP<S, 24> >(o1, motion1, o2, motion2, request, result);
280  break;
281  default:
282  ;
283  }
284 
285  std::cerr << "Warning: BV type not supported by polynomial solver CCD" << std::endl;
286 
287  return -1;
288 }
289 
290 namespace detail
291 {
292 
293 //==============================================================================
294 template<typename NarrowPhaseSolver>
295 typename NarrowPhaseSolver::S continuousCollideConservativeAdvancement(
296  const CollisionGeometry<typename NarrowPhaseSolver::S>* o1,
297  const MotionBase<typename NarrowPhaseSolver::S>* motion1,
298  const CollisionGeometry<typename NarrowPhaseSolver::S>* o2,
299  const MotionBase<typename NarrowPhaseSolver::S>* motion2,
300  const NarrowPhaseSolver* nsolver_,
301  const ContinuousCollisionRequest<typename NarrowPhaseSolver::S>& request,
302  ContinuousCollisionResult<typename NarrowPhaseSolver::S>& result)
303 {
304  using S = typename NarrowPhaseSolver::S;
305 
306  const NarrowPhaseSolver* nsolver = nsolver_;
307  if(!nsolver_)
308  nsolver = new NarrowPhaseSolver();
309 
310  const auto& looktable = getConservativeAdvancementFunctionLookTable<NarrowPhaseSolver>();
311 
312  NODE_TYPE node_type1 = o1->getNodeType();
313  NODE_TYPE node_type2 = o2->getNodeType();
314 
315  S res = -1;
316 
317  if(!looktable.conservative_advancement_matrix[node_type1][node_type2])
318  {
319  std::cerr << "Warning: collision function between node type " << node_type1 << " and node type " << node_type2 << " is not supported"<< std::endl;
320  }
321  else
322  {
323  res = looktable.conservative_advancement_matrix[node_type1][node_type2](o1, motion1, o2, motion2, nsolver, request, result);
324  }
325 
326  if(!nsolver_)
327  delete nsolver;
328 
329  if(result.is_collide)
330  {
331  motion1->integrate(result.time_of_contact);
332  motion2->integrate(result.time_of_contact);
333 
334  Transform3<S> tf1;
335  Transform3<S> tf2;
336  motion1->getCurrentTransform(tf1);
337  motion2->getCurrentTransform(tf2);
338  result.contact_tf1 = tf1;
339  result.contact_tf2 = tf2;
340  }
341 
342  return res;
343 }
344 
345 } // namespace detail
346 
347 template <typename S>
348 S continuousCollideConservativeAdvancement(
349  const CollisionGeometry<S>* o1,
350  const MotionBase<S>* motion1,
351  const CollisionGeometry<S>* o2,
352  const MotionBase<S>* motion2,
353  const ContinuousCollisionRequest<S>& request,
354  ContinuousCollisionResult<S>& result)
355 {
356  switch(request.gjk_solver_type)
357  {
358  case GST_LIBCCD:
359  {
360  detail::GJKSolver_libccd<S> solver;
361  return detail::continuousCollideConservativeAdvancement(o1, motion1, o2, motion2, &solver, request, result);
362  }
363  case GST_INDEP:
364  {
365  detail::GJKSolver_indep<S> solver;
366  return detail::continuousCollideConservativeAdvancement(o1, motion1, o2, motion2, &solver, request, result);
367  }
368  default:
369  return -1;
370  }
371 }
372 
373 //==============================================================================
374 template <typename S>
375 S continuousCollide(
376  const CollisionGeometry<S>* o1,
377  const MotionBase<S>* motion1,
378  const CollisionGeometry<S>* o2,
379  const MotionBase<S>* motion2,
380  const ContinuousCollisionRequest<S>& request,
382 {
383  switch(request.ccd_solver_type)
384  {
385  case CCDC_NAIVE:
386  return continuousCollideNaive(o1, motion1,
387  o2, motion2,
388  request,
389  result);
390  break;
391  case CCDC_CONSERVATIVE_ADVANCEMENT:
392  return continuousCollideConservativeAdvancement(o1, motion1,
393  o2, motion2,
394  request,
395  result);
396  break;
397  case CCDC_RAY_SHOOTING:
398  if(o1->getObjectType() == OT_GEOM && o2->getObjectType() == OT_GEOM && request.ccd_motion_type == CCDM_TRANS)
399  {
400 
401  }
402  else
403  std::cerr << "Warning! Invalid continuous collision setting" << std::endl;
404  break;
405  case CCDC_POLYNOMIAL_SOLVER:
406  if(o1->getObjectType() == OT_BVH && o2->getObjectType() == OT_BVH && request.ccd_motion_type == CCDM_TRANS)
407  {
408  return continuousCollideBVHPolynomial(o1, (const TranslationMotion<S>*)motion1,
409  o2, (const TranslationMotion<S>*)motion2,
410  request, result);
411  }
412  else
413  std::cerr << "Warning! Invalid continuous collision checking" << std::endl;
414  break;
415  default:
416  std::cerr << "Warning! Invalid continuous collision setting" << std::endl;
417  }
418 
419  return -1;
420 }
421 
422 //==============================================================================
423 template <typename S>
424 S continuousCollide(
425  const CollisionGeometry<S>* o1,
426  const Transform3<S>& tf1_beg,
427  const Transform3<S>& tf1_end,
428  const CollisionGeometry<S>* o2,
429  const Transform3<S>& tf2_beg,
430  const Transform3<S>& tf2_end,
431  const ContinuousCollisionRequest<S>& request,
433 {
434  MotionBasePtr<S> motion1 = getMotionBase(tf1_beg, tf1_end, request.ccd_motion_type);
435  MotionBasePtr<S> motion2 = getMotionBase(tf2_beg, tf2_end, request.ccd_motion_type);
436 
437  return continuousCollide(o1, motion1.get(), o2, motion2.get(), request, result);
438 }
439 
440 //==============================================================================
441 template <typename S>
442 S continuousCollide(
443  const CollisionObject<S>* o1,
444  const Transform3<S>& tf1_end,
445  const CollisionObject<S>* o2,
446  const Transform3<S>& tf2_end,
447  const ContinuousCollisionRequest<S>& request,
449 {
450  return continuousCollide(o1->collisionGeometry().get(), o1->getTransform(), tf1_end,
451  o2->collisionGeometry().get(), o2->getTransform(), tf2_end,
452  request, result);
453 }
454 
455 //==============================================================================
456 template <typename S>
457 S collide(
460  const ContinuousCollisionRequest<S>& request,
462 {
463  return continuousCollide(o1->collisionGeometry().get(), o1->getMotion(),
464  o2->collisionGeometry().get(), o2->getMotion(),
465  request, result);
466 }
467 
468 } // namespace fcl
469 
470 #endif
virtual OBJECT_TYPE getObjectType() const
get the type of the object
Definition: collision_geometry-inl.h:72
NODE_TYPE
traversal node type: bounding volume (AABB, OBB, RSS, kIOS, OBBRSS, KDOP16, KDOP18, kDOP24), basic shape (box, sphere, ellipsoid, capsule, cone, cylinder, convex, plane, halfspace, triangle), and octree
Definition: collision_geometry.h:54
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
Definition: bv_motion_bound_visitor.h:57
const std::shared_ptr< const CollisionGeometry< S > > & collisionGeometry() const
get geometry from the object instance
Definition: continuous_collision_object-inl.h:170
the object for continuous collision or distance computation, contains the geometry and the motion inf...
Definition: continuous_collision_object.h:51
The geometry for the object for collision or distance computation.
Definition: collision_geometry.h:59
Definition: continuous_collision_request.h:51
CCDMotionType ccd_motion_type
ccd motion type
Definition: continuous_collision_request.h:60
Definition: bv_motion_bound_visitor.h:45
const Transform3< S > & getTransform() const
get object&#39;s transform
Definition: collision_object-inl.h:170
continuous collision result
Definition: continuous_collision_result.h:48
const std::shared_ptr< const CollisionGeometry< S > > & collisionGeometry() const
get geometry from the object instance
Definition: collision_object-inl.h:243
the object for collision or distance computation, contains the geometry and the transform information...
Definition: collision_object.h:51
MotionBase< S > * getMotion() const
get motion from the object instance
Definition: continuous_collision_object-inl.h:154
CCDSolverType ccd_solver_type
ccd solver type
Definition: continuous_collision_request.h:66