What it means for a simulator to have gradients, how NVIDIA Warp turns Python into GPU-speed physics code, how the Newton engine builds a full multi-solver simulator on top, and where a vehicle engineer should point all of it.
By Majid MazouchiDrafted with ClaudeJuly 2026Companion to Part I: PhysicsNeMo
Abstract. Part I of this series covered learning surrogates of physics. This part covers the complementary move: making the physics simulation itself differentiable, so that gradients of any simulated outcome flow back to parameters, controls, and designs. Two projects anchor the modern stack. NVIDIA Warp is a Python framework that JIT-compiles kernel functions to native CPU and CUDA code and automatically generates their adjoints, giving researchers hand-tuned-CUDA performance with reverse-mode autodiff. Newton, an open-source engine created by NVIDIA, Google DeepMind, and Disney Research and governed by the Linux Foundation, builds a full multi-solver, OpenUSD-native robotics simulator on that foundation, reaching 1.0 alongside Isaac Lab 3.0. This guide covers both layers, the surrounding engine landscape, the honest fine print about gradients through contact, and the vehicle-engineering applications, from suspension system identification to tire-soil interaction.
Section 01
The idea: simulation you can backpropagate through
A classical simulator is a function you can only call. A differentiable simulator is a function you can also differentiate: for any scalar outcome L of a rollout, it returns ∂L/∂θ for the parameters θ that produced it.
Concretely, a simulation step advances state s and parameters θ: s(t+1) = f(s(t), u(t), θ), where u is the control input. Chain many steps into a rollout, compute a loss on the trajectory, and reverse-mode automatic differentiation propagates sensitivities back through every step, exactly the way training a neural network does, except the "network" here is the physics. Three problem classes fall out of this one capability:
System identification. θ are physical parameters: masses, inertias, spring rates, damping coefficients, friction, tire model coefficients. Fit them to measured trajectories by gradient descent instead of derivative-free search. For a health-management engineer this has a second reading: a drifting θ estimated online is a degradation signal.
Control and trajectory optimization. θ are the controls u(t) or policy weights. Gradients through the rollout give first-order policy improvement (the SHAC family of methods) and enable differentiable MPC, often with far fewer samples than zeroth-order RL.
Design optimization. θ are geometric or structural parameters. The simulator becomes an adjoint solver you did not have to derive by hand, the same pattern as the DoMINO design-sensitivities workflow from Part I, but with the real physics instead of a surrogate.
The price of admission is twofold: memory (reverse mode stores or recomputes intermediate states across the rollout, hence gradient checkpointing) and gradient quality through discontinuous events like contact, which gets its own honest section later. Neither price is hidden in Warp or Newton; both are engineered around explicitly.
Section 02
Feel the gradient: a live identification demo
Before any framework, the idea itself, running in this page. A quarter-car with hidden spring rate and damping drives over a bump; noisy displacement measurements are all you get. Press run and watch gradient descent recover the hidden parameters by backpropagating through the simulation.
Everything below is plain JavaScript in this page's source: a semi-implicit Euler forward pass, a hand-written adjoint (the "tape") of about twenty lines, and Adam on log-parameters. It is the same mathematics Warp generates automatically for every kernel, shrunk to a size you can read in one sitting.
Quarter-car system identification · m = 300 kg, hidden k* and c*, 5 cm bump at 0.3 s
Three things worth noticing as it runs. The stiffness converges before the damping, because spring force scales with displacement while damper force scales with velocity, which the noise punishes harder. Higher noise settings slow and roughen convergence but do not break it; the estimator is averaging over 1,500 timesteps of evidence. And the entire optimization is deterministic given the noise seed: gradients, not guesses.
Section 03
NVIDIA Warp: the substrate
Warp is not a physics engine. It is the layer that makes writing one in Python viable: kernel functions JIT-compiled to native CPU and CUDA code, with adjoints generated automatically.
You decorate a Python function with @wp.kernel, and Warp compiles it through its own type-checked subset of Python into efficient parallel code, caching the result. The same source runs on CPU or any CUDA device. Because Warp generates both the forward kernel and its adjoint, any program composed of kernels is differentiable end to end via wp.Tape. The published industrial numbers are striking: NVIDIA reports speedups up to 669x over CPU baselines and large gains over JAX in specific workloads, with zero-copy interoperability into PyTorch and JAX tensors so the physics slots directly into ML training loops.
A sixty-second taste
import warp as wp
@wp.kernel
def quarter_car(x: wp.array(dtype=float), v: wp.array(dtype=float),
f: wp.array(dtype=float), k: float, c: float):
i = wp.tid() # one thread per environment
f[i] = -k * x[i] - c * v[i] # spring-damper force# thousands of parallel suspension corners in one launch
wp.launch(quarter_car, dim=n_envs, inputs=[x, v, f, k, c])
And the gradient, for free
k = wp.array([28000.0], dtype=float, requires_grad=True) # unknown spring rate
tape = wp.Tape()
with tape:
for t in range(steps):
wp.launch(step_dynamics, dim=n, inputs=[state, k, dt])
wp.launch(trajectory_loss, dim=1, inputs=[state, measured, loss])
tape.backward(loss)
print(k.grad) # dLoss/dk: descend on this to identify the spring rate# Sketch of the idiom; consult the Warp docs for current signatures.
The module map
Table 1 · What ships inside Warp
Component
What it gives you
Vehicle-flavored use
wp.kernel / wp.launch
JIT-compiled parallel kernels, CPU and CUDA, cached
Custom vehicle dynamics stepped across thousands of parallel environments
wp.Tape + adjoints
Reverse-mode autodiff over kernel programs, gradient checkpointing for long rollouts
System ID, differentiable MPC, design sensitivities
Geometry: meshes, BVH, SDF, hash grids
GPU spatial queries: ray casts, closest points, signed distances
Contact and collision machinery; sensor simulation
warp.fem
A domain-specific language for finite-element weak forms with integrands as kernels
Battery-pack and inverter thermal solvers you can differentiate
warp.sparse / warp.optim
Sparse linear algebra and optimizers
Implicit integrators; Gauss-Newton loops for identification
Interop
Zero-copy exchange with PyTorch, JAX, NumPy, CuPy via DLPack; CUDA graph capture
Physics-in-the-loop training with a PyTorch model, no copies
warp.sim (legacy)
The original simulation module, now superseded
Its lineage and lessons live on as Newton
Positioning
Think of Warp as "CUDA for people who refuse to leave Python, with adjoints included." It competes less with physics engines and more with hand-written CUDA, Taichi, and JAX: it is the substrate on which engines, solvers, and the geometry pipelines of Part I's PhysicsNeMo are built.
Section 04
Autodiff under the hood
Warp's differentiability is not a wrapper around PyTorch; it is generated at kernel compile time. Knowing the mechanism tells you exactly what will and will not differentiate, and how to debug it when it goes quiet.
How the adjoint gets made
When Warp compiles a @wp.kernel, it emits two functions: the forward kernel you wrote, and an adjoint kernel derived from it by reversing the dataflow, each primitive operation replaced by its derivative rule. Arrays created with requires_grad=True carry a companion .grad buffer. A wp.Tape then simply records every launch inside its context; calling tape.backward(loss) replays the recorded launches in reverse order using the adjoint kernels, accumulating into the .grad buffers. Reverse-mode over the whole program falls out of reverse order over its launches.
The working rules
Gradients accumulate. Adjoint buffers are added into, never overwritten, exactly like PyTorch. Between optimizer steps, call tape.zero() or you will be descending on the sum of every gradient you have ever computed. This is the single most common silent bug.
The tape stores what the backward pass needs. For long rollouts that means intermediate state, and memory grows with horizon length. The remedies, in order: reuse preallocated state arrays where the math permits, checkpoint segments (store every k-th state, recompute the rest during backward), and truncate horizons where the problem allows it.
Custom gradients are first-class. For operations whose true derivative is useless or undefined, a hard contact response, a lookup table, a clamp at its corner, Warp lets you register a replacement adjoint for a @wp.func. This is the sanctioned mechanism for the smoothed contact gradients discussed later: keep the hard physics forward, supply a soft derivative backward, and document that you did.
Not everything differentiates. Integer indexing logic, branches on data, and atomic scatter patterns have the derivative semantics you would derive by hand, which is sometimes zero. If a parameter's gradient is exactly zero, suspect a branch or cast severing the path before suspecting the physics.
Debugging the invisible
A wrong gradient looks like a right gradient until it ruins an optimization, so verification is part of the workflow, not an afterthought. The tools, cheapest first: compare against central finite differences on a shrunken problem (the case study in Section 12 does exactly this and agrees to 1.4e-8); inspect the tape's recorded launch graph to confirm the operations you think are being differentiated actually were; enable Warp's floating-point verification mode during development to trap NaN and inf the moment they appear rather than three kernels later; and bisect long rollouts, checking gradient norms per segment, to localize where sensitivity explodes or dies. Gradient norms that grow exponentially with horizon length are not a bug in the tape; they are Lyapunov instability in your dynamics, and the fix is shorter horizons, not different code.
Section 05
Newton: the engine
Newton is what happens when Warp's simulation module grows up, moves out, and acquires institutional parents: an open-source, GPU-accelerated, multi-solver physics engine created by NVIDIA, Google DeepMind, and Disney Research, governed by the Linux Foundation under Apache 2.0.
Newton explicitly supersedes warp.sim with a more general architecture. Its design commitments: end-to-end GPU execution with CUDA graphs so thousands of environments run without CPU bottlenecks, OpenUSD as the native scene and asset representation, differentiability through inputs, controls, and parameters, and a pluggable solver architecture rather than one monolithic integrator. It reached 1.0 in March 2026, integrated as a first-class backend of Isaac Lab 3.0.
What the solver menu buys you
Table 2 · Newton's solver families (as of v1.x; the menu is growing)
Solver family
Physics regime
Vehicle-flavored use
MuJoCo Warp
Rigid multibody with MuJoCo's proven contact model, GPU-native, full MJCF compatibility
Full-vehicle and chassis multibody; the default for RL and control research assets
XPBD
Position-based compliant constraint dynamics
Fast, stable articulated mechanisms; bushings and compliant joints
Wiring harnesses, seals, hoses, seat and interior soft trim
MPM
Granular and continuum materials
Tire-soil and tire-snow interaction; off-road terramechanics
Featherstone
Reduced-coordinate articulated rigid bodies
Suspension linkages in minimal coordinates, gradient-friendly
Custom (yours)
Any Warp-kernel solver plugged into the same Model/State API
A bespoke ride-dynamics or powertrain solver living beside the standard ones
Two adjacent pieces complete the picture. Hydroelastic contact and an SDF collision library address the contact-quality failure modes that have long plagued sim-to-real transfer. And NeRD, Neural Robot Dynamics, explores the hybrid frontier: learned dynamics models inside the engine that can be fine-tuned with real-world data, which is the engine-side mirror of everything Part I covered.
Section 06
Anatomy of the Newton API
Like the recipe anatomy in Part I, this is the skeleton every Newton program shares. Learn the lifecycle once and each example reads as a variation.
# The lifecycle, end to end
ModelBuilder → finalize() → Model → State / Control → Solver.step → Viewer / USD
build │ GPU arrays per-timestep physics output
or import │ (parameters) buffers advance artifact
ModelBuilder is the construction phase: procedural calls to add bodies, joints, and shapes, or importers that ingest whole MJCF, URDF, and USD descriptions. Nothing touches the GPU yet; you are describing, not simulating.
finalize() is the phase change. The description is compiled into a Model: flat, GPU-resident arrays of masses, inertias, joint limits, shape parameters, and contact properties. This flatness is the point, and the opportunity: physical parameters live in plain arrays you can read, write, and, crucially, differentiate with respect to.
State holds everything that changes per timestep (positions, velocities, in generalized or maximal coordinates depending on solver); Control holds actuation. You allocate them from the model and ping-pong two states through the loop.
Solver.step advances physics. Solvers are interchangeable behind the same call because they consume the same Model/State contract, which is what makes "swap MuJoCo Warp for XPBD and compare" a one-line experiment.
Viewers and USD export sit outside the loop: attach a window for interactive work, or write the rollout to a USD file for replay, review, and diffing.
The two idioms that unlock scale
Environment replication. To simulate 4,096 vehicles, you do not create 4,096 models; you replicate one articulation into a single Model whose arrays are 4,096 environments long, then step them in one launch. Batch dimension, not object count.
Parameter randomization by array writes. Because parameters are flat arrays indexed by environment, domain randomization and per-vehicle system identification are the same operation: write different values into each environment's slice of the mass, stiffness, or friction arrays. No scene rebuilding, no per-env objects, and the writes themselves can sit inside the differentiated program.
Version honesty
Newton is young and its surface is still settling; class and argument names have already shifted between minor versions. The lifecycle above is stable in shape. For signatures, trust the documentation of the version you have pinned, not this page and not your memory.
Section 07
A short OpenUSD primer
Newton's choice of OpenUSD as its native scene representation looks like a rendering detail and is actually an engineering-data decision.
Universal Scene Description, from Pixar, is a scene graph with a superpower: composition. A USD stage is assembled from layers that override and extend one another non-destructively, so a robot asset, an environment, and a set of simulation-specific tweaks live in separate files composed at load time. Physics enters through the UsdPhysics schemas, which attach rigid-body, collider, joint, and material semantics to scene prims as typed attributes. The practical consequences for a simulation team:
One source of truth. The same asset flows through CAD-adjacent tools, Omniverse, Isaac Sim, and Newton without lossy format hops; simulation overrides live in a thin layer on top rather than in a forked copy.
Versionable and reviewable. The ASCII form (.usda) diffs in git like code. A changed inertia or joint limit shows up in review as a changed line, not a changed binary blob.
Rollouts as artifacts. Newton can write simulations out as USD, which turns every run into a portable, replayable, inspectable file, the difference between "it looked wrong yesterday" and attaching the offending trajectory to the bug report.
Table 3 · The three asset dialects Newton ingests
Format
Origin
Strengths
Watch for
MJCF
MuJoCo
Compact, simulation-native, rich actuator and contact semantics; the RL community's lingua franca
MuJoCo-specific conventions; fidelity is best on the MuJoCo Warp backend
URDF
ROS
Ubiquitous in robotics toolchains; every arm and mobile base ships one
No closed kinematic loops, thin dynamics vocabulary; often needs supplementing
Steeper learning curve; schema coverage still evolving across tools
Section 08
Getting started
Both projects are a pip install away. Versions below verified on PyPI at the time of writing.
# Warp (v1.15.0 at time of writing)
pip install warp-lang
# Newton (v1.3.0; the old name newton-physics now redirects here)
pip install newton
# MuJoCo Warp, usable standalone or as Newton's rigid-body backend
pip install mujoco-warp
First contact with Newton
# Discover the shipped examples
python -m newton.examples --list
# Run one with the OpenGL viewer
python -m newton.examples basic_viewer --viewer gl --num-frames 500
# Load a robot description and pick your device
python -m newton.examples basic_urdf --device cuda:0
# Render to an OpenUSD file instead of a window
python -m newton.examples basic_viewer --viewer usd --output-path my_run.usd
The example runner accepts a shared set of flags: viewer backends (gl, usd, rtx, rerun, viser, null), device selection, and frame counts. The usd path matters more than it looks: writing simulations to OpenUSD makes every run a portable, inspectable asset rather than a fleeting window.
The programming idiom
import newton
# 1. Build: describe bodies, joints, shapes (or import MJCF/URDF/USD)
builder = newton.ModelBuilder()
builder.add_ground_plane()
# ... add articulation, e.g. a double-wishbone corner ...
model = builder.finalize()
# 2. Pick a solver and allocate states
solver = newton.solvers.SolverMuJoCo(model)
state_in, state_out = model.state(), model.state()
# 3. Step: the loop is yours, which is the whole pointfor t in range(horizon):
solver.step(state_in, state_out, control, contacts, dt)
state_in, state_out = state_out, state_in
# API sketch to convey the shape; the library is young and moving,# so treat the current docs as the source of truth for signatures.
Build-vs-import note
Newton ingests MJCF, URDF, and USD directly. If your organization already maintains MuJoCo or ROS descriptions of test rigs and vehicles, they are the fastest on-ramp; the MuJoCo Warp backend keeps MJCF semantics intact.
Section 09
Performance engineering
The throughput headlines are real, but they are earned by a handful of disciplines, and lost by their absence. Most "Warp is slow" reports decompose into one of these rows.
Table 4 · Symptom, cause, fix
Symptom
Cause
Fix
First run is slow, later runs fast
JIT compilation of kernels on first launch
Expected; the kernel cache persists across runs. Warm up before benchmarking and never time the first call.
GPU utilization low despite many environments
Host-device synchronization inside the loop: .numpy(), printing, Python-side branching on device values
Keep the loop device-resident; move logging outside the loop or to periodic snapshots; let scalars live in length-1 device arrays.
Thousands of tiny kernels, launch overhead dominates
Each substep is a separate launch; a physics step can be dozens of kernels
CUDA graph capture: record the step sequence once, replay it per iteration. This is the single largest win for many-env simulation and the reason Newton leans on it.
Memory climbs with rollout length until it doesn't fit
The tape retains what backward needs; naive per-step allocation compounds it
Preallocate and ping-pong state buffers; checkpoint the tape into segments; ask whether the loss truly needs the full horizon.
Results drift between runs or diverge slowly
fp32 accumulation over long horizons; atomics ordering
fp32 is the default and usually right; give long-running sums and sensitive reductions fp64 islands, and verify against a small fp64 reference run.
Benchmark numbers nobody can reproduce
Timing includes compile, excludes synchronization, or reports a single lucky run
Synchronize the device before starting and stopping timers, exclude JIT, report steps per second per environment with environment count, GPU, and precision stated.
A sizing intuition
Differentiable simulation shifts the bottleneck: forward-only workloads are compute-bound and scale gloriously with environments; differentiated workloads are usually memory-bound through the tape. Budget rollout length × state size × environments before budgeting FLOPs, and treat checkpointing as a first-class design choice rather than an emergency patch.
Section 10
The differentiable engine landscape
Newton and Warp sit in a lively neighborhood. Choosing among the neighbors is mostly a question of ecosystem, autodiff framework, and physics coverage.
Table 5 · Differentiable (and one deliberately non-differentiable) simulators
You want a fast-moving generalist platform and accept research maturity
Dojo
Julia
Yes, smoothed contact gradients
Rigid with careful contact
Gradient quality through contact is your research subject
Drake
C++/Python
Autodiff types, not GPU-parallel
Multibody with strong contact theory
Rigor, verification, and controls pedigree outrank raw throughput
Project Chrono
C++
No (sensitivities via other means)
Vehicle dynamics, terramechanics, FSI
The automotive multibody incumbent; the fidelity yardstick to validate against
Reading the table honestly
"Differentiable: yes" never means "gradients are always useful." Every engine in this table inherits the contact caveats of Section 13. And Chrono earns its row despite lacking autodiff: for vehicle work it remains the reference physics against which a Newton-based pipeline should be validated.
Section 11
Vehicle applications gallery
Eight concrete places a vehicle engineer can point this stack, from published workflows to well-scoped internal projects.
Showing 8 of 8 applications
Gradient-based suspension & tire identification
System ID
pattern: newton rollout + wp.Tape → fit {k, c, μ, tire coefficients} to telemetry
Model a corner or full vehicle in Newton, drive it with recorded road inputs, and descend on the mismatch between simulated and measured response. Spring rates, damper curves, bushing stiffness, friction, and tire model coefficients become trainable parameters. The same loop run continuously in the fleet turns parameter drift into a first-class degradation observable.
Gradient path
Loss → trajectory → solver steps → θ
Scale
Thousands of vehicles as parallel envs
Vehicle angle This is the flagship VHM use: system identification is condition monitoring when the identified parameters are allowed to move. A damper whose fitted c drops 20 percent over six months has told you something no threshold alarm can.
pattern: unroll horizon in Newton → backprop to controls u(0..H)
With gradients through the rollout, trajectory optimization becomes first-order: shape a lane change, an evasive maneuver, or an energy-optimal speed profile by descending directly on the control sequence. The same machinery differentiates an MPC's closed-loop cost with respect to its tuning parameters, turning controller calibration into optimization rather than manual sweeps.
Methods
First-order shooting, DiffMPC-style tuning
Caveat
Contact-rich segments need Section 13
Vehicle angle For someone with an FOC and MPC background, this is familiar adjoint territory wearing new clothes: the simulator supplies the adjoint model that classical optimal control made you derive by hand.
Isaac Lab 3.0 adopts Newton as a physics backend, giving robot-learning workflows GPU-parallel environments, OpenUSD assets, and a path to differentiable rollouts inside one framework. For automotive, the near-term relevance is manipulation and locomotion in plants and service scenarios; the longer arc is learned controllers for chassis subsystems trained against high-throughput simulation.
Stack
Isaac Lab → Newton → Warp
Throughput
Thousands of parallel environments
Vehicle angle The manufacturing floor gets this first: robot cells, wire-harness handling (VBD cloth), bin picking. The chassis gets it as the sim-to-real gap narrows.
NeRD replaces or augments analytic solver steps with learned dynamics models that can be fine-tuned on real-world trajectories. It is the engine-side answer to the sim-to-real gap: rather than hand-tuning contact parameters forever, let a residual network absorb what the analytic model cannot express, while keeping the analytic core for trust and extrapolation.
Pattern
Analytic solver + learned residual
Data
Fine-tuned with real trajectories
Vehicle angle Structurally identical to the predictor-corrector fine-tuning from Part I, and to residual-based health monitoring: the learned residual is both a model improvement and a diagnostic signal.
Google DeepMind's GPU port of MuJoCo onto Warp kernels, developed as part of the Newton collaboration and serving as Newton's primary rigid-body backend. Existing MJCF models, including vehicle and wheeled-platform descriptions, run with MuJoCo semantics at GPU-parallel scale.
Compatibility
MJCF-faithful
Version
3.10.x on PyPI at time of writing
Vehicle angle The pragmatic bridge: teams with MuJoCo assets get GPU scale today, and a seat inside Newton's architecture tomorrow, without rewriting models.
Warp's FEM module lets you state weak forms with integrand kernels and assemble GPU-resident systems, which is enough to build a conjugate heat transfer or electro-thermal solver for a pack or power module. Because the solver is made of Warp kernels, it is differentiable: sensitivities of hot-spot temperature with respect to contact resistances, coolant flow, or material properties come from the tape, not from finite differences.
Module
warp.fem, warp.sparse
Gradient use
Design sensitivity, parameter estimation
Vehicle angle The natural companion to the thermal-neural-network thread from Part I: a differentiable analytic thermal model to generate data, embed physics losses, and cross-check learned surrogates.
Autodesk's open-source XLB library implements massively parallel lattice-Boltzmann flow simulation with a Warp backend, cited by NVIDIA as a flagship industrial Warp adoption. It demonstrates that a serious, differentiable CFD solver can be written in Python and still saturate the GPU, the existence proof for any bespoke flow solver you are tempted to build.
Method
Lattice-Boltzmann
Backends
Warp, JAX
Vehicle angle Underhood and cabin airflow at interactive speeds, with gradients, an interesting counterpoint to the surrogate-based aero of Part I: solve the physics fast rather than learn it.
MPM terrain: tire-soil and off-road terramechanics
Custom SolverLearning
newton · MPM solver family for granular media
Newton's granular MPM solver family simulates soil, sand, and snow as continuum particles interacting with rigid bodies, which is precisely the regime of off-road tire-terrain interaction, soft-soil mobility, and construction-vehicle work where classical multibody contact models give up. Historically a Chrono and specialized-code domain, now reachable in a differentiable GPU engine.
Method
Material Point Method
Coupling
Granular ↔ rigid multibody
Vehicle angle Traction and mobility prediction on deformable terrain, and training data for terrain-aware controllers, with the option of gradients through the terrain interaction itself.
A worked case study: half-car identification and damper-drift detection
The Section 02 demo, grown up: a pitch-plane half car, four unknown suspension parameters, realistic sensor noise, a hand-written adjoint verified against finite differences, and a deliberately degraded damper to detect. Every number below was produced by the companion script shipped alongside this page.
Protocol
The plant is a pitch-plane half car (m = 1400 kg, I = 2100 kg·m², axle distances a = 1.2 m, b = 1.5 m) with front and rear spring-damper corners. Ground truth: kf = 32,000 N/m, cf = 1,500 N·s/m, kr = 28,000 N/m, cr = 1,300 N·s/m. The excitation is a 5 cm half-sine bump traversed at 10 m/s, hitting the rear axle 0.27 s after the front. Sensors are heave and pitch displacement at 1 kHz over a 4 s horizon (4,000 steps, semi-implicit Euler at 1 ms). Identification is Adam on log-parameters, 500 iterations, from a deliberately poor initial guess (18,000 / 800 / 18,000 / 800). Gradients come from a hand-written discrete adjoint, the same reverse pass Warp generates automatically, small enough here to read in full.
# The adjoint core (backward over one step), verbatim from the scriptfor t in range(N - 1, -1, -1):
gz += 2.0 * rz[t] / (SZ * N) # loss injects adjoint at t+1
gth += 2.0 * rt[t] / (STH * N)
gthd += DT * gth; gthdd = DT * gthd
gzd += DT * gz; gzdd = DT * gzd
gFf = gzdd / M - A_ * gthdd / I # accelerations → forces
gFr = gzdd / M + B_ * gthdd / I
gkf += -zf * gFf; gcf += -zfd * gFf # parameter gradients
gkr += -zr * gFr; gcr += -zrd * gFr
gzf = -kf * gFf; gzfd = -cf * gFf # forces → state at t
gzr = -kr * gFr; gzrd = -cr * gFr
gz += gzf + gzr; gth += -A_ * gzf + B_ * gzr
gzd += gzfd + gzrd; gthd += -A_ * gzfd + B_ * gzrd
Result 1 · The adjoint is correct
Before trusting any optimization, the gradient itself was checked against central finite differences over all four parameters: maximum relative difference 1.4 × 10⁻⁸. This verification step costs seconds and should be a fixed ritual of any differentiable-simulation project; it is rung R4 of the ladder for a reason.
Result 2 · Identification accuracy vs sensor noise
Table 6 · Recovered parameters after 500 iterations (error vs ground truth)
Noise (heave / pitch)
kf error
cf error
kr error
cr error
None
−0.00%
−0.00%
+0.00%
+0.00%
1 mm / 0.5 mrad
+0.21%
−0.79%
+0.08%
+0.09%
5 mm / 2.5 mrad
+0.80%
+2.68%
−0.72%
−0.24%
Two patterns worth internalizing. Noise-free identification is exact to display precision, confirming the estimator and the adjoint jointly. And damping is consistently the hardest parameter: damper force scales with velocity, whose signal-to-noise is worst, so cf carries the largest error at every noise level, the same effect visible in the live demo. Cost: each 500-iteration run over 4,000-step rollouts took about 10 seconds single-threaded on CPU; the identical computation in Warp runs thousands of vehicles as a batch dimension.
Result 3 · Drift detection: the VHM payoff
A second dataset was generated from a vehicle whose front damper had degraded by 25% (cf: 1,500 → 1,125 N·s/m), with everything else unchanged, and re-identified starting from the healthy estimates. The fit localized the fault cleanly:
Table 7 · Re-identification on the worn-damper dataset (1 mm / 0.5 mrad noise)
Parameter
Fitted vs healthy truth
Interpretation
kf
−0.20%
unchanged, correctly
cf
−24.91%
injected degradation: −25.0%; shift vs healthy estimate: −24.3%
kr
+0.01%
unchanged, correctly
cr
−0.73%
unchanged, correctly
This is the argument of the whole guide in one table. A threshold on ride acceleration would eventually notice something; the identified parameter vector says which component, by how much, with the healthy parameters standing still as the control group. Run continuously against telemetry, the fitted cf is a physically interpretable degradation trend, prognosable like any other health indicator, and the residual after fitting bounds what the model cannot explain.
Reproduce it
The complete experiment is one dependency-light Python file, halfcar_sysid.py, shipped alongside this page (NumPy only, about a minute on CPU). Porting the forward loop to a Warp kernel and replacing the hand-written backward pass with wp.Tape is rung R3 of the project ladder, and the honest way to internalize what the tape is doing for you.
Section 13
Gradients through contact: the fine print
Differentiable simulation's hardest honesty problem: contact is discontinuous, and gradients through discontinuities can be biased, exploding, or subtly wrong while looking perfectly plausible.
1 · Discontinuous events break local linearization
Impacts, stick-slip transitions, and contact making-and-breaking are non-smooth. Research examining gradient correctness through contact shows popular engines can return gradients that disagree with the true sensitivity of position, velocity, and control precisely at these events. Treat gradients near contact transitions as suspect until validated.
2 · A useful gradient is not always the true gradient
Analysis of policy learning with differentiable simulators shows first-order gradients can have lower variance but higher bias than zeroth-order estimates, and can lose empirically in stiff contact-rich settings. The practical stance: use analytic gradients where dynamics are smooth (suspension, thermal, aero), fall back to smoothing, randomized smoothing, or RL where they are not.
3 · Long rollouts, exploding tapes
Backpropagation through time over thousands of steps both consumes memory and compounds Lyapunov growth in chaotic dynamics. The standard toolkit: gradient checkpointing (supported in Warp's autodiff machinery), truncated horizons, and the short-horizon formulation that methods like SHAC exist to exploit.
4 · Softening changes the physics you are differentiating
Compliant and hydroelastic contact models give smoother, better-behaved gradients, which is partly why Newton invests in them, but the smoothed system is not identical to the hard-contact system. Validate identified parameters and optimized designs against the unsmoothed physics, or against Chrono-class reference simulation, before believing them.
Rule of thumb
Gradient trustworthiness roughly tracks smoothness: thermal and electrical, excellent; aero fields, good; suspension over smooth roads, good; contact-rich maneuvers, curbs, and impacts, verify everything twice.
Section 14
Choosing a gradient estimator
"Differentiable" names a capability, not a decision. For any given problem you still choose how to estimate the gradient, and the contact caveats of Section 13 are really a claim that this choice should be deliberate.
Table 8 · Gradient estimators, honestly compared
Estimator
Cost per gradient
Variance
Bias
Reach for it when
Analytic adjoint (Warp tape)
≈ one forward + one backward, independent of parameter count
None (deterministic)
None where dynamics are smooth; potentially wrong at contact events
Thermal, electrical, aero fields, suspension over smooth roads; many parameters (the adjoint's superpower)
Central finite differences
2 × n_params forwards
None
Discretization; step-size sensitivity
Verifying the adjoint; few parameters; any solver at all, including non-differentiable references like Chrono
Randomized smoothing
k forwards per gradient (k ≈ 8–64)
Moderate, shrinks with k
Deliberate: you are differentiating a smoothed objective
Contact-rich objectives with discrete events; when analytic gradients are technically defined but practically useless
Zeroth-order / ES / policy gradient
Many full rollouts
High
Low (in the smoothed sense)
Long horizons, chaotic or heavily discontinuous dynamics, policy learning where BPTT explodes
Hybrid short-horizon (SHAC-style)
Truncated BPTT + a learned value function
Reduced vs pure RL
Inherits value-function error
Policy learning where you want first-order efficiency without differentiating through the full episode
A serviceable decision procedure: start with the analytic adjoint and verify it against finite differences on a shrunken problem. If verification fails near contact events or gradients are noisy-looking despite deterministic code, switch the contact-adjacent portion to randomized smoothing or supply a custom smoothed adjoint via Warp's custom-gradient mechanism. If horizons are long enough that gradient norms grow exponentially, truncate and go hybrid. Reserve pure zeroth-order methods for the problems that have defeated everything above; they are the most robust and the most expensive.
Section 15
Sim-to-real: closing the loop with the physical vehicle
A simulator earns its keep only if conclusions transfer. The gap between simulation and reality is not one thing, and each of its components has a different remedy.
A taxonomy of the gap
Five distinguishable error sources, in roughly increasing order of stubbornness: parameter error (masses, stiffnesses, friction coefficients are wrong), contact model error (the functional form of contact is wrong, not just its coefficients), actuator error (real actuators have torque curves, delays, saturation, backlash, and temperature dependence that idealized joints lack), sensor error (bias, noise, quantization, and latency between the world and the measurement), and unmodeled dynamics (flexibility, slop, and physics your model class cannot express at all).
Identify first, then randomize
Domain randomization, training against a distribution of simulated worlds so the real world looks like one more sample, is the standard robustness tool, but randomizing blindly trades performance for robustness you may not need. The disciplined sequence uses the machinery of this guide: identify what can be identified from real trajectories (Sections 02 and 12), which collapses parameter error to a posterior; then randomize around that posterior, wide where identification was uncertain, narrow where it was confident. In Newton this is mechanically trivial, because per-environment randomization is just writes into the model's parameter arrays; every environment in the batch is a different plausible vehicle.
Model the boring parts
Transfer failures are attributed to contact more often than they are caused by it. Actuator and sensor models are the unglamorous half of sim-to-real: a first-order lag and delay on actuation, torque-speed limits, IMU bias random walks, and measurement latency cost little to implement and routinely dominate the residual gap. They also belong inside the differentiated program, so their parameters are identified alongside the plant's.
Residuals for the last mile, and for health
What remains after identification and honest actuator modeling is structural: the model class itself falls short. This is where learned residual dynamics, the NeRD pattern, earns its place: keep the analytic core, let a network absorb the systematic remainder, fine-tune it on real trajectories. The VHM reading is the same as everywhere in this guide: a residual model whose magnitude grows over a vehicle's life is telling you the physical system has moved, and the direction of its growth says something about where.
A validation protocol worth writing down
Hold out maneuvers, not just trajectories: validate on excitation types the identification never saw. Report reality-gap metrics per channel (position, velocity, load) rather than one aggregate. Track identified parameters over repeated sessions; their scatter is your honest uncertainty. And predeclare the acceptance threshold before running the comparison, the same discipline a DFMEA review would demand of any other verification activity.
Section 16
How this stacks with PhysicsNeMo
Part I and Part II are not rivals; they are two halves of one workflow. Surrogates learn from simulation; differentiable engines make simulation itself trainable infrastructure.
Four composition patterns cover most of the practical territory:
Data generation. Newton and Warp-based solvers generate the training corpora that PhysicsNeMo recipes consume, at GPU throughput and with programmatic parameter sweeps, feeding Curator ETL exactly like any other solver output.
Physics-in-the-loop training. Because Warp interoperates zero-copy with PyTorch, a differentiable solver can sit inside a training loop as a layer: the network proposes, the physics evaluates, and gradients flow through both. This is the solver-in-the-loop pattern that pure surrogate training cannot express.
Residual physics, both directions. NeRD adds a learned residual to an analytic engine; PhysicsNeMo's predictor-corrector fine-tuning adds a learned corrector to a pretrained surrogate. Same idea, opposite anchors. A mature pipeline may use both, with the residual magnitudes doubling as model-trust diagnostics.
Cross-validation. A differentiable analytic model is the cheapest independent check on a learned surrogate, and vice versa. Disagreement between them, localized in state space, is a map of where neither should be trusted alone, which is exactly the kind of evidence a V&V case for a digital twin needs.
One sentence to carry away: PhysicsNeMo makes physics learnable; Warp and Newton make it differentiable; the interesting engineering lives where the two meet.
Section 17
A starter project ladder
Five rungs, each one afternoon to one week, each producing something you keep.
R1Warp basics
One kernel, one gradient
Implement a quarter-car spring-damper as a Warp kernel across a thousand parallel environments; recover a known spring rate from a synthetic trajectory using wp.Tape and gradient descent.
the identified k matches ground truth to under one percent
R2Newton basics
Run, view, export
Install Newton, run three shipped examples across the gl and usd viewers, and import one of your own URDF or MJCF assets. Read one solver's source to see how it consumes the Model/State API.
your own asset simulating, exported as a USD you can replay
R3Identification
Half-car system ID on real-ish data
Build a half-car in Newton, generate trajectories with hidden parameters plus noise, and identify spring, damper, and mass parameters by gradient descent. Then perturb a parameter mid-trajectory and detect the drift, your first simulation-based health monitor.
drift detected with a localized, interpretable parameter estimate
R4Custom solver
A differentiable thermal model in warp.fem
Assemble a 2D transient heat solver for a simplified module cross-section, drive it with a load profile, and compute hot-spot sensitivity to a contact resistance via the tape. Cross-check against finite differences.
adjoint and finite-difference sensitivities agree to tolerance
R5Integration
Physics-in-the-loop with PyTorch
Wrap a Newton rollout as a differentiable layer in a PyTorch training loop, train a small controller or residual model through it, and log where gradients degrade near contact, connecting the lesson of Section 13 to your own data.
a training curve, and a written note on where the gradients stopped being trustworthy
Section 18
Glossary
The working vocabulary of this guide, in one place.
Adjoint method
Computing sensitivities of a scalar output by solving the reverse (adjoint) problem once, at cost independent of the number of parameters; reverse-mode autodiff is its algorithmic form.
Tape
The record of operations (in Warp, kernel launches) captured during a forward pass, replayed in reverse with adjoint kernels to accumulate gradients.
BPTT
Backpropagation through time: applying reverse-mode differentiation across the steps of a rollout. Memory grows with horizon; gradients can grow with the dynamics' Lyapunov exponents.
Reverse vs forward mode
Reverse mode: one backward pass yields gradients of one output w.r.t. all inputs (ideal for many parameters, one loss). Forward mode: one pass per input direction (ideal for few inputs, many outputs).
Gradient checkpointing
Storing only periodic states during the forward pass and recomputing the segments between them during backward, trading compute for tape memory.
Semi-implicit (symplectic) Euler
Integrator that updates velocity first, then position with the new velocity; the workhorse of real-time physics for its energy behavior at large timesteps.
Reduced vs maximal coordinates
Reduced: state is joint coordinates, constraints exact by construction (Featherstone). Maximal: each body carries full 6-DoF state, joints enforced as constraints (XPBD-style). Different trade-offs in speed, drift, and gradient conditioning.
XPBD
Extended position-based dynamics: compliant constraints solved on positions, stable and fast; the modern form of the position-based family.
VBD
Vertex block descent: a per-vertex optimization scheme for deformables (cloth, cables, volumetric solids) well suited to GPU parallelism.
MPM
Material point method: continuum material carried on particles, computed on a background grid; the tool of choice for granular media, snow, and soil.
SDF
Signed distance field: an implicit surface representation returning distance-to-surface (negative inside), enabling fast, smooth collision queries.
Hydroelastic contact
A compliant contact model producing distributed pressure fields over patch areas instead of point forces, better-behaved physically and for gradients than rigid point contact.
CUDA graph
A recorded sequence of GPU operations replayed as a unit, eliminating per-launch overhead; the key to stepping thousands of small physics kernels efficiently.
Zero-copy interop
Sharing GPU memory between frameworks (Warp ↔ PyTorch/JAX) via DLPack without copying, letting physics sit inside a training loop at no transfer cost.
MJCF / URDF / USD
The three asset dialects Newton ingests: MuJoCo's simulation-native XML, ROS's ubiquitous robot description, and OpenUSD's composable scene description.
System identification
Estimating a model's physical parameters from measured input-output data; with a differentiable simulator, gradient descent on simulation-vs-measurement error.
Domain randomization
Training against a distribution of simulated worlds so the real world resembles a sample from it; best centered on an identified posterior rather than guessed bounds.
Sim-to-real gap
The composite discrepancy between simulated and physical behavior: parameter, contact, actuator, sensor, and unmodeled-dynamics error, each with its own remedy.
Section 19
Learning resources
Table 9 · Where to learn what
Resource
What it is for
Link
Newton repository
Source, examples runner, contribution and governance links
Newton: an open-source, GPU-accelerated physics engine for robotics, built on NVIDIA Warp. Linux Foundation project, Apache 2.0. github.com/newton-physics/newton
Macklin, M. "Warp: A High-Performance Python Framework for GPU Simulation and Graphics." NVIDIA GTC, 2022. github.com/NVIDIA/warp
NVIDIA Technical Blog. "Build Accelerated, Differentiable Computational Physics Code for AI with NVIDIA Warp." 2026. developer.nvidia.com/blog
Isaac Lab: a GPU-accelerated simulation framework for multi-modal robot learning, with Newton engine integration. 2025. arXiv:2511.04831
Differentiable simulation methods
Hu, Y., et al. "DiffTaichi: Differentiable Programming for Physical Simulation." ICLR 2020. arXiv:1910.00935
Xu, J., et al. "Accelerated Policy Learning with Parallel Differentiable Simulation" (SHAC). ICLR 2022. arXiv:2204.07137
Suh, H. J. T., Simchowitz, M., Zhang, K., Tedrake, R. "Do Differentiable Simulators Give Better Policy Gradients?" ICML 2022. arXiv:2202.00817
"Differentiable Physics Simulations with Contacts: Do They Have Correct Gradients w.r.t. Position, Velocity and Control?" 2022. arXiv:2207.05060
Macklin, M., Müller, M., Chentanez, N. "XPBD: Position-Based Simulation of Compliant Constrained Dynamics." Motion in Games, 2016.
Howell, T., Le Cleac'h, S., Kolter, Z., Schwager, M., Manchester, Z. "Dojo: A Differentiable Physics Engine for Robotics." 2022. arXiv:2203.00806
Werling, K., Omens, D., Lee, J., Exarchos, I., Liu, C. K. "Fast and Feature-Complete Differentiable Physics for Articulated Rigid Bodies with Contact" (Nimble). RSS 2021. arXiv:2103.16021
Neighboring engines
Todorov, E., Erez, T., Tassa, Y. "MuJoCo: A Physics Engine for Model-Based Control." IROS 2012. MJX (JAX) ships within the MuJoCo repository. github.com/google-deepmind/mujoco
Freeman, C. D., et al. "Brax: A Differentiable Physics Engine for Large Scale Rigid Body Simulation." 2021. arXiv:2106.13281
Ataei, M., Salehipour, H. "XLB: A Differentiable Massively Parallel Lattice Boltzmann Library in Python." Computer Physics Communications, 2024. github.com/Autodesk/XLB
Drake: model-based design and verification for robotics. Toyota Research Institute. drake.mit.edu
Project Chrono: multi-physics simulation with the Chrono::Vehicle module. projectchrono.org
On citation hygiene
Package versions (newton 1.3.0, warp-lang 1.15.0, mujoco-warp 3.10.x) were verified against PyPI in July 2026; arXiv identifiers were verified against the sources. Newton's API surface is young and evolving, so prefer the current documentation over any code sketch in this guide when signatures disagree.