@@ -325,12 +325,22 @@ void test_distance_box_box_helper(const Vector3<S>& box1_size,
325
325
// p_B1P1 is the position of the witness point P1 on box 1, measured
326
326
// and expressed in the box 1 frame B1.
327
327
const Vector3<S> p_B1P1 = X_WB1.inverse () * result.nearest_points [0 ];
328
- const double tol = 10 * std::numeric_limits<S>::epsilon ();
329
- EXPECT_TRUE ((p_B1P1.array ().abs () <= (box1_size / 2 ).array () + tol).all ());
328
+ constexpr double tol = 10 * constants<S>::eps ();
329
+ const double tol_1 = tol * std::max (S (1 ), (box1_size / 2 ).maxCoeff ());
330
+ EXPECT_TRUE (
331
+ (p_B1P1.array ().abs () <= (box1_size / 2 ).array () + tol_1).all ())
332
+ << " \n p_B1P1: " << p_B1P1.transpose ()
333
+ << " \n box1_size / 2: " << (box1_size / 2 ).transpose ()
334
+ << " \n tol: " << tol_1;
330
335
// p_B2P2 is the position of the witness point P2 on box 2, measured
331
336
// and expressed in the box 2 frame B2.
337
+ const double tol_2 = tol * std::max (S (1 ), (box2_size / 2 ).maxCoeff ());
332
338
const Vector3<S> p_B2P2 = X_WB2.inverse () * result.nearest_points [1 ];
333
- EXPECT_TRUE ((p_B2P2.array ().abs () <= (box2_size / 2 ).array () + tol).all ());
339
+ EXPECT_TRUE (
340
+ (p_B2P2.array ().abs () <= (box2_size / 2 ).array () + tol_2).all ())
341
+ << " \n p_B2P2: " << p_B2P2.transpose ()
342
+ << " \n box2_size / 2: " << (box2_size / 2 ).transpose ()
343
+ << " \n tol: " << tol_2;
334
344
335
345
// An expected distance has been provided; let's test that the value is as
336
346
// expected.
@@ -345,6 +355,7 @@ void test_distance_box_box_helper(const Vector3<S>& box1_size,
345
355
// reported in https://github.com/flexible-collision-library/fcl/issues/388
346
356
template <typename S>
347
357
void test_distance_box_box_regression1 () {
358
+ SCOPED_TRACE (" test_distance_box_box_regression1" );
348
359
const Vector3<S> box1_size (0.03 , 0.12 , 0.1 );
349
360
Transform3<S> X_WB1 = Transform3<S>::Identity ();
350
361
X_WB1.matrix () << -3.0627937852578681533e-08 , -0.99999999999999888978 ,
@@ -370,6 +381,7 @@ void test_distance_box_box_regression1() {
370
381
// reported in https://github.com/flexible-collision-library/fcl/issues/395
371
382
template <typename S>
372
383
void test_distance_box_box_regression2 () {
384
+ SCOPED_TRACE (" test_distance_box_box_regression2" );
373
385
const Vector3<S> box1_size (0.46 , 0.48 , 0.01 );
374
386
Transform3<S> X_WB1 = Transform3<S>::Identity ();
375
387
X_WB1.matrix () << 1 ,0 ,0 , -0.72099999999999997424 ,
@@ -393,6 +405,7 @@ void test_distance_box_box_regression2() {
393
405
// reported in https://github.com/flexible-collision-library/fcl/issues/415
394
406
template <typename S>
395
407
void test_distance_box_box_regression3 () {
408
+ SCOPED_TRACE (" test_distance_box_box_regression3" );
396
409
const Vector3<S> box1_size (0.49 , 0.05 , 0.21 );
397
410
Transform3<S> X_WB1 = Transform3<S>::Identity ();
398
411
// clang-format off
@@ -416,6 +429,7 @@ void test_distance_box_box_regression3() {
416
429
// reported in https://github.com/flexible-collision-library/fcl/issues/398
417
430
template <typename S>
418
431
void test_distance_box_box_regression4 () {
432
+ SCOPED_TRACE (" test_distance_box_box_regression4" );
419
433
const Vector3<S> box1_size (0.614 , 3 , 0.37 );
420
434
Transform3<S> X_WB1 = Transform3<S>::Identity ();
421
435
X_WB1.translation () << -0.675 , 0 , 0.9115 ;
@@ -429,6 +443,7 @@ void test_distance_box_box_regression4() {
429
443
// reported in https://github.com/flexible-collision-library/fcl/issues/428
430
444
template <typename S>
431
445
void test_distance_box_box_regression5 () {
446
+ SCOPED_TRACE (" test_distance_box_box_regression5" );
432
447
const Vector3<S> box1_size (0.2 , 0.33 , 0.1 );
433
448
Transform3<S> X_WB1 = Transform3<S>::Identity ();
434
449
X_WB1.translation () << -0.071000000000000035305 , -0.77200000000000001954 , 0.79999999999999993339 ;
@@ -440,6 +455,7 @@ void test_distance_box_box_regression5() {
440
455
441
456
template <typename S>
442
457
void test_distance_box_box_regression6 () {
458
+ SCOPED_TRACE (" test_distance_box_box_regression6" );
443
459
const Vector3<S> box1_size (0.31650000000000000355 , 0.22759999999999999676 , 0.1768000000000000127 );
444
460
Transform3<S> X_WB1 = Transform3<S>::Identity ();
445
461
// clang-format off
@@ -460,11 +476,64 @@ void test_distance_box_box_regression6() {
460
476
test_distance_box_box_helper (box1_size, X_WB1, box2_size, X_WB2, &expected_distance);
461
477
}
462
478
479
+ // Issue #493 outlines a number of scenarios that caused signed distance
480
+ // failure. They consisted of two identical, stacked boxes. The boxes are
481
+ // slightly tilted. The boxes were essentially touching but were separated by
482
+ // infinitesimally small distances. The issue outlines three different examples.
483
+ // Rather than reproducing each of them verbatim, this test attempts to
484
+ // generalize those cases by testing the stacked scenario across various box
485
+ // sizes and separation amounts (ranging from slightly penetrating to slightly
486
+ // separated). These should essentially cover the variations described in the
487
+ // issue.
488
+ template <typename S>
489
+ void test_distance_box_box_regression_tilted_kissing_contact () {
490
+ SCOPED_TRACE (" test_distance_box_box_regression_tilted_kissing_contact" );
491
+ // The boxes are posed relative to each other in a common frame F (such that
492
+ // it is easy to reason about their separation). The stack is rotated around
493
+ // box A's origin and translated into the world frame.
494
+ Matrix3<S> R_WF;
495
+ R_WF <<
496
+ 0.94096063217417758029 , 0.29296840037289501035 , 0.16959541586174811667 ,
497
+ -0.23569836841299879326 , 0.92661523595848427348 , -0.29296840037289506586 ,
498
+ -0.2429801799032638987 , 0.23569836841299884878 , 0.94096063217417758029 ;
499
+
500
+ for (const S dim : {S (0.01 ), S (0.25 ), S (0.5 ), S (10 ), S (1000 )}) {
501
+ const Vector3<S> box_size (dim, dim, dim);
502
+
503
+ const Vector3<S> p_WA (0 , 0 , 5 * dim);
504
+ Transform3<S> X_WA;
505
+ X_WA.linear () = R_WF;
506
+ X_WA.translation () = p_WA;
507
+ Transform3<S> X_WB;
508
+ X_WB.linear () = R_WF;
509
+
510
+ // Both boxes always have the same orientation and the *stack* is always
511
+ // located at p_WA. Only the translational component of X_WB changes with
512
+ // varying separation distance.
513
+
514
+ // By design, the distances are all near epsilon. We'll scale them up for
515
+ // larger boxes to make sure the distance doesn't simply disappear in
516
+ // the rounding noise.
517
+ for (const S distance : {S (-1e-15 ), S (-2.5e-16 ), S (-1e-16 ), S (0 ), S (1e-16 ),
518
+ S (2.5e-16 ), S (1e-15 )}) {
519
+ const S scaled_distance = distance * std::max (S (1 ), dim);
520
+ const Vector3<S> p_AB_F = Vector3<S>(0 , dim + scaled_distance, 0 );
521
+
522
+ X_WB.translation () = p_WA + R_WF * p_AB_F;
523
+ SCOPED_TRACE (" dim: " + std::to_string (dim) +
524
+ " , distance: " + std::to_string (distance));
525
+ test_distance_box_box_helper (box_size, X_WA, box_size, X_WB,
526
+ &scaled_distance);
527
+ }
528
+ }
529
+ }
530
+
463
531
// This is a *specific* case that has cropped up in the wild that reaches the
464
532
// unexpected `validateNearestFeatureOfPolytopeBeingEdge` error. This error was
465
533
// reported in https://github.com/flexible-collision-library/fcl/issues/408
466
534
template <typename S>
467
535
void test_distance_sphere_box_regression1 () {
536
+ SCOPED_TRACE (" test_distance_sphere_box_regression1" );
468
537
using CollisionGeometryPtr_t = std::shared_ptr<fcl::CollisionGeometry<S>>;
469
538
const S sphere_radius = 0.06 ;
470
539
CollisionGeometryPtr_t sphere_geo (new fcl::Sphere<S>(sphere_radius));
@@ -533,6 +602,7 @@ GTEST_TEST(FCL_SIGNED_DISTANCE, RealWorldRegression) {
533
602
test_distance_box_box_regression4<double >();
534
603
test_distance_box_box_regression5<double >();
535
604
test_distance_box_box_regression6<double >();
605
+ test_distance_box_box_regression_tilted_kissing_contact<double >();
536
606
test_distance_sphere_box_regression1<double >();
537
607
}
538
608
0 commit comments