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

Automatically update CollisionGroups #1112

Merged
merged 19 commits into from
Oct 24, 2018

Conversation

mxgrey
Copy link
Member

@mxgrey mxgrey commented Sep 17, 2018

This PR adds features to allow CollisionGroup objects to subscribe to Skeleton and BodyNode objects, so that any changes to the properties of either of those structures will get reflected in the collision results.

The implementation here might be a bit crude, but I tried my best to have it require as few overhead operations as possible, especially when no changes are being made to the Skeletons and BodyNodes.

I still plan on doing some more cleanup and writing more tests (so far I've only written one test, which shows a World getting automatically updated), so I'm marking this PR as a WIP for now. But I wanted to open it so that feedback is possible while I finish it up.


Before creating a pull request

  • Document new methods and classes
  • Format new code files using clang-format

Before merging a pull request

  • Set version target by selecting a milestone on the right side
  • Summarize this change in CHANGELOG.md
  • Add unit test(s) for this change

@mxgrey mxgrey requested a review from jslee02 September 17, 2018 10:37
@mxgrey
Copy link
Member Author

mxgrey commented Sep 17, 2018

Note that this PR will fix #664 and #368

@mxgrey
Copy link
Member Author

mxgrey commented Sep 17, 2018

As of right now this does not address #197, but we can fix that pretty easily by "versioning" the Shape objects.

@mxgrey
Copy link
Member Author

mxgrey commented Sep 18, 2018

I'm attempting to add tests for Bullet and ODE collision detectors, but the Factory approach doesn't seem to be working. It looks like each library is supposed to register its collision detector with the static Factory when the library is loaded, but if an executable doesn't use any symbols from the library, then the linker will not bother having the executable link to the library (even though I'm instructing it to link using target_link_libraries(~)), and so it doesn't get loaded when the executable is run.

@jslee02 : Do you know a way to force a test to load a library without calling its symbols? In this case, I'm referring to test_CollisionGroups.cpp specifically. I'm attempting to link the libraries here.

@jslee02
Copy link
Member

jslee02 commented Sep 19, 2018

You're right. It seems there is no way at least with the current implementation. I've genuinely wondered if there is a nice solution for this.

I guess it's related to #1079 and #1040 (#1040 (comment)).

@mxgrey
Copy link
Member Author

mxgrey commented Sep 21, 2018

I agree that #1079 is related, but I don't think #1040 is related. The issue (as far as I can tell) is not about the visibility of symbols, but rather it's about whether the linker decides to link the executable to the library, as requested by the build system.

On this topic, I've noticed something interesting. When I build using gcc/g++, here's what I get when I run $ ldd test_CollisionGroups:

	linux-vdso.so.1 (0x00007ffffb98b000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0e3a984000)
	libdartd.so.6.7 => /home/grey/projects/dartsim/build/user/dart/lib/libdartd.so.6.7 (0x00007f0e38151000)
	libode.so.6 => /usr/lib/x86_64-linux-gnu/libode.so.6 (0x00007f0e37e33000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f0e37aa5000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f0e3788d000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0e3749c000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f0e3aeb8000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0e37298000)
	libfcl.so.0.5 => /usr/lib/x86_64-linux-gnu/libfcl.so.0.5 (0x00007f0e367b0000)
	libassimp.so.4 => /usr/lib/x86_64-linux-gnu/libassimp.so.4 (0x00007f0e35de5000)
	libboost_regex.so.1.65.1 => /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.65.1 (0x00007f0e35add000)
	libboost_system.so.1.65.1 => /usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1 (0x00007f0e358d8000)
	libboost_filesystem.so.1.65.1 => /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1 (0x00007f0e356be000)
	libdart-external-odelcpsolverd.so.6.7 => /home/grey/projects/dartsim/build/user/dart/dart/external/odelcpsolver/libdart-external-odelcpsolverd.so.6.7 (0x00007f0e354af000)
	liboctomap.so.1.8 => /usr/lib/liboctomap.so.1.8 (0x00007f0e3526b000)
	liboctomath.so.1.8 => /usr/lib/liboctomath.so.1.8 (0x00007f0e35065000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0e34cc7000)
	libccd.so.2 => /usr/lib/x86_64-linux-gnu/libccd.so.2 (0x00007f0e34abc000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f0e3489f000)
	libminizip.so.1 => /usr/lib/x86_64-linux-gnu/libminizip.so.1 (0x00007f0e34694000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f0e3448c000)
	libicui18n.so.60 => /usr/lib/x86_64-linux-gnu/libicui18n.so.60 (0x00007f0e33feb000)
	libicuuc.so.60 => /usr/lib/x86_64-linux-gnu/libicuuc.so.60 (0x00007f0e33c34000)
	libicudata.so.60 => /usr/lib/x86_64-linux-gnu/libicudata.so.60 (0x00007f0e3208b000)

You might notice that libdart-collision-bullet.so is missing from the list of linked libraries.

On the other hand, when I build using clang/clang++, I get this:

	linux-vdso.so.1 (0x00007ffd514a8000)
	libdart-collision-bullet.so.6.7 => /home/grey/projects/dartsim/build/user/dart/Default/lib/libdart-collision-bullet.so.6.7 (0x00007ff965b94000)
	libdart-collision-ode.so.6.7 => /home/grey/projects/dartsim/build/user/dart/Default/lib/libdart-collision-ode.so.6.7 (0x00007ff965982000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff965763000)
	libBulletDynamics.so.2.87 => /usr/lib/x86_64-linux-gnu/libBulletDynamics.so.2.87 (0x00007ff9654a8000)
	libBulletCollision.so.2.87 => /usr/lib/x86_64-linux-gnu/libBulletCollision.so.2.87 (0x00007ff9651a9000)
	libLinearMath.so.2.87 => /usr/lib/x86_64-linux-gnu/libLinearMath.so.2.87 (0x00007ff964f87000)
	libBulletSoftBody.so.2.87 => /usr/lib/x86_64-linux-gnu/libBulletSoftBody.so.2.87 (0x00007ff964d40000)
	libdart.so.6.7 => /home/grey/projects/dartsim/build/user/dart/Default/lib/libdart.so.6.7 (0x00007ff9644cd000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff9642c9000)
	libccd.so.2 => /usr/lib/x86_64-linux-gnu/libccd.so.2 (0x00007ff9640be000)
	libfcl.so.0.5 => /usr/lib/x86_64-linux-gnu/libfcl.so.0.5 (0x00007ff9635d6000)
	libassimp.so.4 => /usr/lib/x86_64-linux-gnu/libassimp.so.4 (0x00007ff962c0b000)
	libboost_regex.so.1.65.1 => /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.65.1 (0x00007ff962903000)
	libboost_system.so.1.65.1 => /usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1 (0x00007ff9626fe000)
	libboost_filesystem.so.1.65.1 => /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1 (0x00007ff9624e4000)
	libdart-external-odelcpsolver.so.6.7 => /home/grey/projects/dartsim/build/user/dart/Default/dart/external/odelcpsolver/libdart-external-odelcpsolver.so.6.7 (0x00007ff9622d3000)
	liboctomap.so.1.8 => /usr/lib/liboctomap.so.1.8 (0x00007ff96208f000)
	liboctomath.so.1.8 => /usr/lib/liboctomath.so.1.8 (0x00007ff961e89000)
	libode.so.6 => /usr/lib/x86_64-linux-gnu/libode.so.6 (0x00007ff961b6b000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff9617dd000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff96143f000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff961227000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff960e36000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ff965daa000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007ff960c19000)
	libminizip.so.1 => /usr/lib/x86_64-linux-gnu/libminizip.so.1 (0x00007ff960a0e000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007ff960806000)
	libicui18n.so.60 => /usr/lib/x86_64-linux-gnu/libicui18n.so.60 (0x00007ff960365000)
	libicuuc.so.60 => /usr/lib/x86_64-linux-gnu/libicuuc.so.60 (0x00007ff95ffae000)
	libicudata.so.60 => /usr/lib/x86_64-linux-gnu/libicudata.so.60 (0x00007ff95e405000)

Notice that this does have libdart-collision-bullet.so.6.7 and libdart-collision-ode.so.6.7.

So it seems to just boil down to the discretion of the program that's used for linking, which is a deeply unsatisfying conclusion.

@mxgrey
Copy link
Member Author

mxgrey commented Sep 21, 2018

One approach I can think of that would guarantee that the library gets linked is to use the dlfcn library (or on Windows, dlfcn-win32). This wouldn't be as convenient for users, because it requires you to know the external library location at runtime, but we could at least use it to ensure that our tests are able to link against all the collision libraries, regardless of which compiler is used to build them.

@codecov
Copy link

codecov bot commented Sep 21, 2018

Codecov Report

Merging #1112 into release-6.7 will increase coverage by 0.47%.
The diff coverage is 80.3%.

@@               Coverage Diff               @@
##           release-6.7    #1112      +/-   ##
===============================================
+ Coverage        55.87%   56.34%   +0.47%     
===============================================
  Files              343      344       +1     
  Lines            25192    25461     +269     
===============================================
+ Hits             14076    14347     +271     
+ Misses           11116    11114       -2
Impacted Files Coverage Δ
dart/common/detail/Factory-impl.hpp 100% <ø> (ø) ⬆️
dart/dynamics/ShapeFrame.hpp 77.77% <ø> (-2.23%) ⬇️
dart/collision/CollisionDetector.cpp 98.03% <ø> (+5.88%) ⬆️
dart/common/Factory.hpp 100% <ø> (ø) ⬆️
dart/collision/bullet/BulletCollisionObject.hpp 100% <ø> (ø) ⬆️
dart/collision/dart/DARTCollisionDetector.hpp 100% <ø> (ø) ⬆️
dart/dynamics/CapsuleShape.cpp 54% <0%> (-2.25%) ⬇️
dart/dynamics/CylinderShape.cpp 55.81% <0%> (-2.73%) ⬇️
dart/collision/bullet/BulletCollisionGroup.cpp 42.42% <0%> (ø) ⬆️
dart/dynamics/ConeShape.cpp 39.53% <0%> (-1.93%) ⬇️
... and 34 more

@mxgrey mxgrey added this to the DART 6.7.0 milestone Sep 24, 2018
@mxgrey mxgrey changed the title [WIP] Automatically update CollisionGroups Automatically update CollisionGroups Sep 24, 2018
@mxgrey
Copy link
Member Author

mxgrey commented Sep 24, 2018

I'm removing [WIP] because I believe this is ready to be reviewed. I might still need to take care of some housekeeping on it, though.

The implementation wound up being significantly more complicated than what I was originally hoping for, but I believe I've gotten it to be air-tight with the smallest possible run-time overhead.

@jslee02
Copy link
Member

jslee02 commented Sep 24, 2018

@mxgrey Thanks for this great changes! Overall looks good to me. Let me take a look at the details soon.

Copy link
Member

@jslee02 jslee02 left a comment

Choose a reason for hiding this comment

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

Automatic update control
The current implementation allows us to programmatically turn off the automatic update of the collision group even when a body node or skeleton is subscribed. I'm okay with that, but just wonder if we would have a use case of turning off the automatic update for the subscribing objects.

Supporting Objects
Currently, this API only supports BodyNode and Skeleton. I see the reason MetaSkeleton isn't supported yet. Are we going to support other types like ShapeFrame and CollisionGroup?


};

/// \private Implementation of addShapeFrame. The source argument tells us
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Good to learn \private Doxygen keyword! But, according to the documentation, it's only necessary for a language that doesn't have the concept of protection level natively like C++. Is there a reason we want to use this keyword explicitly?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, I got into a habit of applying it to everything that's private, because it's needed to hide things like private implementation classes. I didn't realize that private functions will automatically be hidden. I'll remove this.

/// \private Implementation of addShapeFrame. The source argument tells us
/// whether this ShapeFrame is being requested explicitly by the user or
/// implicitly through a BodyNode, Skeleton, or other CollisionGroup.
ObjectInfo* _addShapeFrameImpl(
Copy link
Member

Choose a reason for hiding this comment

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

Nit: I see the point you used a leading underscore for private member functions, but I don't think that's our convention. Could you remove it?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think the convention varies a bit throughout the source code, but that's probably just because I have a long-time habit of decorating private things with underscores (I like to make it obvious from the function name that a function isn't part of the public API). I can remove it if it's bothersome.

const Others&... others)
{
const auto collisionShapeNodes =
bodyNode->getShapeNodesWith<dynamics::CollisionAspect>();
Copy link
Member

Choose a reason for hiding this comment

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

This can be moved into the below if-statement to avoid unnecessary computation.

dart/collision/CollisionGroup.cpp Show resolved Hide resolved
dart/collision/CollisionGroup.hpp Show resolved Hide resolved
dart/collision/CollisionGroup.cpp Show resolved Hide resolved
const dynamics::BodyNode*, BodyNodeSource>;

/// \private Internal function called to update a Skeleton source
bool _updateSkeletonSource(SkeletonSources::value_type& entry);
Copy link
Member

Choose a reason for hiding this comment

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

Nit: It seems this function returns true if an update is necessary. Could you add a documentation about it? Ditto for the below two functions.

dart/collision/CollisionGroup.cpp Outdated Show resolved Hide resolved
Copy link
Member

@jslee02 jslee02 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 to me!

@mxgrey
Copy link
Member Author

mxgrey commented Oct 24, 2018

The codacy complaints are false negatives, and the Appveyor failure seems to be a mysterious ICE unrelated to this PR which we can track under issue #1180. I'll go ahead and merge this now.

@mxgrey mxgrey merged commit 84bb83a into release-6.7 Oct 24, 2018
@jslee02
Copy link
Member

jslee02 commented Oct 24, 2018

Yeah, some codacy complaints are false negatives. Let's fix that we think necessary. Thanks for merging this!

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.

2 participants