RobotLocomotion / drake

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

Prescribed Motion Joint with Lookup Table or Splines #19234

Open MarvinSt opened 1 year ago

MarvinSt commented 1 year ago

Feature request: To model complex kinematics (for example, automotive multi-link suspension geometry, see image below) efficiently for real time simulation, it is quite common to reduce this system to a single vertical and steering DOF, while using a lookup table to describe the motion of the constrained DOFs with respect to these free DOF(s) (i.e. pitch, yaw, roll, x, y depending on vertical movement and steering).

Ideal solution: Custom joint with one or two degrees of freedom (configurable) and a 1d or 2d lookup table, respectively. There is potentially cross coupling between the two inputs which needs to be dealt with (i.e. steering rack induces vertical movement). However, for a first try, I would simply try to implement prescribed motion for pitch, yaw, roll, x, y on vertical motion.

Such a joint could also be used to model other systems like variable ratio and a cam profile.

Alternatives: Have not considered any alternatives, but one could of course cheat using a quasi static transformation after each time step, however, this would not be as accurate of course. Of course, a full MBD solution is also possible, given that the run time cost is acceptable.

Additional context Such a "joint" is I believe possible to implement in libraries like Simbody and Project Chrono, it is also available in certain Dymola libraries designed for modelling automotive suspension kinematics.

EricCousineau-TRI commented 1 year ago

Assigning @amcastro-tri for disposition

FWIW: This could be modeled via a holonomic constraint h(q) = y_a(q) - y_d(t, q) = 0. I am not sure if our current coupler constraint API admits something this general.

You can check your workflow by implementing this in a controller, assuming kinematics are far enough away from singularity.

MarvinSt commented 1 year ago

Thanks for the feedback. A custom function is probably the most general implementation, allowing the user to specify the 6 DOFs of this body based on inputs of the connected frame(s). In the case of steering, this would require 2 input frames. Using an auxiliary 1D vertical prismatic joint for the vertical motion, we could do something as follows to express the upright transformation

x,y,z,r,p,y = upright_motion(steering_frame.x, aux_vertical.z)

Within this function one could perform the lookup table interpolation and perhaps a standard component with a lookup table can be provided (up to 2 input dimensions perhaps). Not sure how to deal with the higher order terms though, perhaps taking the numerical derivative from the table.

I saw that Simbody has Mobilizer::FunctionBased and Constraint::PrescribedMotion:

sherm1 commented 1 year ago

BTW Simbody also has Motion objects which are a direct implementation of prescribed motion as mixed forward/inverse dynamics (that is, no constraints). Those are by far the most efficient way to specify prescribed motion and we could do something similar in Drake.