-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Make C++ RigidBodyManipulator methods capable of handling double, TrigPoly, AutoDiffScalar inputs #1199
Comments
I started investigating this a bit. I think there are currently two roadblocks:
I'm now of the opinion that Number 2 should be tackled first. What makes it tricky is that the methods are currently virtual, and it's not possible to have a templated virtual method. I've mocked up two possible solutions for this. See https://www.dropbox.com/s/hf8vd8i54l5bubm/DrakeJointMockup.zip?dl=0. Option 1 comes from a StackOverflow answer. I really like Option 2, which uses the curiously recurring template pattern (CRTP). Don't be afraid, it's really not all that hard to understand. Eigen uses it too. Basically, the inheritance diagram is:
Advantages of this approach:
|
Awesome. I can't look at the zip easily (on my phone), but the design pattern you've described below seems perfectly reasonable to me. The Impl class feels pretty analogous to an explicit instantiation.
|
I like option 2 more. P.S. @RussTedrake if you want to take a look at the stack overflow answer that outlines option 1 without opening the zip file, here's the link http://stackoverflow.com/a/5872633/2228557 |
Thanks John. I also like option 2 more.
|
I just put it on github here: https://github.com/tkoolen/DrakeJointMockup Good, unless there are any more comments today I'll start working on it. |
Some thoughts on this issue after experimenting a bit. We should use fixed size vectors for derivatives wherever possibleGradient computations using
So incredibly, AutoDiffScalar gradient computation is actually faster than user gradients in this case, as long as you use fixed size vectors! The question is how to handle higher level methods, where gradients w.r.t. dynamic-size vectors such as q and v are desired. We could consolidate
|
@psiorx and I made some good progress on this this week. See https://github.com/tkoolen/drake/tree/tk-kinematics-cache We pulled the kinematics cache out of RigidBody and RigidBodyManipulator and put it into As an intermediate step, we had a I'll need to do some profiling to see whether the continuous KinematicsCache allocation and deallocation is too expensive. There are workarounds if that is the case. Note that this also resolves #1167 and allows multiple 'active' mex kinsols at the same time, which is great for trajectory optimization. |
it would be amazing to zap all of the gradient code and use autodiff scalar everywhere. it would be really good to understand how that 7.14 number could change if you were to really scrutinize the motionSubspace code to avoid any internal dynamic memory allocation. (and it will be really good to test it on the kinematics/dynamics methods!) |
I just got the first TaylorVar mex call to work! I can compute the gradient of a mass matrix by calling a mex function with TaylorVar inputs, and the gradient matches the numerical gradient! |
Awesome! What's the speed like? On Wed, Aug 26, 2015, 8:40 PM Twan Koolen notifications@github.com wrote:
|
Haven't tested yet, I'll let you know. |
Here's a comparison between the various C++ methods for computing the mass matrix and its gradient for Atlas.
I included gradient computations with a fixed size derivative vector because Russ came up with the idea of fixing the number of states etc. at compile time if you know which URDF you're going to load. I'm not 100% happy with the last row of the table. It's weird that the time spent in doKinematicsmex doesn't decrease. I'll have to investigate this a little more. If we can get the doKinematicsmex time to decrease as much as the massMatrixmex time, this could be pretty cool. I was also able to compute TaylorVar gradients of the user gradient output (i.e. second order gradients of the mass matrix) by the way. |
Super super exciting to be at the point where you can get these numbers. I'd be looking really hard for hidden dynamic allocations in the doKinematics case. Agreed that it would be amazing if we can get those times down. Another option, perhaps, is to have template specialization and effectively user gradients, but using the autodiff data structure, for just the few methods where it makes a really big difference. If everything is in the autodiff data structure, then we could still use the templated autodiff inside the loop for eg the geometry transformations, and only have our user gradients at the level where we really know sometime special eg about the sparsity. That actually feels like the most likely and optimal conclusion of all this.
|
I just did some profiling. Caveat: I used Instruments, which apparently comes standard on OSX and seems awesome, but I haven't used it before so not sure how trustworthy it is yet. Results:
|
New results. I did this just in C++, so there's no longer any Matlab overhead. Still calling doKinematics and massMatrix. No longer creating a KinematicsCache object in the loop (reusing an existing one).
So using fixed size derivative types with AutoDiffScalar is in this case three times faster than our user gradients! I think it's likely that these results would be significantly different if we were to use fixed size types in our user gradients as well, but I'm pretty happy about this. |
fantastic! also super exciting is that the dynamic sizes are only 3x worse than the user gradients. if we keep seeing numbers like this, then i’d say it’s close enough that we should make the switch and never look back (especially since we could potentially help with the sparsity later).
|
I have a feeling that it would be hard to get the It poses a bit of a tough problem of weighing runtime against compile time if you have a bunch of robots with different size state vectors. One other option we could explore is having fixed maximum size vectors for the derivative type, e.g. |
I think it’s possible we could save loads of time if we get the big part of the sparsity down. Or play some tricks to pre-allocate (dynamically, just not inside the loop). Almost certainly not down to the fixed size, but maybe to the user grads. I still also like the idea of (eventually) templating the RBM class with num_positions / velocities, so that we can get the performance we want on a few special robots.
|
I worked around some issues with fixed max size AutoDiffScalars and added a new row to the table above. Fixed max size AutoDiff lands between fixed size AutoDiff and user gradients. So I think that using fixed maximum size matrices is a very viable option, as it's still pretty fast while limiting the number of template method instantiations required. For most stuff, you could use the instantiation for fixed max size AutoDiffScalar up to maybe size 100, and for larger derivative vector sizes you can fall back to using I still need to investigate the issues I had to work around more. Hopefully I can track them down and propose a fix to the Eigen devs. |
i believe we can consider this one resolved. (which is awesome!) |
Opening an official issue for this.
Having this capability would allow us to get rid of the RigidBodyManipulator code duplication between Matlab and C++ and make things faster.
The text was updated successfully, but these errors were encountered: