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);