How DART Handles Soft Body Dynamics and Soft Contact Constraints: A Complete Technical Guide

DART implements soft body dynamics using a mass-spring system centered on SoftBodyNode with point masses, and resolves soft contacts through a specialized SoftContactConstraint class that integrates directly into the constraint-based solver.

DART (Dynamic Animation and Robotics Toolkit) extends its rigid-body physics engine to support deformable objects through a specialized soft-body architecture. The implementation, found in the dartsim/dart repository, follows the formulation described by Sumit Jain and C. Karen Liu in their "Soft Contacts" research, enabling realistic simulation of soft-rigid and soft-soft interactions within a unified constraint-based framework.

Soft Body Architecture and Core Components

DART models deformable objects using a mass-spring-damper representation rather than finite element methods. This approach balances computational efficiency with realistic deformation behavior.

SoftBodyNode and Point Mass Representation

The SoftBodyNode class, defined in dart/dynamics/soft_body_node.hpp, serves as the primary container for soft body dynamics. Unlike rigid BodyNode instances, a SoftBodyNode maintains a collection of PointMass objects stored in mPointMasses. Each point mass tracks its individual position, velocity, and mass value, forming a dynamic graph connected by springs and dampers.

Key properties governing the material behavior reside in SoftBodyNodeUniqueProperties (accessed via the aspect system) and include:

  • kv: Vertex stiffness controlling resistance to volume deformation
  • ke: Edge stiffness governing spring constants between connected masses
  • dampCoeff: Damping coefficient for internal energy dissipation

The SoftBodyNodeHelper utility within the same header provides convenience functions like setBox(), setSphere(), and setCylinder() to generate common geometric configurations with automatically populated point mass lattices.

SoftBodyAspect and State Management

DART utilizes its aspect architecture to separate soft-body data from the core rigid-body system while maintaining integration within the simulation pipeline. The SoftBodyAspect class, located in dart/dynamics/detail/soft_body_node_aspect.hpp, encapsulates:

  • SoftBodyNodeUniqueState: Current positions, velocities, and the augmented mass matrix
  • SoftBodyNodeUniqueProperties: Material parameters and connectivity data

During each simulation step, the aspect updates the augmented mass matrix via updateMassMatrix(), assembling contributions from all point masses into the global system that the constraint solver processes.

SoftMeshShape for Visualization

To render deformable objects, DART provides SoftMeshShape in dart/dynamics/soft_mesh_shape.hpp. This shape class dynamically constructs a triangle mesh from the current point mass positions, allowing real-time visualization of deformation without affecting the physics simulation.

Soft Contact Constraint Mechanics

When collision detection identifies contact involving a soft body, DART instantiates a SoftContactConstraint from dart/constraint/soft_contact_constraint.hpp rather than a standard rigid contact constraint.

Contact Point Selection and Jacobian Computation

The constraint constructor identifies the nearest point mass to the contact point using selectCollidingPointMass(), storing references in mPointMass1 and mPointMass2 for soft-rigid or soft-soft collisions. During the update() phase, the constraint:

  1. Computes relative velocity at the contact point via getRelVelocity()
  2. Generates contact Jacobians (mJacobians1, mJacobians2) mapping point mass velocities to contact space
  3. Constructs friction directions using getTangentBasisMatrixODE() derived from the contact normal
  4. Enforces non-penetration, restitution, and Coulomb friction through applyImpulse(), applyUnitImpulse(), and getVelocityChange()

Global Constraint Parameters

Tuning parameters for soft contact stability are implemented as static members of the constraint class:

  • mErrorAllowance: Position error tolerance before corrective forces apply
  • mErrorReductionParameter (ERP): Baumgarte stabilization coefficient for error correction
  • mConstraintForceMixing (CFM): Regularization parameter preventing singular matrices

These parameters integrate soft contacts into DART's global constraint solver alongside rigid-body contacts, joints, and other constraints.

Dynamics Simulation Pipeline

The soft body simulation follows a structured update sequence within the World::step() loop:

  1. Force Accumulation: External forces (gravity, user input) apply to individual point masses, while internal spring/damper forces calculate based on relative displacements and velocities between connected masses using the kv, ke, and dampCoeff parameters.

  2. Mass Matrix Assembly: The system constructs the generalized inertia matrix mI2 from point mass properties, augmented to include soft-body degrees of freedom in the global system.

  3. Collision Detection: The collision pipeline generates collision::Contact objects; soft body involvement triggers SoftContactConstraint creation.

  4. Constraint Solution: The unified constraint solver processes soft contacts simultaneously with rigid contacts, solving the Linear Complementarity Problem (LCP) for the augmented system including both rigid-body and point-mass variables.

  5. State Integration: Velocities and positions update according to the solved impulses, with the SoftBodyAspect propagating changes back to individual PointMass instances.

Practical Implementation Guide

Creating a Soft Box

The following example demonstrates instantiating a soft body cube using the helper utilities:

#include <dart/dynamics/soft_body_node.hpp>
#include <dart/simulation/world.hpp>

// Create skeleton to contain the soft body
auto* softSkeleton = new dart::dynamics::Skeleton();

// Initialize SoftBodyNode with default properties
auto* softNode = new dart::dynamics::SoftBodyNode(
    nullptr, nullptr,
    dart::dynamics::SoftBodyNode::Properties());

// Configure as a box with specific material properties
dart::dynamics::SoftBodyNodeHelper::setBox(
    softNode,
    Eigen::Vector3d(0.5, 0.5, 0.5),    // dimensions
    Eigen::Isometry3d::Identity(),     // local transform
    1.0,                               // total mass
    1.0,                               // vertex stiffness (kv)
    1.0,                               // edge stiffness (ke)
    0.01);                             // damping coefficient

// Finalize skeleton setup
softSkeleton->addBodyNode(softNode);
softSkeleton->init();

// Add to simulation world
auto world = dart::simulation::World::create();
world->addSkeleton(softSkeleton);

Running the Simulation

Soft body dynamics and contact handling occur automatically during the world update:

const double dt = 0.001;  // 1ms timestep

for (int i = 0; i < 1000; ++i) {
  world->step();  // Solves all constraints including SoftContactConstraint
  
  // Access current deformation state
  const auto& pointMasses = softNode->getPointMasses();
  for (const auto* pm : pointMasses) {
    Eigen::Vector3d pos = pm->getPositionsInWorld();
    // Process or log point mass positions
  }
}

Inspecting Soft Contact Constraints

For debugging or analysis, you can access active soft contact constraints from the solver:

auto* solver = world->getConstraintSolver();
for (auto* constraint : solver->getConstraints()) {
  if (constraint->getType() == 
      dart::constraint::SoftContactConstraint::getStaticType()) {
    
    auto* softConstraint = static_cast<
        dart::constraint::SoftContactConstraint*>(constraint);
    
    // Access collision parameters
    double friction = softConstraint->mFrictionCoeff;
    Eigen::Vector3d normal = softConstraint->mBodyDirection1;
  }
}

Summary

  • DART models soft bodies using SoftBodyNode, which contains discrete PointMass elements connected by springs and dampers rather than using continuous finite element methods.
  • The aspect architecture (SoftBodyAspect) maintains separation between soft-body state/properties and rigid-body core systems while allowing unified simulation.
  • Soft contacts resolve through SoftContactConstraint, which selects the nearest point mass to compute contact Jacobians and handles friction using getTangentBasisMatrixODE() within the global constraint solver.
  • Material parameters kv (vertex stiffness), ke (edge stiffness), and dampCoeff control deformation behavior and are stored in SoftBodyNodeUniqueProperties.
  • Full integration with rigid-body dynamics occurs automatically when calling World::step(), with soft contacts solved simultaneously alongside rigid contacts using the ERP/CFM stabilization parameters.

Frequently Asked Questions

How does DART represent the mass distribution in soft bodies?

DART discretizes the soft body into point masses (PointMass class) rather than using a continuous mass field. Each point mass stores its individual scalar mass and 3D position, and the total generalized inertia matrix (mI2) is assembled dynamically from these discrete masses during the SoftBodyNode::init() phase and updated each step via updateMassMatrix().

Can soft bodies in DART collide with each other, or only with rigid bodies?

The SoftContactConstraint implementation handles both soft-rigid and soft-soft collisions. When two soft bodies collide, the constraint selects the nearest point mass on each body (mPointMass1 and mPointMass2) and computes coupling Jacobians for both deformable objects simultaneously within the same constraint solver framework used for rigid contacts.

What is the computational cost of adding soft bodies compared to rigid bodies?

Soft bodies increase the degrees of freedom proportionally to their point mass count, expanding the linear system the constraint solver must process. Each point mass adds three translational DOFs, and internal spring forces require additional computations compared to rigid bodies. However, DART maintains performance by integrating soft bodies into the same constraint-based pipeline rather than using a separate penalty-based solver.

Where can I find a complete working example of soft body simulation in DART?

The official repository provides a minimal runnable example in examples/soft_bodies/main.cpp, which demonstrates creating a soft box, configuring material stiffness parameters, adding the skeleton to a world, and stepping the simulation. This file serves as the canonical reference for implementing custom soft body scenarios using the SoftBodyNodeHelper utilities and SoftMeshShape visualization.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →