Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return the correct nearest points from distance(...) #215

Merged
merged 12 commits into from
Jun 15, 2017

Conversation

avalenzu
Copy link

This PR fixes issues in both the CCD-based and the independent GJK solvers, which caused distance to return erroneous values for the nearest points.

  • CCD-base solver: Currently the most recently computed support points are returned as the nearest points, which is incorrect. The nearest points lie in the convex-hull of the points contained in the simplex variable. The points on the original shapes can be computed from the simplex and the nearest point to the origin on the Minkowski difference, dir.
  • Independent solver: Currently, p2 is not properly transformed to its shape's (shape1) frame. toshape0 converts points from shape1 frame to shape0 frame. The points extracted from the GJK simplex are in shape0 frame, so the inverse of toshape0 needs to be applied.

The test_fcl_capsule_box_* tests contained lines that failed due to the issues described above. This PR uncomments those lines and modifies the tests to exercise both solvers.

This PR also adds a distance_tolerance member to fcl::DistanceRequest, which corresponds to the distance_tolerance and gjk_tolerance members in GJKSolver_libccd and GJKSolver_indep respectively. @jslee02, is this an appropriate way to expose this knob to the user? I didn't use abs_err because the default for that was 0.0, whereas the defaults for distance_tolerance and gjk_tolerance are 1e-6.

@avalenzu
Copy link
Author

avalenzu commented Jun 1, 2017

@jslee02, do you have any insights as to why libccd would return different results on Linux than it does on Windows and OSX? test_fcl_capsule_box_1 passes on Linux, but fails on the other two platforms.

@jslee02
Copy link
Member

jslee02 commented Jun 1, 2017

@jslee02, do you have any insights as to why libccd would return different results on Linux than it does on Windows and OSX? test_fcl_capsule_box_1 passes on Linux, but fails on the other two platforms.

One possible reason would be that fcl uses different versions of libccd for the tests depending on platforms? fcl uses 1.5 on Linux and 2.0 for the other two platforms. You could test this by manually installing libccd 2.0 on Linux for sure.

@avalenzu
Copy link
Author

avalenzu commented Jun 1, 2017

You could test this by manually installing libccd 2.0 on Linux for sure.

Hmmm. I've been using the libccd-dev package from the Xenial apt repositories (which uses the libccd 2.0 sources) on my machine, and all the tests pass for me.

@jslee02
Copy link
Member

jslee02 commented Jun 1, 2017

I realized that libccd-dev in the Ubuntu apt repository was built with double precision while macOS uses single precision. If you see the debian file, then it passes -DCCD_DOUBLE:BOOL=True option but the homebrew formula just uses the default setting that is single precision.

If this is the cause of the issue, then we might want to add a precision option to the homebrew formula.

@sherm1
Copy link
Member

sherm1 commented Jun 1, 2017

Is FCL really useful in single precision? Likely it could at least default to double everywhere, but it might be worth simply declaring that only double is supported, especially if there are unit tests that won't pass in float.

@edrumwri
Copy link

edrumwri commented Jun 1, 2017 via email

@avalenzu
Copy link
Author

avalenzu commented Jun 1, 2017

@jslee02, it looks like that's the issue. I verified that test_fcl_capsule_box_1 passes on OSX when libccd is built with double precision, and fails when libccd is build with single precision.

@avalenzu
Copy link
Author

avalenzu commented Jun 1, 2017

Thanks for finding the precision issue, @jslee02!

I think we should update the homebrew formula to use double precision. @jslee02 do you have experience editing homebrew formulae? If so, could you put in a pull request with that change? I haven't the slightest idea how to go about testing changes to homebrew configuration. I'm willing to learn, but if you already have that know-how, it would be awesome if you could put that in 😃

Additionally, is there a way to require at build time that libccd was built with double precision (i.e. that ccd_real_t is double)? As @sherm1 mentioned, it doesn't really make sense to allow building in a configuration that's known to yield wrong answers.

Copy link
Contributor

@SeanCurtis-TRI SeanCurtis-TRI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of notes. Doesn't address correctness, per se, but attempts to strengthen the code that's there.

// p - A = s*AB
//
// This defines three equations, but we only need one. Take the x
// component
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quality of this solution degrades as the line segment becomes more perpendicular to the x-axis (i.e., where B_x - A_x << 1. Ideally, you'd want to pick the axis where |B_i - A_i| is biggest.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

//
// Thus, s is given by
//
// s = (p_x - A_x)/(B_x - vA_x)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo? vA_x

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

// t = n . (AB x p') / n . (AB x AC)
double s{-ccdVec3Dot(&n, &AC_cross_v_prime) / n_dot_AB_cross_AC};
double t{ccdVec3Dot(&n, &AB_cross_v_prime) / n_dot_AB_cross_AC};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe a little algebraic manipulation simplifies the math (making it cheaper and more robust -- no square roots and fewer floating point ops).

Starting with the following definitions (and focusing only on t with the understanding that it applies directly to s:

n = AB x AC
n̂ = n / ||n||
t = n̂⋅(AC x p') / (n̂⋅(AB x AC))

We get the following:

t = n̂⋅(AC x p') / (n̂⋅(AB x AC))                              - the given equation
t = (n / ||n||)⋅(AC x p') / ((n / ||n||)⋅(AB x AC))          - substitute for n̂
t = n⋅(AC x p') / (n⋅(AB x AC))                              - cancel 1 / ||n||
t = (AB x AC)⋅(AC x p') / ((AB x AC)⋅(AB x AC))              - substitute for n
t = (AB x AC)⋅(AC x p') / ||AB x AC||²                       - simplify

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Done. PTAL.

double A_x{ccdVec3X(&(simplex->ps[0].v))};
double B_x{ccdVec3X(&(simplex->ps[1].v))};
double p_x{ccdVec3X(p)};
double s{(p_x - A_x) / (B_x - A_x)};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: extra space proceeding s

@jslee02
Copy link
Member

jslee02 commented Jun 1, 2017

@jslee02 do you have experience editing homebrew formulae? If so, could you put in a pull request with that change?

I think I could do that. Let me put that it to my list.

Copy link
Contributor

@SeanCurtis-TRI SeanCurtis-TRI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@jslee02
Copy link
Member

jslee02 commented Jun 1, 2017

Submitted a PR: Homebrew/homebrew-science#5762

@avalenzu
Copy link
Author

avalenzu commented Jun 5, 2017

I see that the homebrew PR went through! Is there a way to re-trigger the CI checks for this PR?

@avalenzu
Copy link
Author

avalenzu commented Jun 9, 2017

@jslee02, am I correct in thinking that this PR is blocked by #216?

Also, could I get your take on the last paragraph of the PR description? Thank you!

@jslee02
Copy link
Member

jslee02 commented Jun 14, 2017

Sorry for delayed response.

#216 is now merged. Could you merge master into this PR so that the CI checks are re-triggered as well?

@jslee02
Copy link
Member

jslee02 commented Jun 14, 2017

@jslee02, is this an appropriate way to expose this knob to the user?

It looks good to me. Adding a new parameter to DistanceRequest would break the API compatibility, but it would be okay because FCL 0.6.0 breaks it anyway by other changes.

@avalenzu
Copy link
Author

Is it possible that the cached libccd is still single precision on the x64 Windows machine?

@jslee02
Copy link
Member

jslee02 commented Jun 14, 2017

I believe so. Let's refresh the cache by removing it and adding it back (enabling the cache).

Andrés Valenzuela added 2 commits June 14, 2017 15:24
@avalenzu
Copy link
Author

OK, the appveyor/pr check passed once the cache was cleared. I've re-enabled the cache now.

@jslee02
Copy link
Member

jslee02 commented Jun 14, 2017

Hm, it seems the cache isn't reset by doing so. Instead, I found another method (ref1, ref2). Could you change this line

cache:
  - C:\Program Files\libccd

to

cache:
  - C:\Program Files\libccd -> appveyor.yml

?

Thanks!

Now the libccd cache should be invalidated whenever `.appveyor.yml` is modified.
@avalenzu
Copy link
Author

@jslee02: appveyor/pr is finally happy! What's being checked in appveyor/branch?

@jslee02
Copy link
Member

jslee02 commented Jun 15, 2017

I believe appveyor/branch checks for regular commits to the branch, but it seems not to work sometimes. I just removed it from the requirements as suggested in the post.

Merging this! Thank you for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants