GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/hpp/fcl/narrowphase/gjk.h Lines: 56 63 88.9 %
Date: 2024-02-09 12:57:42 Branches: 22 46 47.8 %

Line Branch Exec Source
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
36
/** \author Jia Pan */
37
38
#ifndef HPP_FCL_GJK_H
39
#define HPP_FCL_GJK_H
40
41
#include <vector>
42
43
#include <hpp/fcl/shape/geometric_shapes.h>
44
#include <hpp/fcl/math/transform.h>
45
46
namespace hpp {
47
namespace fcl {
48
49
namespace details {
50
51
/// @brief the support function for shape
52
/// \param hint use to initialize the search when shape is a ConvexBase object.
53
Vec3f getSupport(const ShapeBase* shape, const Vec3f& dir, bool dirIsNormalized,
54
                 int& hint);
55
56
/// @brief Minkowski difference class of two shapes
57
///
58
/// @note The Minkowski difference is expressed in the frame of the first shape.
59
struct HPP_FCL_DLLAPI MinkowskiDiff {
60
  typedef Eigen::Array<FCL_REAL, 1, 2> Array2d;
61
62
  /// @brief points to two shapes
63
  const ShapeBase* shapes[2];
64
65
  struct ShapeData {
66
    std::vector<int8_t> visited;
67
  };
68
69
  /// @brief Store temporary data for the computation of the support point for
70
  /// each shape.
71
  ShapeData data[2];
72
73
  /// @brief rotation from shape1 to shape0
74
  /// such that @f$ p_in_0 = oR1 * p_in_1 + ot1 @f$.
75
  Matrix3f oR1;
76
77
  /// @brief translation from shape1 to shape0
78
  /// such that @f$ p_in_0 = oR1 * p_in_1 + ot1 @f$.
79
  Vec3f ot1;
80
81
  /// @brief The radius of the sphere swepted volume.
82
  /// The 2 values correspond to the inflation of shape 0 and shape 1/
83
  /// These inflation values are used for Sphere and Capsule.
84
  Array2d inflation;
85
86
  /// @brief Number of points in a Convex object from which using a logarithmic
87
  /// support function is faster than a linear one.
88
  /// It defaults to 32.
89
  /// \note It must set before the call to \ref set.
90
  int linear_log_convex_threshold;
91
92
  /// @brief Wether or not to use the normalize heuristic in the GJK Nesterov
93
  /// acceleration. This setting is only applied if the Nesterov acceleration in
94
  /// the GJK class is active.
95
  bool normalize_support_direction;
96
97
  typedef void (*GetSupportFunction)(const MinkowskiDiff& minkowskiDiff,
98
                                     const Vec3f& dir, bool dirIsNormalized,
99
                                     Vec3f& support0, Vec3f& support1,
100
                                     support_func_guess_t& hint,
101
                                     ShapeData data[2]);
102
  GetSupportFunction getSupportFunc;
103
104
29982507
  MinkowskiDiff()
105
29982507
      : linear_log_convex_threshold(32),
106
        normalize_support_direction(false),
107



89947521
        getSupportFunc(NULL) {}
108
109
  /// Set the two shapes,
110
  /// assuming the relative transformation between them is identity.
111
  void set(const ShapeBase* shape0, const ShapeBase* shape1);
112
113
  /// Set the two shapes, with a relative transformation.
114
  void set(const ShapeBase* shape0, const ShapeBase* shape1,
115
           const Transform3f& tf0, const Transform3f& tf1);
116
117
  /// @brief support function for shape0
118
  inline Vec3f support0(const Vec3f& d, bool dIsNormalized, int& hint) const {
119
    return getSupport(shapes[0], d, dIsNormalized, hint);
120
  }
121
122
  /// @brief support function for shape1
123
  inline Vec3f support1(const Vec3f& d, bool dIsNormalized, int& hint) const {
124
    return oR1 *
125
               getSupport(shapes[1], oR1.transpose() * d, dIsNormalized, hint) +
126
           ot1;
127
  }
128
129
  /// @brief support function for the pair of shapes
130
98672364
  inline void support(const Vec3f& d, bool dIsNormalized, Vec3f& supp0,
131
                      Vec3f& supp1, support_func_guess_t& hint) const {
132
98672364
    assert(getSupportFunc != NULL);
133
98672364
    getSupportFunc(*this, d, dIsNormalized, supp0, supp1, hint,
134
98672364
                   const_cast<ShapeData*>(data));
135
98672364
  }
136
};
137
138
/// @brief class for GJK algorithm
139
///
140
/// @note The computations are performed in the frame of the first shape.
141
struct HPP_FCL_DLLAPI GJK {
142
  struct HPP_FCL_DLLAPI SimplexV {
143
    /// @brief support vector for shape 0 and 1.
144
    Vec3f w0, w1;
145
    /// @brief support vector (i.e., the furthest point on the shape along the
146
    /// support direction)
147
    Vec3f w;
148
  };
149
150
  typedef unsigned char vertex_id_t;
151
152
  struct HPP_FCL_DLLAPI Simplex {
153
    /// @brief simplex vertex
154
    SimplexV* vertex[4];
155
    /// @brief size of simplex (number of vertices)
156
    vertex_id_t rank;
157
158
59965658
    Simplex() {}
159
  };
160
161
  /// @brief Status of the GJK algorithm:
162
  /// Valid: GJK converged and the shapes are not in collision.
163
  /// Inside: GJK converged and the shapes are in collision.
164
  /// Failed: GJK did not converge.
165
  enum Status { Valid, Inside, Failed, EarlyStopped };
166
167
  MinkowskiDiff const* shape;
168
  Vec3f ray;
169
  GJKVariant gjk_variant;
170
  GJKConvergenceCriterion convergence_criterion;
171
  GJKConvergenceCriterionType convergence_criterion_type;
172
  support_func_guess_t support_hint;
173
  /// The distance computed by GJK. The possible values are
174
  /// - \f$ d = - R - 1 \f$ when a collision is detected and GJK
175
  ///   cannot compute penetration informations.
176
  /// - \f$ - R \le d \le 0 \f$ when a collision is detected and GJK can
177
  ///   compute penetration informations.
178
  /// - \f$ 0 < d \le d_{ub} \f$ when there is no collision and GJK can compute
179
  ///   the closest points.
180
  /// - \f$ d_{ub} < d \f$ when there is no collision and GJK cannot compute the
181
  ///   closest points.
182
  ///
183
  /// where \f$ d \f$ is the GJK::distance, \f$ R \f$ is the sum of the \c shape
184
  /// MinkowskiDiff::inflation and \f$ d_{ub} \f$ is the
185
  /// GJK::distance_upper_bound.
186
  FCL_REAL distance;
187
  Simplex simplices[2];
188
189
  /// \param max_iterations_ number of iteration before GJK returns failure.
190
  /// \param tolerance_ precision of the algorithm.
191
  ///
192
  /// The tolerance argument is useful for continuous shapes and for polyhedron
193
  /// with some vertices closer than this threshold.
194
  ///
195
  /// Suggested values are 100 iterations and a tolerance of 1e-6.
196
29982542
  GJK(unsigned int max_iterations_, FCL_REAL tolerance_)
197

209877794
      : max_iterations(max_iterations_), tolerance(tolerance_) {
198
29982542
    initialize();
199
29982542
  }
200
201
  void initialize();
202
203
  /// @brief GJK algorithm, given the initial value guess
204
  Status evaluate(
205
      const MinkowskiDiff& shape, const Vec3f& guess,
206
      const support_func_guess_t& supportHint = support_func_guess_t::Zero());
207
208
  /// @brief apply the support function along a direction, the result is return
209
  /// in sv
210
98672364
  inline void getSupport(const Vec3f& d, bool dIsNormalized, SimplexV& sv,
211
                         support_func_guess_t& hint) const {
212
98672364
    shape->support(d, dIsNormalized, sv.w0, sv.w1, hint);
213
98672364
    sv.w = sv.w0 - sv.w1;
214
98672364
  }
215
216
  /// @brief whether the simplex enclose the origin
217
  bool encloseOrigin();
218
219
  /// @brief get the underlying simplex using in GJK, can be used for cache in
220
  /// next iteration
221
574
  inline Simplex* getSimplex() const { return simplex; }
222
223
  /// Tells whether the closest points are available.
224
  bool hasClosestPoints() { return distance < distance_upper_bound; }
225
226
  /// Tells whether the penetration information.
227
  ///
228
  /// In such case, most indepth points and penetration depth can be retrieved
229
  /// from GJK. Calling EPA has an undefined behaviour.
230
6726
  bool hasPenetrationInformation(const MinkowskiDiff& shape) {
231
6726
    return distance > -shape.inflation.sum();
232
  }
233
234
  /// Get the closest points on each object.
235
  /// @return true on success
236
  bool getClosestPoints(const MinkowskiDiff& shape, Vec3f& w0, Vec3f& w1);
237
238
  /// @brief get the guess from current simplex
239
  Vec3f getGuessFromSimplex() const;
240
241
  /// @brief Distance threshold for early break.
242
  /// GJK stops when it proved the distance is more than this threshold.
243
  /// @note The closest points will be erroneous in this case.
244
  ///       If you want the closest points, set this to infinity (the default).
245
29982448
  void setDistanceEarlyBreak(const FCL_REAL& dup) {
246
29982448
    distance_upper_bound = dup;
247
29982448
  }
248
249
  /// @brief Convergence check used to stop GJK when shapes are not in
250
  /// collision.
251
  bool checkConvergence(const Vec3f& w, const FCL_REAL& rl, FCL_REAL& alpha,
252
                        const FCL_REAL& omega);
253
254
  /// @brief Get GJK number of iterations.
255
68000
  inline size_t getIterations() { return iterations; }
256
257
  /// @brief Get GJK tolerance.
258
2
  inline FCL_REAL getTolerance() { return tolerance; }
259
260
 private:
261
  SimplexV store_v[4];
262
  SimplexV* free_v[4];
263
  vertex_id_t nfree;
264
  vertex_id_t current;
265
  Simplex* simplex;
266
  Status status;
267
268
  unsigned int max_iterations;
269
  FCL_REAL tolerance;
270
  FCL_REAL distance_upper_bound;
271
  size_t iterations;
272
273
  /// @brief discard one vertex from the simplex
274
  inline void removeVertex(Simplex& simplex);
275
276
  /// @brief append one vertex to the simplex
277
  inline void appendVertex(Simplex& simplex, const Vec3f& v, bool isNormalized,
278
                           support_func_guess_t& hint);
279
280
  /// @brief Project origin (0) onto line a-b
281
  /// For a detailed explanation of how to efficiently project onto a simplex,
282
  /// check out Ericson's book, page 403:
283
  /// https://realtimecollisiondetection.net/ To sum up, a simplex has a voronoi
284
  /// region for each feature it has (vertex, edge, face). We find the voronoi
285
  /// region in which the origin lies and stop as soon as we find it; we then
286
  /// project onto it and return the result. We start by voronoi regions
287
  /// generated by vertices then move on to edges then faces. Checking voronoi
288
  /// regions is done using simple dot products. Moreover, edges voronoi checks
289
  /// reuse computations of vertices voronoi checks. The same goes for faces
290
  /// which reuse checks from edges.
291
  /// Finally, in addition to the voronoi procedure, checks relying on the order
292
  /// of construction
293
  // of the simplex are added. To know more about these, visit
294
  // https://caseymuratori.com/blog_0003.
295
  bool projectLineOrigin(const Simplex& current, Simplex& next);
296
297
  /// @brief Project origin (0) onto triangle a-b-c
298
  /// See \ref projectLineOrigin for an explanation on simplex projections.
299
  bool projectTriangleOrigin(const Simplex& current, Simplex& next);
300
301
  /// @brief Project origin (0) onto tetrahedron a-b-c-d
302
  /// See \ref projectLineOrigin for an explanation on simplex projections.
303
  bool projectTetrahedraOrigin(const Simplex& current, Simplex& next);
304
};
305
306
static const size_t EPA_MAX_FACES = 128;
307
static const size_t EPA_MAX_VERTICES = 64;
308
static const FCL_REAL EPA_EPS = 0.000001;
309
static const size_t EPA_MAX_ITERATIONS = 255;
310
311
/// @brief class for EPA algorithm
312
struct HPP_FCL_DLLAPI EPA {
313
  typedef GJK::SimplexV SimplexV;
314
  struct HPP_FCL_DLLAPI SimplexF {
315
    Vec3f n;
316
    FCL_REAL d;
317
    SimplexV* vertex[3];  // a face has three vertices
318
    SimplexF* f[3];       // a face has three adjacent faces
319
    SimplexF* l[2];       // the pre and post faces in the list
320
    size_t e[3];
321
    size_t pass;
322
323
73472
    SimplexF() : n(Vec3f::Zero()){};
324
  };
325
326
  struct HPP_FCL_DLLAPI SimplexList {
327
    SimplexF* root;
328
    size_t count;
329
1148
    SimplexList() : root(NULL), count(0) {}
330
118878
    void append(SimplexF* face) {
331
118878
      face->l[0] = NULL;
332
118878
      face->l[1] = root;
333
118878
      if (root) root->l[0] = face;
334
118878
      root = face;
335
118878
      ++count;
336
118878
    }
337
338
45406
    void remove(SimplexF* face) {
339
45406
      if (face->l[1]) face->l[1]->l[0] = face->l[0];
340
45406
      if (face->l[0]) face->l[0]->l[1] = face->l[1];
341
45406
      if (face == root) root = face->l[1];
342
45406
      --count;
343
45406
    }
344
  };
345
346
58060
  static inline void bind(SimplexF* fa, size_t ea, SimplexF* fb, size_t eb) {
347
58060
    fa->e[ea] = eb;
348
58060
    fa->f[ea] = fb;
349
58060
    fb->e[eb] = ea;
350
58060
    fb->f[eb] = fa;
351
58060
  }
352
353
  struct HPP_FCL_DLLAPI SimplexHorizon {
354
    SimplexF* cf;  // current face in the horizon
355
    SimplexF* ff;  // first face in the horizon
356
    size_t nf;     // number of faces in the horizon
357
6292
    SimplexHorizon() : cf(NULL), ff(NULL), nf(0) {}
358
  };
359
360
 private:
361
  unsigned int max_face_num;
362
  unsigned int max_vertex_num;
363
  unsigned int max_iterations;
364
  FCL_REAL tolerance;
365
366
 public:
367
  enum Status {
368
    Failed = 0,
369
    Valid = 1,
370
    AccuracyReached = 1 << 1 | Valid,
371
    Degenerated = 1 << 1 | Failed,
372
    NonConvex = 2 << 1 | Failed,
373
    InvalidHull = 3 << 1 | Failed,
374
    OutOfFaces = 4 << 1 | Failed,
375
    OutOfVertices = 5 << 1 | Failed,
376
    FallBack = 6 << 1 | Failed
377
  };
378
379
  Status status;
380
  GJK::Simplex result;
381
  Vec3f normal;
382
  FCL_REAL depth;
383
  SimplexV* sv_store;
384
  SimplexF* fc_store;
385
  size_t nextsv;
386
  SimplexList hull, stock;
387
388
574
  EPA(unsigned int max_face_num_, unsigned int max_vertex_num_,
389
      unsigned int max_iterations_, FCL_REAL tolerance_)
390
574
      : max_face_num(max_face_num_),
391
        max_vertex_num(max_vertex_num_),
392
        max_iterations(max_iterations_),
393
574
        tolerance(tolerance_) {
394
574
    initialize();
395
574
  }
396
397
1148
  ~EPA() {
398
574
    delete[] sv_store;
399
574
    delete[] fc_store;
400
574
  }
401
402
  void initialize();
403
404
  /// \return a Status which can be demangled using (status & Valid) or
405
  ///         (status & Failed). The other values provide a more detailled
406
  ///         status
407
  Status evaluate(GJK& gjk, const Vec3f& guess);
408
409
  /// Get the closest points on each object.
410
  /// @return true on success
411
  bool getClosestPoints(const MinkowskiDiff& shape, Vec3f& w0, Vec3f& w1);
412
413
 private:
414
  bool getEdgeDist(SimplexF* face, SimplexV* a, SimplexV* b, FCL_REAL& dist);
415
416
  SimplexF* newFace(SimplexV* a, SimplexV* b, SimplexV* vertex, bool forced);
417
418
  /// @brief Find the best polytope face to split
419
  SimplexF* findBest();
420
421
  /// @brief the goal is to add a face connecting vertex w and face edge f[e]
422
  bool expand(size_t pass, SimplexV* w, SimplexF* f, size_t e,
423
              SimplexHorizon& horizon);
424
};
425
426
}  // namespace details
427
428
}  // namespace fcl
429
430
}  // namespace hpp
431
432
#endif