40 #ifndef COAL_NARROWPHASE_H
41 #define COAL_NARROWPHASE_H
59 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
75 COAL_DEPRECATED_MESSAGE(Use gjk_initial_guess
instead)
76 bool enable_cached_guess;
98 mutable details::EPA epa;
101 size_t epa_max_iterations;
107 mutable details::MinkowskiDiff minkowski_difference;
128 enable_cached_guess(false),
129 cached_guess(
Vec3s(1, 0, 0)),
131 distance_upper_bound((std::numeric_limits<
CoalScalar>::max)()),
149 :
gjk(request.gjk_max_iterations, request.gjk_tolerance),
150 epa(0, request.epa_tolerance) {
151 this->cached_guess =
Vec3s(1, 0, 0);
152 this->support_func_cached_guess = support_func_guess_t::Zero();
167 this->enable_cached_guess) {
174 this->distance_upper_bound = (std::numeric_limits<CoalScalar>::max)();
177 this->gjk_convergence_criterion_type =
187 this->epa.status = details::EPA::Status::DidNotRun;
188 this->gjk.
status = details::GJK::Status::DidNotRun;
201 :
gjk(request.gjk_max_iterations, request.gjk_tolerance),
202 epa(0, request.epa_tolerance) {
203 this->cached_guess =
Vec3s(1, 0, 0);
204 this->support_func_cached_guess = support_func_guess_t::Zero();
219 this->enable_cached_guess) {
227 this->distance_upper_bound = (std::max)(
231 this->gjk_convergence_criterion_type =
241 this->gjk.
status = details::GJK::Status::DidNotRun;
242 this->epa.status = details::EPA::Status::DidNotRun;
251 return this->enable_cached_guess ==
260 this->gjk_convergence_criterion_type ==
273 return compute_penetration
274 ? (std::max)(this->gjk_tolerance, this->epa_tolerance)
275 : this->gjk_tolerance;
307 template <
typename S1,
typename S2>
311 Vec3s& normal)
const {
312 constexpr
bool relative_transformation_already_computed =
false;
315 normal, relative_transformation_already_computed);
322 template <
typename S1>
326 Vec3s& normal)
const {
331 constexpr
bool relative_transformation_already_computed =
true;
333 this->runGJKAndEPA(s1,
tf1, tri, tf_1M2, compute_penetration,
distance,
p1,
334 p2, normal, relative_transformation_already_computed);
339 template <
typename S2>
343 Vec3s& normal)
const {
345 s2,
tf2, s1,
tf1, compute_penetration, p2,
p1, normal);
353 template <
typename S1,
typename S2>
356 const Vec3s& default_guess =
Vec3s(1, 0, 0))
const {
359 support_hint = this->support_func_cached_guess;
361 switch (gjk_initial_guess) {
363 guess = default_guess;
366 guess = this->cached_guess;
369 if (s1.aabb_local.volume() < 0 || s2.aabb_local.volume() < 0) {
371 "computeLocalAABB must have been called on the shapes before "
373 "GJKInitialGuess::BoundingVolumeGuess.",
377 s1.aabb_local.center() -
378 (this->minkowski_difference.oR1 * s2.aabb_local.center() +
379 this->minkowski_difference.ot1);
387 if (this->enable_cached_guess) {
388 guess = this->cached_guess;
420 template <
typename S1,
typename S2,
426 const bool relative_transformation_already_computed =
false)
const {
428 if (relative_transformation_already_computed)
429 this->minkowski_difference.set<_SupportOptions>(&s1, &s2);
431 this->minkowski_difference.set<_SupportOptions>(&s1, &s2,
tf1,
tf2);
432 this->gjk.
reset(this->gjk_max_iterations, this->gjk_tolerance);
437 this->epa.status = details::EPA::Status::DidNotRun;
442 getGJKInitialGuess(*(this->minkowski_difference.shapes[0]),
443 *(this->minkowski_difference.shapes[1]), guess,
446 this->gjk.
evaluate(this->minkowski_difference, guess, support_hint);
448 switch (this->gjk.
status) {
450 COAL_ASSERT(
false,
"GJK did not run. It should have!",
452 this->cached_guess =
Vec3s(1, 0, 0);
453 this->support_func_cached_guess.setZero();
454 distance = -(std::numeric_limits<CoalScalar>::max)();
456 Vec3s::Constant(std::numeric_limits<CoalScalar>::quiet_NaN());
462 GJKExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
469 GJKEarlyStopExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2,
472 this->m_dummy_precision,
473 "The distance should be bigger than GJK's "
474 "`distance_upper_bound`.",
482 GJKExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
485 "The distance found by GJK should coincide with the "
486 "distance between the closest points.",
493 GJKExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
495 distance <= this->
gjk.getTolerance() + this->m_dummy_precision,
496 "The distance found by GJK should be negative or at "
497 "least below GJK's tolerance.",
501 if (!compute_penetration) {
503 GJKCollisionExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2,
514 this->epa.reset(this->epa_max_iterations, this->epa_tolerance);
518 this->epa.evaluate(this->gjk, -guess);
520 switch (epa.status) {
534 EPAExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
538 EPAExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
542 EPAExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
547 -epa.depth <= epa.getTolerance() + this->m_dummy_precision,
548 "EPA's penetration distance should be negative (or "
549 "at least below EPA's tolerance).",
551 EPAExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
555 "EPA warning: created a polytope with a degenerated face.");
556 EPAExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
560 "EPA warning: EPA got called onto non-convex shapes.");
561 EPAExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
565 EPAExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2, normal);
568 COAL_ASSERT(
false,
"EPA did not run. It should have!",
571 EPAFailedExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2,
577 "EPA went into fallback mode. It should never do that.",
580 EPAFailedExtractWitnessPointsAndNormal(
tf1,
distance,
p1, p2,
592 Vec3s& normal)
const {
595 this->cached_guess = this->gjk.
ray;
596 this->support_func_cached_guess = this->gjk.
support_hint;
600 Vec3s::Constant(std::numeric_limits<CoalScalar>::quiet_NaN());
620 this->gjk.getTolerance() - this->m_dummy_precision,
621 "The norm of GJK's ray should be bigger than GJK's tolerance.",
624 this->cached_guess = this->gjk.
ray;
625 this->support_func_cached_guess = this->gjk.
support_hint;
630 gjk.getWitnessPointsAndNormal(this->minkowski_difference,
p1, p2, normal);
632 normal =
tf1.getRotation() * normal;
634 p2.noalias() = p + 0.5 *
distance * normal;
640 Vec3s& normal)
const {
643 this->gjk.getTolerance() + this->m_dummy_precision,
644 "The distance should be lower than GJK's tolerance.",
650 this->support_func_cached_guess = this->gjk.
support_hint;
654 Vec3s::Constant(std::numeric_limits<CoalScalar>::quiet_NaN());
662 this->cached_guess = -(this->epa.depth * this->epa.normal);
663 this->support_func_cached_guess = this->epa.support_hint;
664 distance = (std::min)(0., -this->epa.depth);
665 this->epa.getWitnessPointsAndNormal(this->minkowski_difference,
p1, p2,
707 normal =
tf1.getRotation() * normal;
709 p2.noalias() = p + 0.5 *
distance * normal;
715 this->cached_guess =
Vec3s(1, 0, 0);
716 this->support_func_cached_guess.setZero();
719 distance = -(std::numeric_limits<CoalScalar>::max)();
721 Vec3s::Constant(std::numeric_limits<CoalScalar>::quiet_NaN());