37 #define BOOST_TEST_MODULE COAL_GJK 
   39 #include <boost/test/included/unit_test.hpp> 
   41 #include <Eigen/Geometry> 
   58 typedef Eigen::Matrix<CoalScalar, Eigen::Dynamic, 1> 
vector_t;
 
   61 typedef Eigen::Matrix<CoalScalar, Eigen::Dynamic, Eigen::Dynamic> 
matrix_t;
 
   72     bool enable_gjk_nesterov_acceleration) {
 
   73   Eigen::IOFormat numpy(Eigen::FullPrecision, Eigen::DontAlignCols, 
", ", 
", ",
 
   74                         "np.array ((", 
"))", 
"", 
"");
 
   75   Eigen::IOFormat tuple(Eigen::FullPrecision, Eigen::DontAlignCols, 
"", 
", ",
 
   77   std::size_t N = 10000;
 
   79   if (enable_gjk_nesterov_acceleration)
 
   87   std::size_t nCol = 0, nDiff = 0;
 
   90   for (std::size_t i = 0; i < N; ++i) {
 
   91     Vec3s P1_loc(Vec3s::Random()), P2_loc(Vec3s::Random()),
 
   92         P3_loc(Vec3s::Random());
 
   93     Vec3s Q1_loc(Vec3s::Random()), Q2_loc(Vec3s::Random()),
 
   94         Q3_loc(Vec3s::Random());
 
   96       P1_loc = 
Vec3s(0.063996093749999997, -0.15320971679687501,
 
   97                      -0.42799999999999999);
 
   99           Vec3s(0.069105957031249998, -0.150722900390625, -0.42999999999999999);
 
  100       P3_loc = 
Vec3s(0.063996093749999997, -0.15320971679687501,
 
  101                      -0.42999999999999999);
 
  103           Vec3s(-25.655000000000001, -1.2858199462890625, 3.7249809570312502);
 
  104       Q2_loc = 
Vec3s(-10.926, -1.284259033203125, 3.7281499023437501);
 
  105       Q3_loc = 
Vec3s(-10.926, -1.2866180419921875, 3.72335400390625);
 
  107           Quatf(-0.42437287410898855, -0.26862477561450587,
 
  108                 -0.46249645019513175, 0.73064726592483387),
 
  109           Vec3s(-12.824601270753471, -1.6840516940066426, 3.8914453043793844));
 
  113           Vec3s(-0.8027043342590332, -0.30276307463645935, -0.4372950792312622);
 
  115           Vec3s(-0.8027043342590332, 0.30276307463645935, -0.4372950792312622);
 
  117           Vec3s(0.8027043342590332, 0.30276307463645935, -0.4372950792312622);
 
  119           Vec3s(-0.224713996052742, -0.7417119741439819, 0.19999997317790985);
 
  121           Vec3s(-0.5247139930725098, -0.7417119741439819, 0.19999997317790985);
 
  123           Vec3s(-0.224713996052742, -0.7417119741439819, 0.09999997168779373);
 
  126       R << 0.9657787025454787, 0.09400415350535746, 0.24173273843919627,
 
  127           -0.06713698817647556, 0.9908494114820345, -0.11709000206805695,
 
  128           -0.25052768814676646, 0.09685382227587608, 0.9632524147814993;
 
  130       T << -0.13491177905469953, -1, 0.6000449621843792;
 
  132       tf1.setTranslation(T);
 
  140     const bool compute_penetration = 
true;
 
  149         &tri1, 
tf1, &tri2, 
tf2, &solver, request, result);
 
  155     results[i].timeGjk = end - start;
 
  156     results[i].collision = 
res;
 
  163       assert(penetration_depth >= 0);
 
  164       tf2.setTranslation((penetration_depth + 10 - 4) * normal);
 
  167           &tri1, 
tf1, &tri2, 
tf2, &solver, request, result);
 
  173         std::cerr << 
"P1 = " << P1_loc.format(tuple) << std::endl;
 
  174         std::cerr << 
"P2 = " << P2_loc.format(tuple) << std::endl;
 
  175         std::cerr << 
"P3 = " << P3_loc.format(tuple) << std::endl;
 
  176         std::cerr << 
"Q1 = " << Q1_loc.format(tuple) << std::endl;
 
  177         std::cerr << 
"Q2 = " << Q2_loc.format(tuple) << std::endl;
 
  178         std::cerr << 
"Q3 = " << Q3_loc.format(tuple) << std::endl;
 
  179         std::cerr << 
"p1 = " << c1.format(tuple) << std::endl;
 
  180         std::cerr << 
"p2 = " << 
c2.format(tuple) << std::endl;
 
  181         std::cerr << 
"tf1 = " << 
tf1.getTranslation().format(tuple) << 
" + " 
  182                   << 
tf1.getQuatRotation().coeffs().format(tuple) << std::endl;
 
  183         std::cerr << 
"tf2 = " << 
tf2.getTranslation().format(tuple) << 
" + " 
  184                   << 
tf2.getQuatRotation().coeffs().format(tuple) << std::endl;
 
  185         std::cerr << 
"normal = " << normal.format(tuple) << std::endl;
 
  193         P3(
tf1.transform(P3_loc)), 
Q1(
tf2.transform(Q1_loc)),
 
  194         Q2(
tf2.transform(Q2_loc)), 
Q3(
tf2.transform(Q3_loc));
 
  197     Vec3s w1(u1.cross(v1));
 
  200     Vec3s w2(u2.cross(v2));
 
  201     BOOST_CHECK(w1.squaredNorm() > 
eps * 
eps);
 
  206     a1 = 
M.inverse() * (
p1 - 
P1);
 
  208     BOOST_CHECK(w2.squaredNorm() > 
eps * 
eps);
 
  213     a2 = 
M.inverse() * (p2 - 
Q1);
 
  237     grad_f[0] = -(p2 - 
p1).dot(u1);
 
  238     grad_f[1] = -(p2 - 
p1).dot(v1);
 
  239     grad_f[2] = (p2 - 
p1).dot(u2);
 
  240     grad_f[3] = (p2 - 
p1).dot(v2);
 
  244     g[2] = a1[0] + a1[1] - 1;
 
  247     g[5] = a2[0] + a2[1] - 1;
 
  260     BOOST_CHECK_SMALL(a1[2], 
eps);
 
  262     BOOST_CHECK_SMALL(a2[2], 
eps);
 
  278     matrix_t::Index col = 0;
 
  280     for (vector6_t::Index j = 0; j < 6; ++j) {
 
  281       BOOST_CHECK(g[j] <= 
eps);
 
  283       if (fabs(g[j]) <= 
eps) {
 
  284         Mkkt.col(col) = grad_g.col(j);
 
  289       Mkkt.conservativeResize(4, col);
 
  292       Eigen::JacobiSVD<matrix_t> svd(Mkkt,
 
  293                                      Eigen::ComputeThinU | Eigen::ComputeThinV);
 
  295       for (vector_t::Index j = 0; j < 
c.size(); ++j) {
 
  296         BOOST_CHECK_MESSAGE(
c[j] >= -
eps,
 
  297                             "c[" << j << 
"]{" << 
c[j] << 
"} is below " << -
eps);
 
  301   std::cerr << 
"nCol / nTotal = " << nCol << 
" / " << N << std::endl;
 
  302   std::cerr << 
"nDiff = " << nDiff << std::endl;
 
  304   clock_t totalTimeGjkColl = 0;
 
  305   clock_t totalTimeGjkNoColl = 0;
 
  306   for (std::size_t i = 0; i < N; ++i) {
 
  308       totalTimeGjkColl += results[i].timeGjk;
 
  310       totalTimeGjkNoColl += results[i].timeGjk;
 
  313   std::cerr << 
"Total / average time gjk: " 
  314             << totalTimeGjkNoColl + totalTimeGjkColl << 
", " 
  315             << 
CoalScalar(totalTimeGjkNoColl + totalTimeGjkColl) /
 
  318   std::cerr << 
"-- Collisions -------------------------" << std::endl;
 
  319   std::cerr << 
"Total / average time gjk: " << totalTimeGjkColl << 
", " 
  322   std::cerr << 
"-- No collisions -------------------------" << std::endl;
 
  323   std::cerr << 
"Total / average time gjk: " << totalTimeGjkNoColl << 
", " 
  338                           double swept_sphere_radius,
 
  339                           bool use_gjk_nesterov_acceleration) {
 
  340   using namespace coal;
 
  343   sphere.setSweptSphereRadius(swept_sphere_radius);
 
  345   typedef Eigen::Matrix<CoalScalar, 4, 1> Vec4f;
 
  349   bool expect_collision = center_distance <= 2 * (
r + swept_sphere_radius);
 
  360   if (use_gjk_nesterov_acceleration)
 
  364   if (expect_collision) {
 
  370                 center_distance > 
gjk.getTolerance());
 
  375   Vec3s w0, w1, normal;
 
  376   gjk.getWitnessPointsAndNormal(shape, w0, w1, normal);
 
  378   Vec3s w0_expected(tf0.inverse().transform(tf0.getTranslation() + ray) +
 
  379                     swept_sphere_radius * normal);
 
  380   Vec3s w1_expected(tf0.inverse().transform(
tf1.getTranslation() - ray) -
 
  381                     swept_sphere_radius * normal);
 
  388   std::array<bool, 2> use_nesterov_acceleration = {
false, 
true};
 
  389   std::array<double, 5> swept_sphere_radius = {0., 0.1, 1., 10., 100.};
 
  390   for (
bool nesterov_acceleration : use_nesterov_acceleration) {
 
  391     for (
double ssr : swept_sphere_radius) {
 
  402                            nesterov_acceleration);
 
  405                            nesterov_acceleration);
 
  408                            nesterov_acceleration);
 
  411                            nesterov_acceleration);
 
  417                                bool use_gjk_nesterov_acceleration,
 
  419   using namespace coal;
 
  424   tf1.setTranslation(T);
 
  437   if (use_gjk_nesterov_acceleration)
 
  441   if (expect_collision) {
 
  448     Vec3s guess = 
gjk.getGuessFromSimplex();
 
  454   Vec3s w0, w1, normal;
 
  457     gjk.getWitnessPointsAndNormal(shape, w0, w1, normal);