hpp-fcl  3.0.0
HPP fork of FCL -- The Flexible Collision Library
gjk.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  * Copyright (c) 2021-2024, INRIA
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Open Source Robotics Foundation nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
39 #ifndef HPP_FCL_GJK_H
40 #define HPP_FCL_GJK_H
41 
42 #include <vector>
43 
45 
46 namespace hpp {
47 namespace fcl {
48 
49 namespace details {
50 
57  Vec3f w0, w1;
61  };
62 
63  typedef unsigned char vertex_id_t;
64 
74  SimplexV* vertex[4];
77 
78  Simplex() {}
79 
80  void reset() {
81  rank = 0;
82  for (size_t i = 0; i < 4; ++i) vertex[i] = nullptr;
83  }
84  };
85 
95  enum Status {
101  Collision
102  };
103 
104  public:
110 
120  Simplex* simplex; // Pointer to the result of the last run of GJK.
121 
122  private:
123  // max_iteration and tolerance are made private
124  // because they are meant to be set by the `reset` function.
125  size_t max_iterations;
126  FCL_REAL tolerance;
127 
128  SimplexV store_v[4];
129  SimplexV* free_v[4];
130  vertex_id_t nfree;
131  vertex_id_t current;
132  Simplex simplices[2];
133  size_t iterations;
134  size_t iterations_momentum_stop;
135 
136  public:
144  GJK(size_t max_iterations_, FCL_REAL tolerance_)
145  : max_iterations(max_iterations_), tolerance(tolerance_) {
146  HPP_FCL_ASSERT(tolerance_ > 0, "Tolerance must be positive.",
147  std::invalid_argument);
148  initialize();
149  }
150 
154  void reset(size_t max_iterations_, FCL_REAL tolerance_);
155 
158  const MinkowskiDiff& shape, const Vec3f& guess,
159  const support_func_guess_t& supportHint = support_func_guess_t::Zero());
160 
163  inline void getSupport(const Vec3f& d, SimplexV& sv,
164  support_func_guess_t& hint) const {
165  shape->support(d, sv.w0, sv.w1, hint);
166  sv.w = sv.w0 - sv.w1;
167  }
168 
171 
174  inline Simplex* getSimplex() const { return simplex; }
175 
177  bool hasClosestPoints() const { return distance < distance_upper_bound; }
178 
186  Vec3f& w1, Vec3f& normal) const;
187 
190 
195  void setDistanceEarlyBreak(const FCL_REAL& dup) {
196  distance_upper_bound = dup;
197  }
198 
201  bool checkConvergence(const Vec3f& w, const FCL_REAL& rl, FCL_REAL& alpha,
202  const FCL_REAL& omega) const;
203 
205  size_t getNumMaxIterations() const { return max_iterations; }
206 
208  FCL_REAL getTolerance() const { return tolerance; }
209 
211  size_t getNumIterations() const { return iterations; }
212 
216  return iterations_momentum_stop;
217  }
218 
219  private:
223  void initialize();
224 
226  inline void removeVertex(Simplex& simplex);
227 
229  inline void appendVertex(Simplex& simplex, const Vec3f& v,
230  support_func_guess_t& hint);
231 
247  bool projectLineOrigin(const Simplex& current, Simplex& next);
248 
251  bool projectTriangleOrigin(const Simplex& current, Simplex& next);
252 
255  bool projectTetrahedraOrigin(const Simplex& current, Simplex& next);
256 };
257 
264  bool ignore; // If the origin does not project inside the face, we
265  // ignore this face.
266  size_t vertex_id[3]; // Index of vertex in sv_store.
267  SimplexFace* adjacent_faces[3]; // A face has three adjacent faces.
268  SimplexFace* prev_face; // The previous face in the list.
269  SimplexFace* next_face; // The next face in the list.
270  size_t adjacent_edge[3]; // Each face has 3 edges: `0`, `1` and `2`.
271  // The i-th adjacent face is bound (to this face)
272  // along its `adjacent_edge[i]`-th edge
273  // (with 0 <= i <= 2).
274  size_t pass;
275 
276  SimplexFace() : n(Vec3f::Zero()), ignore(false) {};
277  };
278 
284  size_t count;
285  SimplexFaceList() : root(nullptr), count(0) {}
286 
287  void reset() {
288  root = nullptr;
289  count = 0;
290  }
291 
292  void append(SimplexFace* face) {
293  face->prev_face = nullptr;
294  face->next_face = root;
295  if (root != nullptr) root->prev_face = face;
296  root = face;
297  ++count;
298  }
299 
300  void remove(SimplexFace* face) {
301  if (face->next_face != nullptr)
302  face->next_face->prev_face = face->prev_face;
303  if (face->prev_face != nullptr)
304  face->prev_face->next_face = face->next_face;
305  if (face == root) root = face->next_face;
306  --count;
307  }
308  };
309 
312  static inline void bind(SimplexFace* fa, size_t ea, SimplexFace* fb,
313  size_t eb) {
314  assert(ea == 0 || ea == 1 || ea == 2);
315  assert(eb == 0 || eb == 1 || eb == 2);
316  fa->adjacent_edge[ea] = eb;
317  fa->adjacent_faces[ea] = fb;
318  fb->adjacent_edge[eb] = ea;
319  fb->adjacent_faces[eb] = fa;
320  }
321 
323  SimplexFace* current_face; // current face in the horizon
324  SimplexFace* first_face; // first face in the horizon
325  size_t num_faces; // number of faces in the horizon
327  : current_face(nullptr), first_face(nullptr), num_faces(0) {}
328  };
329 
330  enum Status {
331  DidNotRun = -1,
332  Failed = 0,
333  Valid = 1,
334  AccuracyReached = 1 << 1 | Valid,
335  Degenerated = 1 << 1 | Failed,
336  NonConvex = 2 << 1 | Failed,
337  InvalidHull = 3 << 1 | Failed,
338  OutOfFaces = 4 << 1 | Failed,
339  OutOfVertices = 5 << 1 | Failed,
340  FallBack = 6 << 1 | Failed
341  };
342 
343  public:
350 
351  private:
352  // max_iteration and tolerance are made private
353  // because they are meant to be set by the `reset` function.
354  size_t max_iterations;
355  FCL_REAL tolerance;
356 
357  std::vector<SimplexVertex> sv_store;
358  std::vector<SimplexFace> fc_store;
359  SimplexFaceList hull, stock;
360  size_t num_vertices; // number of vertices in polytpoe constructed by EPA
361  size_t iterations;
362 
363  public:
364  EPA(size_t max_iterations_, FCL_REAL tolerance_)
365  : max_iterations(max_iterations_), tolerance(tolerance_) {
366  initialize();
367  }
368 
371  EPA(const EPA& other)
372  : max_iterations(other.max_iterations),
373  tolerance(other.tolerance),
374  sv_store(other.sv_store),
375  fc_store(other.fc_store) {
376  initialize();
377  }
378 
380  size_t getNumMaxIterations() const { return max_iterations; }
381 
383  size_t getNumMaxVertices() const { return sv_store.size(); }
384 
386  size_t getNumMaxFaces() const { return fc_store.size(); }
387 
389  FCL_REAL getTolerance() const { return tolerance; }
390 
392  size_t getNumIterations() const { return iterations; }
393 
395  size_t getNumVertices() const { return num_vertices; }
396 
398  size_t getNumFaces() const { return hull.count; }
399 
408  void reset(size_t max_iterations, FCL_REAL tolerance);
409 
413  Status evaluate(GJK& gjk, const Vec3f& guess);
414 
423  Vec3f& w1, Vec3f& normal) const;
424 
425  private:
429  void initialize();
430 
431  bool getEdgeDist(SimplexFace* face, const SimplexVertex& a,
432  const SimplexVertex& b, FCL_REAL& dist);
433 
437  SimplexFace* newFace(size_t id_a, size_t id_b, size_t id_vertex,
438  bool force = false);
439 
441  SimplexFace* findClosestFace();
442 
444  bool expand(size_t pass, const SimplexVertex& w, SimplexFace* f, size_t e,
445  SimplexHorizon& horizon);
446 
447  // @brief Use this function to debug expand if needed.
448  // void PrintExpandLooping(const SimplexFace* f, const SimplexVertex& w);
449 };
450 
451 } // namespace details
452 
453 } // namespace fcl
454 
455 } // namespace hpp
456 
457 #endif
#define HPP_FCL_DLLAPI
Definition: config.hh:88
#define HPP_FCL_ASSERT(check, message, exception)
Definition: fwd.hh:82
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.
GJKVariant
Variant to use for the GJK algorithm.
Definition: data_types.h:88
Eigen::Matrix< FCL_REAL, 3, 1 > Vec3f
Definition: data_types.h:67
GJKConvergenceCriterionType
Wether the convergence criterion is scaled on the norm of the solution or not.
Definition: data_types.h:98
GJKConvergenceCriterion
Which convergence criterion is used to stop the algorithm (when the shapes are not in collision)....
Definition: data_types.h:94
double FCL_REAL
Definition: data_types.h:66
Eigen::Vector2i support_func_guess_t
Definition: data_types.h:77
Main namespace.
Definition: broadphase_bruteforce.h:44
The simplex list of EPA is a linked list of faces. Note: EPA's linked list does not own any memory....
Definition: gjk.h:282
size_t count
Definition: gjk.h:284
SimplexFace * root
Definition: gjk.h:283
void append(SimplexFace *face)
Definition: gjk.h:292
void reset()
Definition: gjk.h:287
void remove(SimplexFace *face)
Definition: gjk.h:300
SimplexFaceList()
Definition: gjk.h:285
SimplexFace * adjacent_faces[3]
Definition: gjk.h:267
SimplexFace()
Definition: gjk.h:276
bool ignore
Definition: gjk.h:264
SimplexFace * next_face
Definition: gjk.h:269
SimplexFace * prev_face
Definition: gjk.h:268
Vec3f n
Definition: gjk.h:262
size_t pass
Definition: gjk.h:274
size_t adjacent_edge[3]
Definition: gjk.h:270
FCL_REAL d
Definition: gjk.h:263
size_t num_faces
Definition: gjk.h:325
SimplexFace * current_face
Definition: gjk.h:323
SimplexFace * first_face
Definition: gjk.h:324
SimplexHorizon()
Definition: gjk.h:326
class for EPA algorithm
Definition: gjk.h:259
size_t getNumMaxFaces() const
Get the max number of faces of EPA.
Definition: gjk.h:386
Status status
Definition: gjk.h:344
GJK::SimplexV SimplexVertex
Definition: gjk.h:260
size_t getNumVertices() const
Get the number of vertices in the polytope of the last run of EPA.
Definition: gjk.h:395
SimplexFace * closest_face
Definition: gjk.h:349
FCL_REAL getTolerance() const
Get the tolerance of EPA.
Definition: gjk.h:389
void getWitnessPointsAndNormal(const MinkowskiDiff &shape, Vec3f &w0, Vec3f &w1, Vec3f &normal) const
Vec3f normal
Definition: gjk.h:346
size_t getNumFaces() const
Get the number of faces in the polytope of the last run of EPA.
Definition: gjk.h:398
size_t getNumMaxIterations() const
Get the max number of iterations of EPA.
Definition: gjk.h:380
EPA(const EPA &other)
Copy constructor of EPA. Mostly needed for the copy constructor of GJKSolver.
Definition: gjk.h:371
support_func_guess_t support_hint
Definition: gjk.h:347
Status
Definition: gjk.h:330
size_t getNumMaxVertices() const
Get the max number of vertices of EPA.
Definition: gjk.h:383
static void bind(SimplexFace *fa, size_t ea, SimplexFace *fb, size_t eb)
We bind the face fa along its edge ea to the face fb along its edge fb.
Definition: gjk.h:312
Status evaluate(GJK &gjk, const Vec3f &guess)
EPA(size_t max_iterations_, FCL_REAL tolerance_)
Definition: gjk.h:364
FCL_REAL depth
Definition: gjk.h:348
size_t getNumIterations() const
Get the number of iterations of the last run of EPA.
Definition: gjk.h:392
void reset(size_t max_iterations, FCL_REAL tolerance)
resets the EPA algorithm, preparing it for a new run. It potentially reallocates memory for the verti...
GJK::Simplex result
Definition: gjk.h:345
Vec3f w1
Definition: gjk.h:57
Vec3f w0
support vector for shape 0 and 1.
Definition: gjk.h:57
Vec3f w
support vector (i.e., the furthest point on the shape along the support direction)
Definition: gjk.h:60
A simplex is a set of up to 4 vertices. Its rank is the number of vertices it contains.
Definition: gjk.h:72
vertex_id_t rank
size of simplex (number of vertices)
Definition: gjk.h:76
Simplex()
Definition: gjk.h:78
void reset()
Definition: gjk.h:80
class for GJK algorithm
Definition: gjk.h:54
size_t getNumMaxIterations() const
Get the max number of iterations of GJK.
Definition: gjk.h:205
Simplex * getSimplex() const
get the underlying simplex using in GJK, can be used for cache in next iteration
Definition: gjk.h:174
void setDistanceEarlyBreak(const FCL_REAL &dup)
Distance threshold for early break. GJK stops when it proved the distance is more than this threshold...
Definition: gjk.h:195
support_func_guess_t support_hint
Definition: gjk.h:113
FCL_REAL distance_upper_bound
Definition: gjk.h:105
MinkowskiDiff const * shape
Definition: gjk.h:111
void getWitnessPointsAndNormal(const MinkowskiDiff &shape, Vec3f &w0, Vec3f &w1, Vec3f &normal) const
size_t getNumIterationsMomentumStopped() const
Get GJK number of iterations before momentum stops. Only usefull if the Nesterov or Polyak accelerati...
Definition: gjk.h:215
FCL_REAL getTolerance() const
Get the tolerance of GJK.
Definition: gjk.h:208
Simplex * simplex
Definition: gjk.h:120
Status
Status of the GJK algorithm: DidNotRun: GJK has not been run. Failed: GJK did not converge (it exceed...
Definition: gjk.h:95
@ CollisionWithPenetrationInformation
Definition: gjk.h:100
@ DidNotRun
Definition: gjk.h:96
@ NoCollisionEarlyStopped
Definition: gjk.h:98
@ Failed
Definition: gjk.h:97
@ NoCollision
Definition: gjk.h:99
bool checkConvergence(const Vec3f &w, const FCL_REAL &rl, FCL_REAL &alpha, const FCL_REAL &omega) const
Convergence check used to stop GJK when shapes are not in collision.
GJK(size_t max_iterations_, FCL_REAL tolerance_)
Definition: gjk.h:144
GJKConvergenceCriterion convergence_criterion
Definition: gjk.h:108
void reset(size_t max_iterations_, FCL_REAL tolerance_)
resets the GJK algorithm, preparing it for a new run. Other than the maximum number of iterations and...
GJKConvergenceCriterionType convergence_criterion_type
Definition: gjk.h:109
FCL_REAL distance
The distance between the two shapes, computed by GJK. If the distance is below GJK's threshold,...
Definition: gjk.h:119
Vec3f ray
Definition: gjk.h:112
Status evaluate(const MinkowskiDiff &shape, const Vec3f &guess, const support_func_guess_t &supportHint=support_func_guess_t::Zero())
GJK algorithm, given the initial value guess.
GJKVariant gjk_variant
Definition: gjk.h:107
unsigned char vertex_id_t
Definition: gjk.h:63
Vec3f getGuessFromSimplex() const
get the guess from current simplex
size_t getNumIterations() const
Get the number of iterations of the last run of GJK.
Definition: gjk.h:211
bool encloseOrigin()
whether the simplex enclose the origin
void getSupport(const Vec3f &d, SimplexV &sv, support_func_guess_t &hint) const
apply the support function along a direction, the result is return in sv
Definition: gjk.h:163
bool hasClosestPoints() const
Tells whether the closest points are available.
Definition: gjk.h:177
Status status
Definition: gjk.h:106
Minkowski difference class of two shapes.
Definition: minkowski_difference.h:54
void support(const Vec3f &dir, Vec3f &supp0, Vec3f &supp1, support_func_guess_t &hint) const
Support function for the pair of shapes. This method assumes set has already been called.
Definition: minkowski_difference.h:175
bool initialize(MeshCollisionTraversalNode< BV, RelativeTransformationIsIdentity > &node, BVHModel< BV > &model1, Transform3f &tf1, BVHModel< BV > &model2, Transform3f &tf2, CollisionResult &result, bool use_refit=false, bool refit_bottomup=false)
Initialize traversal node for collision between two meshes, given the current transforms.
Definition: traversal_node_setup.h:468