RobotLocomotion / drake

Model-based design and verification for robotics.
https://drake.mit.edu
Other
3.23k stars 1.25k forks source link

Adding a simple ForceElement to an MbP is very hard #12697

Open ggould-tri opened 4 years ago

ggould-tri commented 4 years ago

(This is a metabug; subsidiary issues should be opened for its contributing factors if they are judged sufficiently individually buggy)

A real-world system I am modeling has a hinge with complex dynamics (static, dynamic, and viscous friction, a catch, and a spring). I decided to model this by creating a ForceElement, and wrote the necessary four functions (force, energy, non-conservative power, and conservative power) on double as well as a class that took a Joint to apply this to.

The resulting odyssey is chronicled on slack:

The major problems that I encountered:

Of course each of the above also suffers from its own incomprehensibility problem:

Which of these problems are or aren't worth solving -- and if so how -- will doubtless be a matter of some controversy. However I think there is a meta defect here that we have made a straightforward matter (a couple of dozen lines of math) into a journey through the heart of darkness of forwarding constructors, templates of templates, and the objects-versus-IDs mess. An object which could conceptually be two symbolic expressions (energy, nonconservative power) and a correspondence to joint {q,v} (or even just one function of double, given that energy and power are unused) is instead somewhat north of our maximum code-review length even without tests.

ggould-tri commented 4 years ago

After some cleanup, https://gist.github.com/ggould-tri/b686cf978754bc2bffe55ee99daff8a5 is the (now much simplified) form the code ended up in.

Bad things that could be resolved but only by adding yet more code:

Bad things that I think cannot be avoided on current architecture:

Bad things resulting from bad API docs:

jwnimmer-tri commented 4 years ago

Another complaint... The entire ForceElement API towards its subclasses mentions multibody::internal namespace frequently -- for the MultibodyTree, PositionKinematicsCache, etc.

Since users shall not touch things in internal namespace, it's not possible to legally implement a new ForceElement.