Forward Dynamics vs Hybrid Dynamics in DART: Key Differences Explained
Forward dynamics computes accelerations from forces using the Articulated-Body Algorithm, while hybrid dynamics is a usage pattern that mixes different joint actuator types—such as passive, velocity-controlled, and locked joints—within the same simulation step.
The Dynamic Animation and Robotics Toolkit (DART) provides two related but distinct concepts for simulating articulated rigid-body systems. Understanding the difference between forward dynamics and hybrid dynamics in DART is essential for choosing the right approach for physics-based character animation, robotics control, or mixed kinematic-physical simulations.
What Is Forward Dynamics in DART?
Forward dynamics is the core physics routine that computes the motion of a skeleton from the forces and torques acting upon it. In dart/dynamics/Skeleton.cpp, the method Skeleton::computeForwardDynamics() implements this by solving the articulated-body equation:
M·ddq + C + G = τ + Jᵀ·λ
Where M is the mass matrix, ddq is the acceleration vector, C and G are Coriolis and gravity terms, τ is the joint force vector, and λ represents constraint impulses from contacts.
The mathematical core combines the Articulated-Body Algorithm (ABA) for efficient mass-matrix computations with a Linear Complementarity Problem (LCP) solver for handling contacts and joint limits. This integration occurs at line 3855 of Skeleton.cpp, where the system builds the constraint matrix and solves for the Lagrange multipliers before integrating accelerations into velocities and positions.
What Is Hybrid Dynamics in DART?
Hybrid dynamics is not a separate solver but a configuration pattern that allows a single skeleton to contain joints with different actuator types. While forward dynamics treats all joints uniformly as passive dynamic elements, hybrid dynamics lets you designate specific joints as velocity-controlled, acceleration-controlled, force-controlled, or locked.
Each Joint object stores an ActuatorType enum that instructs the dynamics engine how to treat that DOF during computeForwardDynamics():
Joint::PASSIVE– The joint follows standard forward dynamics; forces are computed from the physics solver.Joint::VELOCITY– The joint’s commanded velocity is enforced directly as a kinematic constraint, bypassing acceleration computation for that DOF.Joint::LOCKED– The joint is fixed with zero velocity; the solver adds a hard constraint to maintain the current position.
The engine still calls the same forward dynamics routine, but it modifies the system matrices to reflect the prescribed motions of velocity-controlled or locked joints. This effectively partitions the skeleton into dynamic and kinematic subsystems within a single simulation step.
Key Differences Between Forward Dynamics and Hybrid Dynamics
| Aspect | Forward Dynamics | Hybrid Dynamics |
|---|---|---|
| Primary Goal | Compute accelerations from forces and constraints for all DOFs. | Combine different control modes (passive, velocity, locked) within one skeleton. |
| Mathematical Treatment | Solves full articulated-body equations with ABA + LCP for all joints uniformly. | Modifies boundary conditions for specific joints while using the same ABA+LCP core. |
| API Usage | Call skeleton->computeForwardDynamics() or world->step(). |
Call joint->setActuatorType() to configure modes before stepping. |
| Joint Behavior | All joints respond to physics forces and torques. | Some joints follow scripted trajectories (velocity) or stay fixed (locked). |
| Use Case | Pure physics simulation, robotics dynamics analysis. | Animation blending, teleoperation, mixed real-virtual control. |
Practical Implementation: Using Hybrid Dynamics in DART
The hybrid dynamics pattern appears in examples/hybrid_dynamics/main.cpp, where a humanoid skeleton mixes passive and controlled joints. Here is the essential implementation pattern:
// Load skeleton and set floating base to passive (dynamic)
SkeletonPtr skel = world->getSkeleton(1);
skel->getJoint(0)->setActuatorType(Joint::PASSIVE);
// Set arm joints to velocity-controlled (kinematic)
for (std::size_t i = 1; i < skel->getNumBodyNodes(); ++i) {
skel->getJoint(i)->setActuatorType(Joint::VELOCITY);
skel->getJoint(i)->setCommand(0, targetVelocity); // Set desired velocity
}
// Runtime switching: lock and unlock the pelvis
Joint* pelvis = skel->getBodyNode("h_pelvis")->getParentJoint();
pelvis->setActuatorType(Joint::LOCKED); // Fix position
// ... later ...
pelvis->setActuatorType(Joint::PASSIVE); // Release to physics
When computeForwardDynamics() executes, it detects the actuator types and treats the velocity joints as kinematic constraints while solving dynamics for the passive joints. The LCP solver still handles contacts involving all bodies, ensuring consistent physical interaction between dynamic and kinematic segments.
When to Use Forward Dynamics vs Hybrid Dynamics
Choose forward dynamics when:
- Simulating passive robotic systems where all joints obey Newton-Euler equations.
- Analyzing contact dynamics or stability without external motion scripting.
- All actuators are modeled as force/torque sources applied to passive joints.
Choose hybrid dynamics when:
- Animating characters where some limbs follow motion capture data (velocity control) while others react physically.
- Implementing teleoperation where a robot’s base is dynamic but the end-effector follows a commanded trajectory.
- Creating safety locks that fix specific joints during part of a simulation (e.g.,
Joint::LOCKEDduring calibration).
Summary
- Forward dynamics is DART’s core physics solver that computes accelerations for all degrees of freedom using the Articulated-Body Algorithm and LCP constraint resolution, implemented in
Skeleton::computeForwardDynamics(). - Hybrid dynamics is a usage pattern that configures individual joints with different
ActuatorTypemodes (PASSIVE,VELOCITY,LOCKED) to mix physics-based and kinematic control within the same simulation step. - Both use the same underlying mathematical core; hybrid dynamics modifies the boundary conditions for specific joints while reusing the forward dynamics solver.
- The
examples/hybrid_dynamics/main.cppfile demonstrates runtime switching between locked and passive modes for character animation.
Frequently Asked Questions
What is the mathematical core of forward dynamics in DART?
The mathematical core combines the Articulated-Body Algorithm (ABA) for efficient computation of mass-matrix-vector products with a Linear Complementarity Problem (LCP) solver for contact and constraint resolution. This solves the equation M·ddq + C + G = τ + Jᵀ·λ to determine accelerations ddq for all degrees of freedom.
How does hybrid dynamics differ from inverse dynamics?
Hybrid dynamics mixes forward dynamics (physics simulation) with kinematic control (prescribed motions) within the same skeleton. Inverse dynamics, by contrast, computes the forces or torques required to achieve a desired acceleration trajectory. DART’s hybrid dynamics does not compute inverse dynamics; it instead constrains certain joints to follow commanded velocities while solving forward dynamics for the remaining passive joints.
Can I switch actuator types at runtime in DART?
Yes. You can change a joint’s actuator type at any time by calling joint->setActuatorType() with values like Joint::PASSIVE, Joint::VELOCITY, or Joint::LOCKED. The examples/hybrid_dynamics/main.cpp file demonstrates this by toggling a pelvis joint between LOCKED and PASSIVE modes during simulation to lock and unlock the character’s base.
Where can I find the hybrid dynamics example code?
The official example is located at examples/hybrid_dynamics/main.cpp in the DART repository. This file demonstrates how to load a humanoid skeleton, configure different joints with PASSIVE, VELOCITY, and LOCKED actuator types, and handle keyboard events to switch between locked and passive modes for the pelvis joint during the simulation loop.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →