Skip to content

Commit

Permalink
Distance queries return nearest points in the world frame
Browse files Browse the repository at this point in the history
The DistanceResult struct documents the near points as being defined in the
*world* frame. This wasn't true in the code.

1. Correct both gjk solver implementations to put the pose in *world* frame.
2. Modify sphere-sphere and sphere-capsule custom implementations to do the
   same.
3. Fix some related typos in documentation.
4. Update tests to expect points in world frame.
  • Loading branch information
SeanCurtis-TRI committed Aug 10, 2018
1 parent 9d25b53 commit c9ccab8
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 82 deletions.
13 changes: 8 additions & 5 deletions include/fcl/narrowphase/detail/gjk_solver_indep-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,10 @@ struct ShapeDistanceIndepImpl

if(distance) *distance = (w0 - w1).norm();

if(p1) *p1 = w0;
if(p2) (*p2).noalias() = shape.toshape0.inverse() * w1;
// Answer is solved in Shape1's local frame; answers are given in the
// world frame.
if(p1) p1->noalias() = tf1 * w0;
if(p2) p2->noalias() = tf1 * w1;

return true;
}
Expand Down Expand Up @@ -880,8 +882,9 @@ struct ShapeTriangleDistanceIndepImpl
}

if(distance) *distance = (w0 - w1).norm();
// The answers are produced in world coordinates. Keep them there.
if(p1) *p1 = w0;
if(p2) (*p2).noalias() = shape.toshape0 * w1;
if(p2) *p2 = w1;
return true;
}
else
Expand Down Expand Up @@ -970,8 +973,8 @@ struct ShapeTransformedTriangleDistanceIndepImpl
}

if(distance) *distance = (w0 - w1).norm();
if(p1) *p1 = w0;
if(p2) (*p2).noalias() = shape.toshape0 * w1;
if(p1) p1->noalias() = tf1 * w0;
if(p2) p2->noalias() = tf1 * w1;
return true;
}
else
Expand Down
18 changes: 0 additions & 18 deletions include/fcl/narrowphase/detail/gjk_solver_libccd-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -567,12 +567,6 @@ struct ShapeSignedDistanceLibccdImpl
p1,
p2);

if (p1)
(*p1).noalias() = tf1.inverse(Eigen::Isometry) * *p1;

if (p2)
(*p2).noalias() = tf2.inverse(Eigen::Isometry) * *p2;

detail::GJKInitializer<S, Shape1>::deleteGJKObject(o1);
detail::GJKInitializer<S, Shape2>::deleteGJKObject(o2);

Expand Down Expand Up @@ -624,12 +618,6 @@ struct ShapeDistanceLibccdImpl
p1,
p2);

if (p1)
(*p1).noalias() = tf1.inverse(Eigen::Isometry) * *p1;

if (p2)
(*p2).noalias() = tf2.inverse(Eigen::Isometry) * *p2;

detail::GJKInitializer<S, Shape1>::deleteGJKObject(o1);
detail::GJKInitializer<S, Shape2>::deleteGJKObject(o2);

Expand Down Expand Up @@ -848,8 +836,6 @@ struct ShapeTriangleDistanceLibccdImpl
dist,
p1,
p2);
if(p1)
(*p1).noalias() = tf.inverse(Eigen::Isometry) * *p1;

detail::GJKInitializer<S, Shape>::deleteGJKObject(o1);
detail::triDeleteGJKObject(o2);
Expand Down Expand Up @@ -923,10 +909,6 @@ struct ShapeTransformedTriangleDistanceLibccdImpl
dist,
p1,
p2);
if(p1)
(*p1).noalias() = tf1.inverse(Eigen::Isometry) * *p1;
if(p2)
(*p2).noalias() = tf2.inverse(Eigen::Isometry) * *p2;

detail::GJKInitializer<S, Shape>::deleteGJKObject(o1);
detail::triDeleteGJKObject(o2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,31 @@ bool sphereCapsuleDistance(const Sphere<S>& s1, const Transform3<S>& tf1,

S distance = diff.norm() - s1.radius - s2.radius;

if(distance <= 0)
if(distance <= 0) {
// NOTE: By assigning this a negative value, it allows the ultimately
// calling code in distance-inl.h (distance() method) to use collision to
// determine penetration depth and contact points. NOTE: This is a
// *horrible* thing.
// TODO(SeanCurtis-TRI): Create a *signed* distance variant of this and use
// it to determined signed distance, penetration, and distance.
if (dist) *dist = -1;
return false;
}

if(dist) *dist = distance;

if(p1 || p2) diff.normalize();
if(p1)
{
*p1 = s_c - diff * s1.radius;
*p1 = tf1.inverse(Eigen::Isometry) * tf2 * (*p1);
*p1 = tf2 * (*p1);
}

if(p2) *p2 = segment_point + diff * s1.radius;
if(p2)
{
*p2 = segment_point + diff * s2.radius;
*p2 = tf2 * (*p2);
}

return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ bool sphereSphereDistance(const Sphere<S>& s1, const Transform3<S>& tf1,
if(len > s1.radius + s2.radius)
{
if(dist) *dist = len - (s1.radius + s2.radius);
if(p1) *p1 = tf1.inverse(Eigen::Isometry) * (o1 - diff * (s1.radius / len));
if(p2) *p2 = tf2.inverse(Eigen::Isometry) * (o2 + diff * (s2.radius / len));
if(p1) *p1 = (o1 - diff * (s1.radius / len));
if(p2) *p2 = (o2 + diff * (s2.radius / len));
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions include/fcl/narrowphase/distance_result.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ struct FCL_EXPORT DistanceResult
/// @sa DistanceRequest::enable_signed_distance
S min_distance;

/// @brief Nearest points in the world coordinates
/// @brief Nearest points in the world coordinates.
///
/// @sa DeistanceRequest::enable_nearest_points
/// @sa DistanceRequest::enable_nearest_points
Vector3<S> nearest_points[2];

/// @brief collision object 1
Expand Down
8 changes: 4 additions & 4 deletions test/test_fcl_capsule_box_1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void test_distance_capsule_box(fcl::GJKSolverType solver_type, S solver_toleranc
// Nearest point on box
fcl::Vector3<S> o2 (distanceResult.nearest_points [1]);
EXPECT_NEAR (distanceResult.min_distance, 0.5, test_tolerance);
EXPECT_NEAR (o1 [0], -2.0, test_tolerance);
EXPECT_NEAR (o1 [0], 1.0, test_tolerance);
EXPECT_NEAR (o1 [1], 0.0, test_tolerance);
EXPECT_NEAR (o2 [0], 0.5, test_tolerance);
EXPECT_NEAR (o2 [1], 0.0, test_tolerance);
Expand All @@ -89,7 +89,7 @@ void test_distance_capsule_box(fcl::GJKSolverType solver_type, S solver_toleranc
EXPECT_NEAR (distanceResult.min_distance, 2.0, test_tolerance);
EXPECT_NEAR (o1 [0], 0.0, test_tolerance);
EXPECT_NEAR (o1 [1], 0.0, test_tolerance);
EXPECT_NEAR (o1 [2], -4.0, test_tolerance);
EXPECT_NEAR (o1 [2], 4.0, test_tolerance);

EXPECT_NEAR (o2 [0], 0.0, test_tolerance);
EXPECT_NEAR (o2 [1], 0.0, test_tolerance);
Expand All @@ -107,9 +107,9 @@ void test_distance_capsule_box(fcl::GJKSolverType solver_type, S solver_toleranc
o2 = distanceResult.nearest_points [1];

EXPECT_NEAR (distanceResult.min_distance, 5.5, test_tolerance);
EXPECT_NEAR (o1 [0], 0.0, test_tolerance);
EXPECT_NEAR (o1 [0], -6.0, test_tolerance);
EXPECT_NEAR (o1 [1], 0.0, test_tolerance);
EXPECT_NEAR (o1 [2], 4.0, test_tolerance);
EXPECT_NEAR (o1 [2], 0.0, test_tolerance);
EXPECT_NEAR (o2 [0], -0.5, test_tolerance);
EXPECT_NEAR (o2 [1], 0.0, test_tolerance);
EXPECT_NEAR (o2 [2], 0.0, test_tolerance);
Expand Down
6 changes: 3 additions & 3 deletions test/test_fcl_capsule_box_2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ void test_distance_capsule_box(fcl::GJKSolverType solver_type, S solver_toleranc
fcl::Vector3<S> o2 = distanceResult.nearest_points [1];

EXPECT_NEAR (distanceResult.min_distance, 5.5, test_tolerance);
EXPECT_NEAR (o1 [0], 0.0, test_tolerance);
EXPECT_NEAR (o1 [1], 0.0, test_tolerance);
EXPECT_NEAR (o1 [2], 4.0, test_tolerance);
EXPECT_NEAR (o1 [0], -6.0, test_tolerance);
EXPECT_NEAR (o1 [1], 0.8, test_tolerance);
EXPECT_NEAR (o1 [2], 1.5, test_tolerance);
EXPECT_NEAR (o2 [0], -0.5, test_tolerance);
EXPECT_NEAR (o2 [1], 0.8, test_tolerance);
EXPECT_NEAR (o2 [2], 1.5, test_tolerance);
Expand Down
31 changes: 23 additions & 8 deletions test/test_fcl_distance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#include "fcl/narrowphase/detail/traversal/collision_node.h"
#include "test_fcl_utility.h"
#include "eigen_matrix_compare.h"
#include "fcl_resources/config.h"

// TODO(SeanCurtis-TRI): A file called `test_fcl_distance.cpp` should *not* have
Expand Down Expand Up @@ -315,6 +316,10 @@ void NearestPointFromDegenerateSimplex() {
// line segment. As a result, nearest points were populated with NaN values.
// See https://github.com/flexible-collision-library/fcl/issues/293 for
// more discussion.
// This test is only relevant if box-box distance is computed via GJK. If
// a custom test is created, this may no longer be relevant.
// TODO(SeanCurtis-TRI): Provide some mechanism where we can assert what the
// solving algorithm is (i.e., default convex vs. custom).
DistanceResult<S> result;
DistanceRequest<S> request;
request.enable_nearest_points = true;
Expand All @@ -335,15 +340,25 @@ void NearestPointFromDegenerateSimplex() {

EXPECT_NO_THROW(fcl::distance(&box_object_1, &box_object_2, request, result));

// The values here have been visually confirmed from the computation.
// These hard-coded values have been previously computed and visually
// inspected and considered to be the ground truth for this very specific
// test configuration.
S expected_dist{0.053516322172152138};
Vector3<S> expected_p0{-1.375, -0.098881502700918666, -0.025000000000000022};
Vector3<S> expected_p1{0.21199965773384655, 0.074999692703297122,
0.084299993303443954};
EXPECT_TRUE(nearlyEqual(result.nearest_points[0], expected_p0));
EXPECT_TRUE(nearlyEqual(result.nearest_points[1], expected_p1));
// TODO(SeanCurtis-TRI): Change this tolerance to constants<S>::eps_34() when
// the mac single/double libccd problem is resolved.
// The "nearest" points (N1 and N2) measured and expressed in box 1's and
// box 2's frames (B1 and B2, respectively).
const Vector3<S> expected_p_B1N1{-1.375, -0.098881502700918666,
-0.025000000000000022};
const Vector3<S> expected_p_B2N2{0.21199965773384655, 0.074999692703297122,
0.084299993303443954};
// The nearest points in the world frame.
const Vector3<S> expected_p_WN1 =
box_object_1.getTransform() * expected_p_B1N1;
const Vector3<S> expected_p_WN2 =
box_object_2.getTransform() * expected_p_B2N2;
EXPECT_TRUE(CompareMatrices(result.nearest_points[0], expected_p_WN1,
DELTA<S>(), MatrixCompareType::absolute));
EXPECT_TRUE(CompareMatrices(result.nearest_points[1], expected_p_WN2,
DELTA<S>(), MatrixCompareType::absolute));
EXPECT_NEAR(expected_dist, result.min_distance,
constants<ccd_real_t>::eps_34());
}
Expand Down
Loading

0 comments on commit c9ccab8

Please sign in to comment.