From baa374228647ff52c8be68be77cdf8bd46227b04 Mon Sep 17 00:00:00 2001 From: Florent Lamiraux <florent@laas.fr> Date: Fri, 11 Jan 2019 21:01:12 +0100 Subject: [PATCH] [GJK] If gjk fails for two triangles, return no collision. It seems that GJK fails when the triangles are close to each other but not colliding, Add a test in test_fcl_gjk with specific triangles and transforms that make GJK fail. --- src/narrowphase/narrowphase.cpp | 29 ++++++------------- test/test_fcl_gjk.cpp | 49 ++++++++++++++++++++++++++------- test/test_fcl_gjk.py | 32 ++++++--------------- 3 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/narrowphase/narrowphase.cpp b/src/narrowphase/narrowphase.cpp index 7eb28b72..9d00eafe 100644 --- a/src/narrowphase/narrowphase.cpp +++ b/src/narrowphase/narrowphase.cpp @@ -636,18 +636,17 @@ bool GJKSolver_indep::shapeDistance<Capsule, Capsule> details::GJK::Status gjk_status = gjk.evaluate(shape, -guess); if(enable_cached_guess) cached_guess = gjk.getGuessFromSimplex(); - if(gjk_status == details::GJK::Valid) + Vec3f w0 (Vec3f::Zero()), w1 (Vec3f::Zero()); + for(size_t i = 0; i < gjk.getSimplex()->rank; ++i) + { + FCL_REAL p = gjk.getSimplex()->coefficient[i]; + w0 += shape.support(gjk.getSimplex()->vertex[i]->d, 0) * p; + w1 += shape.support(-gjk.getSimplex()->vertex[i]->d, 1) * p; + } + if((gjk_status == details::GJK::Valid) || + (gjk_status == details::GJK::Failed)) { - Vec3f w0 (Vec3f::Zero()), w1 (Vec3f::Zero()); - for(size_t i = 0; i < gjk.getSimplex()->rank; ++i) - { - FCL_REAL p = gjk.getSimplex()->coefficient[i]; - w0 += shape.support(gjk.getSimplex()->vertex[i]->d, 0) * p; - w1 += shape.support(-gjk.getSimplex()->vertex[i]->d, 1) * p; - } - dist = (w0 - w1).norm(); - p1 = tf1.transform (w0); p2 = tf1.transform (w1); @@ -655,15 +654,7 @@ bool GJKSolver_indep::shapeDistance<Capsule, Capsule> } else if (gjk_status == details::GJK::Inside) { - Vec3f w0 (Vec3f::Zero()), w1 (Vec3f::Zero()); - for(size_t i = 0; i < gjk.getSimplex()->rank; ++i) - { - FCL_REAL p = gjk.getSimplex()->coefficient[i]; - w0 += shape.support(gjk.getSimplex()->vertex[i]->d, 0) * p; - w1 += shape.support(-gjk.getSimplex()->vertex[i]->d, 1) * p; - } dist = 0; - p1 = tf1.transform (w0); p2 = tf1.transform (w1); @@ -675,7 +666,5 @@ bool GJKSolver_indep::shapeDistance<Capsule, Capsule> } return false; } - abort (); - return false; } } // fcl diff --git a/test/test_fcl_gjk.cpp b/test/test_fcl_gjk.cpp index e65b9a44..59d8c0fc 100644 --- a/test/test_fcl_gjk.cpp +++ b/test/test_fcl_gjk.cpp @@ -47,6 +47,7 @@ using fcl::GJKSolver_indep; using fcl::TriangleP; using fcl::Vec3f; +using fcl::Quaternion3f; using fcl::Transform3f; using fcl::Matrix3f; using fcl::FCL_REAL; @@ -83,10 +84,32 @@ BOOST_AUTO_TEST_CASE(distance_triangle_triangle_1) FCL_REAL eps = 1e-7; Results_t results (N); for (std::size_t i=0; i<N; ++i) { - Vec3f P1 (Vec3f::Random ()), P2 (Vec3f::Random ()), P3 (Vec3f::Random ()); - Vec3f Q1 (Vec3f::Random ()), Q2 (Vec3f::Random ()), Q3 (Vec3f::Random ()); - TriangleP tri1 (P1, P2, P3); - TriangleP tri2 (Q1, Q2, Q3); + Vec3f P1_loc (Vec3f::Random ()), P2_loc (Vec3f::Random ()), + P3_loc (Vec3f::Random ()); + Vec3f Q1_loc (Vec3f::Random ()), Q2_loc (Vec3f::Random ()), + Q3_loc (Vec3f::Random ()); + if (i==0) { + P1_loc = Vec3f (0.063996093749999997, -0.15320971679687501, + -0.42799999999999999); + P2_loc = Vec3f (0.069105957031249998, -0.150722900390625, + -0.42999999999999999); + P3_loc = Vec3f (0.063996093749999997, -0.15320971679687501, + -0.42999999999999999); + Q1_loc = Vec3f (-25.655000000000001, -1.2858199462890625, + 3.7249809570312502); + Q2_loc = Vec3f (-10.926, -1.284259033203125, 3.7281499023437501); + Q3_loc = Vec3f (-10.926, -1.2866180419921875, 3.72335400390625); + Transform3f tf + (Quaternion3f (-0.42437287410898855, -0.26862477561450587, + -0.46249645019513175, 0.73064726592483387), + Vec3f (-12.824601270753471, -1.6840516940066426, 3.8914453043793844)); + tf1 = tf; + } else { + tf1 = Transform3f (); + } + + TriangleP tri1 (P1_loc, P2_loc, P3_loc); + TriangleP tri2 (Q1_loc, Q2_loc, Q3_loc); Vec3f normal; bool res; @@ -107,14 +130,17 @@ BOOST_AUTO_TEST_CASE(distance_triangle_triangle_1) res = solver.shapeDistance (tri1, tf1, tri2, tf2, distance, c1, c2, normal2); if (!res) { - std::cerr << "P1 = " << P1.format (tuple) << std::endl; - std::cerr << "P2 = " << P2.format (tuple) << std::endl; - std::cerr << "P3 = " << P3.format (tuple) << std::endl; - std::cerr << "Q1 = " << Q1.format (tuple) << std::endl; - std::cerr << "Q2 = " << Q2.format (tuple) << std::endl; - std::cerr << "Q3 = " << Q3.format (tuple) << std::endl; + std::cerr << "P1 = " << P1_loc.format (tuple) << std::endl; + std::cerr << "P2 = " << P2_loc.format (tuple) << std::endl; + std::cerr << "P3 = " << P3_loc.format (tuple) << std::endl; + std::cerr << "Q1 = " << Q1_loc.format (tuple) << std::endl; + std::cerr << "Q2 = " << Q2_loc.format (tuple) << std::endl; + std::cerr << "Q3 = " << Q3_loc.format (tuple) << std::endl; std::cerr << "p1 = " << c1.format (tuple) << std::endl; std::cerr << "p2 = " << c2.format (tuple) << std::endl; + std::cerr << "tf1 = " << tf1.getTranslation ().format (tuple) + << " + " << tf1.getQuatRotation ().coeffs ().format (tuple) + << std::endl; std::cerr << "tf2 = " << tf2.getTranslation ().format (tuple) << " + " << tf2.getQuatRotation ().coeffs ().format (tuple) << std::endl; @@ -125,6 +151,9 @@ BOOST_AUTO_TEST_CASE(distance_triangle_triangle_1) tf2.setIdentity (); } // Compute vectors between vertices + Vec3f P1 (tf1.transform (P1_loc)), P2 (tf1.transform (P2_loc)), + P3 (tf1.transform (P3_loc)), Q1 (tf2.transform (Q1_loc)), + Q2 (tf2.transform (Q2_loc)), Q3 (tf2.transform (Q3_loc)); Vec3f u1 (P2 - P1); Vec3f v1 (P3 - P1); Vec3f w1 (u1.cross (v1)); diff --git a/test/test_fcl_gjk.py b/test/test_fcl_gjk.py index a8e96435..b92dac60 100644 --- a/test/test_fcl_gjk.py +++ b/test/test_fcl_gjk.py @@ -20,35 +20,21 @@ c.gui.createScene (sceneName) c.gui.addSceneToWindow (sceneName, wid) P1 = (-0.6475786872429674, -0.519875255189778, 0.5955961037406681) -P2 = (0.4653088233737781, 0.313127305970121, 0.934810277044219) -P3 = (0.2789166910941325, 0.5194696837661181, -0.8130390456938367) -Q1 = (-0.7301951766620367, 0.04042013969291935, -0.8435357165725602) -Q2 = (-0.8601872044895716, -0.5906898274974384, -0.07715905321629679) -Q3 = (0.6393545603562867, 0.1466372567911807, 0.5111616707924576) -p1 = (0.2238377827027012, 0.2163758468474661, 0.4505435657492071) -p2 = (0.2238377827027012, 0.2163758468474662, 0.450543565749207) -tf2 = (-0.1588705771755817, 0.1959319373363798, 0.04007284069698749) + (0, 0, 0, 1) -normal = (-0.6220181878092853, 0.7671227156255918, 0.1568952300284174) +P2 = (0.069105957031249998, -0.150722900390625, -0.42999999999999999) +P3 = (0.063996093749999997, -0.15320971679687501, -0.42999999999999999) +Q1 = (-25.655000000000001, -1.2858199462890625, 3.7249809570312502) +Q2 = (-10.926, -1.284259033203125, 3.7281499023437501) +Q3 = (-10.926, -1.2866180419921875, 3.72335400390625) +tf1 = (-12.824601270753471, -1.6840516940066426, 3.8914453043793844, + -0.26862477561450587, -0.46249645019513175, 0.73064726592483387, + -0.42437287410898855) +tf2 = (0, 0, 0, 0, 0, 0, 1) c.gui.addTriangleFace ("triangle1", P1, P2, P3, Red) c.gui.addTriangleFace ("triangle2", Q1, Q2, Q3, Green) c.gui.addToGroup ('triangle1', sceneName) c.gui.addToGroup ('triangle2', sceneName) -c.gui.addSphere ('closest point 1', .02, Red) -c.gui.addSphere ('closest point 2', .02, Green) -c.gui.addToGroup ('closest point 1', sceneName) -c.gui.addToGroup ('closest point 2', sceneName) - -c.gui.addLine ('normal', P1, tuple (np.array (P1) + np.array (normal)), Red) -c.gui.addToGroup ('normal', sceneName) - -q1 = p1 + (1,0,0,0) -q2 = p2 + (1,0,0,0) -tf1 = (0, 0, 0, 0, 0, 0, 1) - -c.gui.applyConfiguration ('closest point 1', q1) -c.gui.applyConfiguration ('closest point 2', q2) c.gui.applyConfiguration ('triangle1', tf1) c.gui.applyConfiguration ('triangle2', tf2) c.gui.refresh () -- GitLab