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 and Kamino 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.
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 |
Particles |
Cloth |
Soft bodies |
Differentiable |
|
|---|---|---|---|---|---|---|---|
Semi-implicit |
✅ |
✅ generalized coordinates |
✅ |
🟨 no self-collision |
✅ |
🟨 basic 2 |
|
Implicit |
❌ |
❌ |
✅ |
❌ |
❌ |
❌ |
|
Semi-implicit: Euler, Moreau-Jean |
✅ maximal coordinates |
✅ maximal coordinates |
❌ |
❌ |
❌ |
❌ |
|
Explicit, Semi-implicit, Implicit-in-velocity |
✅ 1 |
✅ generalized coordinates |
❌ |
❌ |
❌ |
❌ |
|
Semi-implicit |
✅ |
✅ maximal coordinates |
✅ |
🟨 no self-collision |
✅ |
🟨 basic 2 |
|
Implicit |
❌ |
❌ |
✅ |
✅ |
❌ |
❌ |
|
Implicit |
✅ |
✅ |
✅ |
✅ |
❌ |
||
Implicit |
✅ |
✅ maximal coordinates |
✅ |
🟨 no self-collision |
🟨 experimental |
❌ |
use_mujoco_contacts=False to use Newton’s collision pipeline.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.
mu:SolverFeatherstone,SolverSemiImplicit,SolverXPBD,SolverMuJoCo,SolverVBD,SolverKamino,SolverStyle3D, andSolverImplicitMPM.ke/kd:SolverFeatherstone,SolverSemiImplicit,SolverMuJoCo, andSolverVBD.kf/ka:SolverFeatherstoneandSolverSemiImplicit.restitution:SolverXPBDwhenenable_restitution=True, andSolverKamino.mu_torsional/mu_rolling:SolverXPBDandSolverMuJoCo.kh: consumed by hydroelastic contact generation for Newton-generated contacts used bySolverFeatherstone,SolverSemiImplicit, andSolverMuJoCowhenuse_mujoco_contacts=False. See Hydroelastic Contacts.
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 via soft constraints (AVBD).
SolverStyle3D and SolverImplicitMPM do not support joints.
Joint types
Joint type |
||||||
|---|---|---|---|---|---|---|
PRISMATIC |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
REVOLUTE |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
BALL |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
FIXED |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
FREE |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
DISTANCE |
🟨 1 |
🟨 1 |
✅ |
❌ |
❌ |
❌ |
D6 |
✅ |
✅ |
✅ |
✅ |
✅ |
❌ |
CABLE |
❌ |
❌ |
❌ |
❌ |
✅ |
❌ |
Joint properties
Property |
||||||
|---|---|---|---|---|---|---|
❌ |
✅ |
✅ |
❌ |
✅ |
❌ |
|
✅ |
❌ |
❌ |
✅ |
❌ |
✅ |
|
❌ |
❌ |
❌ |
✅ |
❌ |
❌ |
|
✅ |
✅ 2 |
✅ |
✅ |
✅ |
✅ |
|
✅ |
✅ 2 |
❌ |
✅ |
✅ 4 |
❌ |
|
❌ |
❌ |
❌ |
✅ |
❌ |
❌ |
|
❌ |
❌ |
❌ |
❌ |
❌ |
❌ |
Actuation and control
Feature |
||||||
|---|---|---|---|---|---|---|
✅ |
✅ 2 |
✅ |
✅ |
✅ 4 |
✅ |
|
❌ |
❌ |
❌ |
✅ |
❌ |
✅ |
|
|
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
Constraints
Feature |
||||||
|---|---|---|---|---|---|---|
Equality constraints (CONNECT, WELD, JOINT) |
❌ |
❌ |
❌ |
✅ |
❌ |
❌ |
Mimic constraints |
❌ |
❌ |
❌ |
✅ 3 |
❌ |
❌ |
joint_target_kd and joint_limit_kd as absolute damping coefficients in physical units.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.