-
Notifications
You must be signed in to change notification settings - Fork 92
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
Fixed computation of intersectsRay() for Cylinder, Box and ConvexMesh #109
Fixed computation of intersectsRay() for Cylinder, Box and ConvexMesh #109
Conversation
This would deserve a few tests, they're coming tomorrow. For the time being I verified the algorithm in RViz. |
82ec8c0
to
fcf33ca
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, this looks good to me.
Please provide a description for this PR, mentioning that this depends on other PRs.
Please also provide the promised unit tests (one of them should be failing before this fix).
9f2429b
to
d0d5b72
Compare
I added PR description and separated this PR from the others as it doesn't depend on them semantically. I'll have a look at the tests. |
d0d5b72
to
60260af
Compare
a1fa4da
to
522340c
Compare
4be04c6
to
828c146
Compare
I had a look at this again, rebased on current melodic-devel, and added a lot of tests. First, I only added box-ray tests, but then I decided to add tests for all bodies. And along the way, I've discovered and fixed a lot of other bugs in various more or less related functions, like I would've sent these other fixes as another PRs, but the tests in this one would fail without them. But if it's desired, I can take the effort and split this into more PRs - I just do not want to take this effort with the tests, so I'd separate them as the "final" PR, and the prior ones would come without tests. I did some API/ABI breaks here.
If API/ABI breaks are not desired for melodic-devel, 1) can be avoided completely (and the API break be left to noetic), and 2) can also be worked around somehow (last resort would be the translation-unit-private global variable ugly trick). For some reason, CI did not trigger here (maybe because of the pending requested changes?), but here's mine which shows okay: https://travis-ci.com/github/peci1/geometric_shapes . I've also run a local test with this PR and the whole Moveit repo. It ran fine, except for a few As with my other PRs, this may of course break user code that counted with the buggy behavior. But (thanks to the tests), I'm pretty sure that if the library is used correctly, it should not bring any new problems. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please address the inline comments. Aside from them, I approve.
Lastly, this patch conflicted with one of the others I merged. Could you please rebase? |
a7ffd0c
to
43cb6f0
Compare
I've made the requested changes. |
Thanks for the reviews, @v4hn ;) |
On Fri, Apr 24, 2020 at 10:17:21AM -0700, Martin Pecka wrote:
Thanks for the reviews, @v4hn ;)
Thanks for your continuous effort with these patches!
I still fail to understand how all these issues could ever have made it through the years...
|
I think insisting on good tests for PRs is the way to prevent most of such errors for the future. I've seen moveit repos already report some kind of test coverage... What about this repo? Is it planned? |
#120 :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
Eigen::Vector3d corner1_; | ||
Eigen::Vector3d corner2_; | ||
Eigen::Vector3d corner1_; //!< The translated, but not rotated min corner |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about renaming these vectors to min_corner_ and max_corner_?
As you renamed normal[L,W,H]
anyway, ABI and API is broken anyway and we need to target this to Noetic only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I can rename them for noetic. As I'd still like to see this in melodic, should I split this PR into two and try to make this one compatible with melodic? In my view, this approach would be easier than first merging to noetic and then backporting...
As discussed earlier, the API/ABI breaks can be avoided at the cost of minor uglification of code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To maintain ABI you would need to keep the axis vectors instead of invRot_
. More ugly, but ok.
The other addition I have seen is std::map<unsigned int, unsigned int> triangle_for_plane_
.
Didn't look for what it is actually used. Replacing this by a global variable, I would actually not support. Why is it needed now? Just to be faster?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Walking on a thin ice, I guess a Matrix3d
could take up the same amount of memory as three Vector3d
s. But that could run in many issues once memory alignment comes into play. So I rather give up this idea.
invRot
would have to be recomputed every time it is used, but as it is only a transpose, it shouldn't be that bad in melodic. I can also imagine storing the rows/cols of the inverted matrix in the abandoned vectors, but I bet the performance could be even worse than transposing it where needed.
The triangle_for_plane
is really required for efficiency - otherwise mesh-ray intersection tests would need to re-enumrate over all triangles to find which plane the current one belongs to. The global variable trick is something Gazebo people are willing to accept if it is just "temporary" to get a feature to a released version; the development version then implements the nicer, but ABI-breaking version. An example is here: gazebosim/gazebo-classic@415be40 . It creates a global map, which stores references to created objects (ConvexMesh in this case) and maps them to the structure that is needed to be added. Ugly, but works.
Actually, I'd consider making the whole MeshData
PIMPL for noetic (i.e. moving it to the .cpp file), so that storing additional data will not cause an ABI break any more. The same could be done for the other bodies, too, but there would be the additional cost of dynamic memory allocation. The ConvexMesh allocates memory anyways, so adding one more unique_ptr should not be a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I implemented ABI compatibility using the global variable.
Even according to the link to the used method, the approach should only work for axis-aligned boxes. But bodies::Box can be arbitrarily transformed. So I instead strip rotation from both the box and the ray, which gives the same results. The old implementation would fail every time the untransformed min corner ceased to be the min corner of the transformed box. # Conflicts: # src/bodies.cpp
…within the box. A false second intersection was returned in that case, but as the ray starts inside the box, there should only be one intersection.
43cb6f0
to
2f39342
Compare
Codecov Report
@@ Coverage Diff @@
## melodic-devel #109 +/- ##
=================================================
+ Coverage 46.24% 49.22% +2.98%
=================================================
Files 11 11
Lines 1691 1684 -7
=================================================
+ Hits 782 829 +47
+ Misses 909 855 -54
Continue to review full report at Codecov.
|
@rhaschke I did all the changes you requested. ABI compatibility with melodic is achieved by the very last commit. Thanks for the deep insights. The code looks much better now. |
I also restructured the commit history. Now I consider all the commits valuable and further squashing is not needed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor remarks left.
As I will not cherry-pick to noetic, but revert the last commit, please remove the comment
Do not cherry-pick this commit to noetic.
from it.
Thanks a lot for all this work. Hope, we can merge this later today.
…int by the transform of the body.
…in case the ray is touching the cylinder side. Also fixed the case when the ray goes exactly at the edge between base and sides.
The reported problems no longer occur.
…d some other bugs.
…h::intersectsRay().
2f39342
to
ed4cf13
Compare
@rhaschke I addressed your comments. |
@peci1, thank you very much. All your PRs are a great improvement of this code base!
|
I added a |
This PR fixes a multitude of problems the current implementations of
intersectsRay()
had.In Box, even according to the link to the used method, the approach should only work for axis-aligned boxes. But bodies::Box can be arbitrarily transformed. So I instead strip rotation from both the box and the ray, which gives the same results. The old implementation would fail every time the untransformed min corner ceased to be the min corner of the transformed box.
For Cylinder, there were a few cornercases when incorrect number of intersections were returned (e.g. when the ray is tangential to the cylinder or when it goes through the edge between base and sides).
For ConvexMesh, there were several problems. Many of them arose from a wrong approach to incorporate padding. Also, if a ray hit the edge of two triangles, it was reported twice.
I also restructured the tests for both
containsPoint()
andintersectsRay()
and added a lot of new tests - both randomized and testing corner cases. There is also a regression testBoxRayIntersection::Regression109
which fails on current melodic-devel and succeeds with this test.Aside from the fixes in
intersectsRay()
, I also fixedCylinder::samplePointInside()
andConvexMesh::containsPoint()
whose correct working is needed by the unit tests.