Solvers#

Solvers are used to integrate the dynamics of a Newton model. The typical workflow is to construct a Model and a State object, then use a solver to advance the state forward in time via the step() method:

        ---
config:
  theme: forest
  themeVariables:
    lineColor: '#76b900'

---
flowchart LR
    subgraph Input["Input Data"]
        M[newton.Model]
        S[newton.State]
        C[newton.Control]
        K[newton.Contacts]
        DT[Time step dt]
    end

    STEP["solver.step()"]

    subgraph Output["Output Data"]
        SO["newton.State (updated)"]
    end

    %% Connections
    M --> STEP
    S --> STEP
    C --> STEP
    K --> STEP
    DT --> STEP
    STEP --> SO
    

See the solver API reference for constructor and method details. For symptom-driven diagnosis and parameter tuning, start with Simulation Tuning.

Choosing a Solver#

MuJoCo, Kamino, and VBD currently have dedicated backend guides:

  • MuJoCo — generalized-coordinate rigid-body simulation and MuJoCo or MJCF workflows.

  • Kamino — constrained rigid mechanisms with kinematic loops and hard frictional contacts; experimental.

  • VBD — unified simulation of cloth, soft bodies, and rigid bodies in a single VBD-based solver; experimental.

The other solver backends are documented through their linked API references and the comparison tables below.

For a rigid articulated robot, first decide which coordinate representation fits the application. SolverMuJoCo and SolverFeatherstone use generalized coordinates, while SolverXPBD, SolverSemiImplicit, and SolverKamino use maximal coordinates. For deformable bodies, particles, or differentiable simulation, use the feature matrix below to narrow the choice, then follow the linked API documentation.

Supported Features#

Solver

Integration

Rigid bodies

Articulations

Particles

Cloth

Soft bodies

Differentiable

SolverFeatherstone

Semi-implicit

✅

✅ generalized coordinates

✅

🟨 no self-collision

✅

🟨 basic 2

SolverImplicitMPM

Implicit

❌

❌

✅

❌

❌

❌

SolverKamino

Semi-implicit: Euler, Moreau-Jean

✅ maximal coordinates

✅ maximal coordinates

❌

❌

❌

❌

SolverMuJoCo

Explicit, Semi-implicit, Implicit-in-velocity

✅ 1

✅ generalized coordinates

❌

❌

❌

❌

SolverSemiImplicit

Semi-implicit

✅

✅ maximal coordinates

✅

🟨 no self-collision

✅

🟨 basic 2

SolverStyle3D

Implicit

❌

❌

✅

✅

❌

❌

SolverVBD

Implicit

✅

🟨 limited joint support

✅

✅

✅

❌

SolverXPBD

Implicit

✅

✅ maximal coordinates

✅

🟨 no self-collision

🟨 experimental

❌

1 Uses MuJoCo’s built-in collision pipeline by default. Set use_mujoco_contacts=False to use Newton’s collision pipeline.
2 basic means Newton includes several examples that use these solvers in diffsim workflows, see Differentiability for further details.

Experimental

SolverKamino’s public API and behavior may change without prior notice.

Experimental

SolverVBD’s public API and behavior may change without prior notice.

Contact Material Support#

ShapeConfig and the matching Model shape material arrays store solver-neutral contact data. This section documents which fields are currently used by Newton’s built-in solvers. External solvers may use different subsets or interpret these fields according to their own formulation.

Joint Feature Support#

Not every solver supports every joint type or joint property. The tables below document which joint features each solver handles.

Only SolverFeatherstone and SolverMuJoCo operate on articulations (generalized/reduced coordinates). The maximal-coordinate solvers (SolverSemiImplicit, SolverXPBD, and SolverKamino) enforce joints as pairwise body constraints but do not use the articulation kinematic-tree structure. SolverVBD supports a subset of joint types through maximal-coordinate constraints, with unified compliant ALM by default and a deprecated legacy AVBD path. SolverStyle3D and SolverImplicitMPM do not support joints.

Joint types

Joint type

SolverFeatherstone

SolverSemiImplicit

SolverXPBD

SolverMuJoCo

SolverVBD

SolverKamino

PRISMATIC

✅

✅

✅

✅

✅

✅

REVOLUTE

✅

✅

✅

✅

✅

✅

BALL

✅

✅

✅

✅

✅

✅

FIXED

✅

✅

✅

✅

✅

✅

FREE

✅

✅

✅

✅

✅

✅

DISTANCE

🟨 1

🟨 1

✅

❌

❌

❌

D6

✅

✅

✅

✅

✅

❌

ROD

❌

❌

❌

❌

✅

❌

1 DISTANCE joints are treated as FREE (no distance constraint enforcement).

Joint properties

Property

SolverFeatherstone

SolverSemiImplicit

SolverXPBD

SolverMuJoCo

SolverVBD

SolverKamino

joint_enabled

❌

✅

✅

❌

✅

❌

joint_armature

✅

❌

❌

✅

❌

✅

joint_friction

❌

❌

❌

✅

❌

✅

joint_limit_lower / joint_limit_upper

✅

✅ 2

✅

✅

✅

✅

joint_limit_ke / joint_limit_kd

✅

✅ 2

❌

✅

✅ 7

❌

joint_effort_limit

❌

❌

❌

✅

❌

✅

joint_velocity_limit

❌

❌

❌

❌

❌

❌

2 Not enforced for BALL joints in SemiImplicit.

Actuation and control

Feature

SolverFeatherstone

SolverSemiImplicit

SolverXPBD

SolverMuJoCo

SolverVBD

SolverKamino

joint_target_ke / joint_target_kd

✅

✅ 2

✅

✅

✅ 7

✅

joint_target_mode

❌

❌

❌

✅

❌

✅

joint_f (feedforward forces)

✅

✅

✅

✅

✅

✅

Constraints

Feature

SolverFeatherstone

SolverSemiImplicit

SolverXPBD

SolverMuJoCo

SolverVBD

SolverKamino

Equality constraints (CONNECT, WELD, JOINT)

❌

❌

❌

✅

❌

❌

Mimic joints

✅ 3

✅ 4

✅ 5

✅ 6

✅ 5

❌

Particle-body attachments

❌

❌

❌

❌

✅ 8

❌

3 Featherstone eliminates follower degrees of freedom from its reduced dynamics and transfers follower forces and inertia to the reference joint.
4 SemiImplicit enforces joint-owned mimic relationships with penalty springs configured by joint_mimic_ke and joint_mimic_kd.
5 XPBD and VBD enforce joint-owned mimic relationships through coupled maximal-coordinate corrections. Both apply one mimic correction per solver iteration.
6 MuJoCo lowers each joint-owned relationship to joint equality constraints. Multi-axis D6 relationships produce one equality constraint per axis.
7 VBD interprets joint_target_kd and joint_limit_kd as absolute damping coefficients in physical units.
8 See Particle-Body Attachments for authoring and semantics. Attachments spanning two solvers are coupled by SolverCoupledADMM instead.

Particle-Body Attachments#

A particle-body attachment ties one cloth or solid particle to a point in a rigid body’s local frame. Author attachments with newton.ModelBuilder.add_attachment_particle_body(). They are stored on the Model and do not require a coupled solver.

SolverVBD applies an attachment whenever it integrates both endpoints. The attachment is compliant rather than rigid: it contributes a quadratic penalty with stiffness [N/m] and damping [N·s/m], so a heavily loaded attachment keeps a small offset instead of holding the particle exactly. The constraint is translational, similar to the positional part of a ball joint; a single particle has no orientation, so there is no angular counterpart. Forces are equal and opposite, including the torque about the body’s center of mass, and the path is independent of contact, so it stays active without penetration.

Both endpoints must be integrated by the same solver, so SolverVBD rejects attachments when it is constructed with integrate_with_external_rigid_solver=True.

When the endpoints belong to two different solvers in a coupled simulation, SolverCoupledADMM turns the same model rows into cross-solver interface constraints; see ADMM Coupling. The two cases are mutually exclusive, so no attachment is applied twice, and a row whose body or particle is owned by no solver applies no force at all. The coupler also warns when both endpoints belong to one entry whose solver does not support attachments.

Differentiability#

Differentiable simulation in Newton typically runs a forward rollout inside wp.Tape(), computes a scalar loss from the simulated state, and then calls tape.backward(loss) to populate gradients on differentiable state, control, or model arrays. In practice, this starts by calling finalize() with requires_grad=True.

import warp as wp
import newton

@wp.kernel
def loss_kernel(particle_q: wp.array[wp.vec3], target: wp.vec3, loss: wp.array[float]):
    delta = particle_q[0] - target
    loss[0] = wp.dot(delta, delta)

builder = newton.ModelBuilder()
builder.add_particle(pos=wp.vec3(0.0, 0.0, 0.0), vel=wp.vec3(1.0, 0.0, 0.0), mass=1.0)

model = builder.finalize(requires_grad=True)
solver = newton.solvers.SolverSemiImplicit(model)

state_in = model.state(requires_grad=True)
state_out = model.state(requires_grad=True)
control = model.control()
loss = wp.zeros(1, dtype=float, requires_grad=True)
target = wp.vec3(0.25, 0.0, 0.0)

tape = wp.Tape()
with tape:
    state_in.clear_forces()
    solver.step(state_in, state_out, control, None, 1.0 / 60.0)
    wp.launch(
        loss_kernel,
        dim=1,
        inputs=[state_out.particle_q, target],
        outputs=[loss],
    )

tape.backward(loss)
initial_velocity_grad = state_in.particle_qd.grad.numpy()
assert float(initial_velocity_grad[0, 0]) < 0.0

See the DiffSim examples on GitHub for the current reference workflows.