42 #include <gtest/gtest.h>
43 #include <Eigen/Dense>
59 S min_distance = (p_F1 - p_F2).norm() - radius1 - radius2;
67 S solver_tolerance, S test_tol,
68 S min_distance_expected) {
91 tf1.translation() = p_F1;
92 tf2.translation() = p_F2;
107 EXPECT_EQ(res, min_distance_expected >= 0);
109 EXPECT_NEAR(dist, min_distance_expected, test_tol);
112 EXPECT_NEAR((p_FN1 - p_FN2).norm(), std::abs(dist),
116 EXPECT_NEAR((p_FN1 - p_F1).norm(), radius1, test_tol);
117 EXPECT_NEAR((p_FN2 - p_F2).norm(), radius2, test_tol);
122 EXPECT_NEAR((p_F1 + p_FN2 - p_FN1 - p_F2).norm(), radius1 + radius2,
143 template <
typename S>
151 template <
typename S>
153 std::vector<SphereSpecification<S>> spheres;
154 spheres.emplace_back(0.5,
Vector3<S>(0, 0, -1.2));
155 spheres.emplace_back(0.5,
Vector3<S>(1.25, 0, 0));
156 spheres.emplace_back(0.3,
Vector3<S>(-0.2, 0, 0));
157 spheres.emplace_back(0.4,
Vector3<S>(-0.2, 0, 1.1));
158 for (
int i = 0; i < static_cast<int>(spheres.size()); ++i) {
159 for (
int j = i + 1; j < static_cast<int>(spheres.size()); ++j) {
160 if ((spheres[i].center - spheres[j].center).norm() >
161 spheres[i].radius + spheres[j].radius) {
163 for (
const S solver_tolerance : {S(1e-4), S(1e-5), S(1e-6)}) {
164 const S min_distance_expected =
166 spheres[i].center, spheres[j].center);
171 TestSphereToSphereGJKSignedDistance<S>(
172 spheres[i].radius, spheres[j].radius, spheres[i].center,
173 spheres[j].center, solver_tolerance, 10 * solver_tolerance,
174 min_distance_expected);
177 GTEST_FAIL() <<
"The two spheres collide."
178 <<
"\nSpheres[" << i <<
"] with radius "
179 << spheres[i].radius <<
", centered at "
180 << spheres[i].center.transpose() <<
"\nSpheres[" << j
181 <<
"] with radius " << spheres[j].radius
182 <<
", centered at " << spheres[j].center.transpose()
189 template <
typename S>
191 std::vector<SphereSpecification<S>> spheres;
192 spheres.emplace_back(0.5,
Vector3<S>(0, 0, 0));
193 spheres.emplace_back(0.5,
Vector3<S>(0.75, 0, 0));
194 spheres.emplace_back(0.3,
Vector3<S>(0.2, 0, 0));
195 spheres.emplace_back(0.4,
Vector3<S>(0.2, 0, 0.4));
196 for (
int i = 0; i < static_cast<int>(spheres.size()); ++i) {
197 for (
int j = i + 1; j < static_cast<int>(spheres.size()); ++j) {
198 if ((spheres[i].center - spheres[j].center).norm() <
199 spheres[i].radius + spheres[j].radius) {
201 const S min_distance_expected =
203 spheres[i].center, spheres[j].center);
204 for (
const S solver_tolerance : {S(1E-4), S(1E-5), S(1E-6)}) {
207 TestSphereToSphereGJKSignedDistance<S>(
208 spheres[i].radius, spheres[j].radius, spheres[i].center,
209 spheres[j].center, solver_tolerance, solver_tolerance,
210 min_distance_expected);
213 GTEST_FAIL() <<
"The two spheres failed to collide."
214 <<
"\nSpheres[" << i <<
"] with radius "
215 << spheres[i].radius <<
", centered at "
216 << spheres[i].center.transpose() <<
"\nSpheres[" << j
217 <<
"] with radius " << spheres[j].radius
218 <<
", centered at " << spheres[j].center.transpose()
226 TestNonCollidingSphereGJKSignedDistance<double>();
227 TestNonCollidingSphereGJKSignedDistance<float>();
228 TestCollidingSphereGJKSignedDistance<double>();
229 TestCollidingSphereGJKSignedDistance<float>();
236 template <
typename S>
238 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
246 template <
typename S>
258 X_FB1.translation() << 0, 0, 0.5;
265 X_FB2.linear() << 0.6, -0.8, 0, 0.8, 0.6, 0, 0, 0, 1;
271 auto CheckDistance = [&box1_size, &box2_size, &X_FB1, &X_WF](
274 S solver_distance_tolerance, S test_distance_tolerance,
275 S test_witness_tolerance) {
295 if (distance_expected < 0) {
297 }
else if (distance_expected > 0) {
301 EXPECT_NEAR(dist, distance_expected, test_distance_tolerance);
303 X_WF.linear().transpose() * (p_WN1 - X_WF.translation());
305 X_WF.linear().transpose() * (p_WN2 - X_WF.translation());
307 EXPECT_TRUE(p_FN1.template head<2>().isApprox(p_xy_FN1_expected,
308 test_witness_tolerance));
309 EXPECT_TRUE(p_FN2.template head<2>().isApprox(p_xy_FN2_expected,
310 test_witness_tolerance));
312 EXPECT_NEAR(p_FN1(2), p_FN2(2), test_witness_tolerance);
315 EXPECT_GE(p_FN1(2), 0);
316 EXPECT_GE(p_FN2(2), 0);
317 EXPECT_LE(p_FN1(2), 1);
318 EXPECT_LE(p_FN2(2), 1);
324 auto CheckBoxEdgeBoxFaceDistance = [&CheckDistance](
326 S test_distance_tolerance, S test_witness_tolerance) {
330 Vector2<S>(X_FB2.translation()(0) + 0.5, X_FB2.translation()(1)),
331 solver_distance_tolerance, test_distance_tolerance,
332 test_witness_tolerance);
341 for (
int i = 0; i < static_cast<int>(solver_tolerances.size()); ++i) {
342 const S solver_distance_tolerance = solver_tolerances[i];
347 const S test_distance_tolerance = 10 * solver_distance_tolerance;
348 const S test_witness_tolerance = test_distance_tolerance;
350 X_FB2.translation() << -1, 0, 0.5;
351 CheckBoxEdgeBoxFaceDistance(X_FB2, solver_distance_tolerance,
352 test_distance_tolerance,
353 test_witness_tolerance);
357 X_FB2.translation() << -1, 0.1, 0.5;
358 CheckBoxEdgeBoxFaceDistance(X_FB2, solver_distance_tolerance,
359 test_distance_tolerance,
360 test_witness_tolerance);
363 X_FB2.translation() << -1, -0.1, 0.5;
364 CheckBoxEdgeBoxFaceDistance(X_FB2, solver_distance_tolerance,
365 test_distance_tolerance,
366 test_witness_tolerance);
374 for (
int i = 0; i < static_cast<int>(solver_tolerances.size()); ++i) {
375 const S solver_distance_tolerance = solver_tolerances[i];
379 const S test_distance_tolerance = solver_distance_tolerance;
380 const S test_witness_tolerance = test_distance_tolerance;
382 X_FB2.translation() << -0.9, 0, 0.5;
383 CheckBoxEdgeBoxFaceDistance(X_FB2, solver_distance_tolerance,
384 test_distance_tolerance,
385 test_witness_tolerance);
388 X_FB2.translation() << -0.9, 0.1, 0.5;
389 CheckBoxEdgeBoxFaceDistance(X_FB2, solver_distance_tolerance,
390 test_distance_tolerance,
391 test_witness_tolerance);
394 X_FB2.translation() << -0.9, -0.05, 0.5;
395 CheckBoxEdgeBoxFaceDistance(X_FB2, solver_distance_tolerance,
396 test_distance_tolerance,
397 test_witness_tolerance);
400 X_FB2.translation() << -0.9, -0.1, 0.5;
401 CheckBoxEdgeBoxFaceDistance(X_FB2, solver_distance_tolerance,
402 test_distance_tolerance,
403 test_witness_tolerance);
407 template <
typename S>
415 X_WF.translation() << 0, 0, 1;
418 X_WF.translation() << 0, 1, 0;
421 X_WF.translation() << 1, 0, 0;
441 X_WF.translation() << 0.1, 0.2, 0.3;
453 int main(
int argc,
char* argv[]) {
454 ::testing::InitGoogleTest(&argc, argv);
455 return RUN_ALL_TESTS();