dart-demos (Python)
June 19, 2026 ยท View on GitHub
A scene-registry runner that hosts DART's Python demo scenes in the shared
Filament viewer. This is the Python-first World demo surface from PLAN-103; C++
dart-demos (PLAN-102) is the smaller World-only C++ companion.
Run
pixi run py-demos # default: open rigid_body
pixi run py-demos -- --scene rigid_solver_compare # compare SI vs IPC visually
pixi run py-demos -- --scene replay_scrubber # open the replay timeline
pixi run py-demos -- --scene articulated # select any scene by id
pixi run py-demos -- --scene gui_fidelity_debug_visuals
pixi run py-demos -- --cycle-scenes --frames 4 # cycle through every scene
pixi run py-demos -- --list # print the scene catalog
Or directly (without pixi), from the repo root:
PYTHONPATH=build/default/cpp/Release/python:python \
.pixi/envs/default/bin/python -m examples.demos --scene rigid_body --frames 5
CLI
The runner mirrors C++ dart-demos to keep the cross-language UX consistent:
| Flag | Meaning |
|---|---|
--scene <id> | Select the initial scene (default: rigid_body) |
--cycle-scenes | Advance through every scene for --frames frames and exit |
--frames N | Per-scene step budget (default 60 single, 4 cycle) |
--screenshot PATH | Write the final rendered frame as a binary PPM image |
--out DIR | Write a numbered binary PPM frame sequence |
--headless | Render without opening an interactive window |
--show-ui | Include ImGui panels in headless screenshots |
--list | Print the catalog and exit |
In cycle mode, --frames N is the per-scene budget. The host prints
Cycling demo scene <i>/<N>: <scene_id> as it advances, which keeps long
headless or live-window catalog smokes diagnosable.
--screenshot and --out use the real Filament render path. For visual
debugging, avoid --backend noop: it can exercise CPU code but produces blank
pixels and is not evidence for layout, camera, lighting, or material quality.
Visual debugging
Capture one frame:
pixi run py-demo-capture -- --scene rigid_body --frames 2 \
--width 640 --height 360
The helper writes a PPM, converts it to PNG, rejects blank captures, and prints
the artifact paths. On Linux it defaults to the same software Mesa settings used
by GUI tests, so captures stay useful on dev hosts where the desktop GL driver
is unavailable. With --show-ui, it also rejects screenshots that do not show
the docked workspace and drops early warm-up frames before ImGui is visible from
the converted frame sequence. For scenes in the maintained rigid workflow, the
single-scene manifest.json also records workflow_guidance with the row
number, role, workflow phase, focus axis, user question, try-first action,
inspect signals, healthy signal, and scope note. Capture the docked ImGui
workspace:
pixi run py-demo-capture -- --scene rigid_solver_compare --show-ui --frames 2 \
--width 1280 --height 720
Capture motion evidence for a solver comparison:
pixi run py-demo-capture -- --scene rigid_solver_compare --frames 72 \
--width 960 --height 540 --show-ui --video --fps 24
Scene-owned replay state can also be restored before capture with
--scene-state-json. This is useful for reproducible visual A/B packets where a
panel control would otherwise need to be clicked manually. Add
--capture-label to give the stateful capture a distinct default output
directory and artifact stem. For example, capture the rigid_body baseline with
the boxed-LCP contact method selected:
pixi run py-demo-capture -- --scene rigid_body --frames 180 \
--width 960 --height 540 --show-ui \
--scene-state-json '{"controls":{"contact_method_index":1}}' \
--capture-label boxed_lcp
The docked workspace has a top Simulation toolbar, a searchable Demos
navigator, scene-specific panels on the right, bottom scene panels when a demo
owns timeline controls, and a docked DART diagnostics panel. Use Rebuild to
reload the active scene, Restart to reload and run it from the beginning, and
Layout to restore the default docks after rearranging panels. When frame
capture is active, the Simulation panel also exposes a timeline scrubber over
the recorded PPM sequence with first/previous/play/next/last controls and the
selected frame path.
The first 36 World Rigid Body entries in the interactive Demos navigator
are prefixed with their workflow position and role, such as
01/36 Baseline: World Rigid Body or
15/36 Solver family: Rigid Solver Compare. --list keeps the stable scene
titles and ids for scripts.
World-backed scenes also get a bottom Replay panel. Save replay is enabled
by default and records bounded DART 7 World state snapshots while the
scene runs. Use the replay transport or scrubber to pause the live simulation,
restore a saved frame, and play the saved states without stepping physics again;
Resume live continues simulation from the selected restored state. Scenes with
live controller state outside the World can provide small replay-state
capture/restore callbacks; the shared panel stores those mutable controller
snapshots beside the World frames instead of storing static scene assets.
Rigid body visual verification workflow
The rigid-body rows are ordered as a short debugging path instead of a flat
feature list. Start with rigid_body for default World rigid dynamics,
use rigid_body_modes when dynamic/static/kinematic mode semantics need a
first check, use deactivation_sleeping when the public sleep/wake
deactivation surface needs inspection, use rigid_free_flight when contact-free initial velocity,
gravity, spin, inertia, momentum, or energy diagnostics need inspection, use
rigid_frame_hierarchy when body-fixed sensor/tool frames, local transforms,
world transforms, or relative transforms need inspection, use
rigid_external_loads when force and torque accumulator response needs
inspection alongside direct rigid-body impulse momentum, use
rigid_link_point_loads when off-center force application and world/local
frame semantics need inspection, use
rigid_timestep_sensitivity when World.time_step or gravity tuning
changes integration error, contact timing, clearance, or step cost, use
rigid_step_diagnostics when per-stage step profiling, ECS counters, or
frame-scratch memory need inspection across scene complexity, use
rigid_contact_scale_budget when contact-count scaling, per-contact cost,
scratch usage, or a user frame budget needs inspection, use
rigid_restitution_ladder when material bounce response needs inspection,
use rigid_material_mixing when body/surface material ownership or pair
mixing rules need inspection, then use rigid_contact_inspector when raw
contact pairs need inspection, use rigid_collision_query_options when
World.collide(options) body-kind filtering or ignored pairs need inspection, use
rigid_collision_casts when raycast or swept-sphere hit queries need
inspection, including swept-capsule link/tool proxies and capture metrics, use
rigid_solver_compare, rigid_executor_equivalence, and
rigid_contact_solver_compare when the question is solver family, executor
parity, or contact policy, then use contact when multibody links need to
drop, slide, or push through solver contact. Continue through the focused
threshold, stability, manipulation, kinematic-driver, joint, distance-spring,
dynamics, and loop-closure rows when those behaviors need inspection.
World Rigid Body
here means World-facade rigid debugging: solver-family rows compare sequential
impulse and IPC, executor-equivalence rows hold the selected physics solver
constant across executors, and focused threshold or stability rows may pin one
solver or contact policy when that is the user question. The older Rigid IPC
category remains a solver-specific capability shelf for one-off IPC contact
cases such as edge-drops, piles, no-tunneling, and capture-first stack packets.
In the interactive viewer, every numbered World Rigid Body row also gets a
compact Rigid Workflow panel. It mirrors the maintained PLAN-103 question for
the current row as a small checklist: the workflow phase, the row's focus axis,
what to try first, what to look for, and what not to infer from that row. The
workflow phases group rows into foundations; diagnostics; contact, material,
and query basics; the solver decision path; contact behavior cases; rigid
constraints and joint mechanics; and multibody dynamics and kinematics. The
focus axis names the main comparison or debugging dimension, such as solver
family, executor, contact-policy, workload size, passive joint parameters,
backend/profile diagnostics, or loop-closure family, before the user opens a
scene. The panel also has selectable previous/next numbered rows, a restart
command, a direct row selector, a per-row
live py-demos --scene open command, a paired py-demo-capture command with
frame/resolution/UI settings, and a ranked text filter over row ids, scene ids,
labels, questions, workflow phases, focus axes, signals, and explicit aliases
such as
RigidBodySolver, SI, boxed LCP, ContactSolverMethod, worker count,
accelerated backend, compute backend, CUDA, GPU, CUDA backend,
GPU backend, backend comparison, Taskflow executor,
executor comparison, semi-implicit, variational solver,
joint damping, joint friction, throughput, latency, raycast,
swept sphere, friction coefficient, coefficient of restitution,
time-of-impact, CollisionQueryOptions, generalized force, coriolis,
compute_impulse_response, RigidBody.apply_linear_impulse, stack jitter,
closed chain, closed loop, direct rigid body impulse, sleep wake,
island activation, and loop closure compliance that request in-viewer scene
switches.
The filter folds punctuation, underscores, hyphens, dotted API names,
CamelCase, compact API tokens, and simple plurals, so queries such as
RigidBody.applyLinearImpulse, Multibody.computeImpulseResponse,
ray-cast, shape-cast, body kind filters, or resting contacts find the
same rows as their documented snake_case or singular forms.
Search-result tooltips name the match source, such as maintained alias, row
number, user question, workflow phase, focus axis, related evidence, or scope
caveat, so users can see why the navigator chose a row before switching scenes.
Public activation searches such as sleep wake and island activation route
to the related deactivation_sleeping verifier. Deferred public-API searches
such as loop closure compliance also show a deferred API caveat in the
tooltip, guide payload, workflow manifest, and static review card before
opening or reviewing the closest current verifier row. Workflow manifests
include deferred_api_caveat_summary, and review indexes include a top-level
Deferred API Caveats table and badge for packet triage.
Broad queries keep the list compact by showing the top six ranked rows, but the
panel also states the full match count so users can tell when a term like
contact or solver has more rows than are visible.
Backend-status terms route to
rigid_step_diagnostics, while executor terms route to the same-solver
rigid_executor_equivalence row. Scope caveats remain visible in the row, so
deferred public-API searches route to the closest current row without claiming
unsupported compliance behavior. Direct rigid-body impulse API searches route
to the public load/impulse row, activation API searches open the public
deactivation scene as related evidence, and multibody impulse-response API
searches route to the generalized dynamics row. The filter ranks positive
intent matches first so searches such as
contact, solver, step profile, backend comparison,
GPU backend, variational solver, joint damping, raycast,
friction coefficient, CollisionQueryOptions, generalized force,
compute_impulse_response, closed chain,
executor comparison, and sequential impulse do not get dominated by early
rows that only mention what not to infer. Related-evidence searches such as
rigid_ipc_tunnel,
rigid_ipc_edge_drop, or avbd prismatic open the related shelf scene directly
through the maintained route table. Comparison and parameter rows also label the
comparison axis and held-fixed controls in the panel and capture metrics so
solver, executor, contact-policy, workload-size, and parameter-family changes
are not conflated.
The full workflow capture writes a top-level review_index.html contact sheet
next to manifest.json so all numbered screenshots, per-scene manifests,
frame directories, live open commands, workflow-row rerun commands, direct
capture commands, and metric summaries can be reviewed from one page. Rows with
scene-owned Replay timeline metadata also write a JSON-safe
scene_metadata.replay_timeline summary into each per-scene manifest, and the
review card names the Replay track plus whether it has signal and marker
tracks. The top-level manifest and review header record the exact workflow
packet command that produced the artifact, so a reviewer can rerun the same
selected packet. Workflow manifests also record workflow_phase_summary, and
the review header shows a Workflow Phase Map with selected numbered row
ranges, phase count, per-phase status, focus axes, and scene ids so row-range
packets remain readable at a glance. Successful scene captures also promote a
machine-readable
resolved_solver_identity block from the latest scene metrics into the
per-scene manifest; workflow manifests count those identities and list any
captured row missing one, while the review cards show the resolved solver
summary beside the row's workflow phase, focus axis, comparison axis, and
controls.
Workflow packets require that identity to include both a solver-family field
and a context field such as
executor, contact method, same-solver marker, or held-fixed configuration.
Workflow manifests also count rows with latest scene metrics and list any
captured row missing metrics. Non-dry-run workflow packets return failure status
when a captured row misses scene metrics or solver identity evidence, and the
review index highlights those rows before a reviewer treats the packet as
complete. Review cards also promote nested step-diagnostics lane metrics into
a compact backend-diagnostics line, so backend activity, accelerated-stage
counts, worker counts, top stages, and stage timings are visible without
opening the raw manifest JSON. Contact-query and collision-cast review cards
also promote selected contact/depth, query-filter, ignored-pair, ray hit, swept
probe, time-of-impact, and cast-margin values into latest signals, so
reviewers can scan the query rows without opening raw manifests. The panel also
includes a current-row motion packet command; workflow
packets pass --video --fps through to the selected row captures and the review
index links MP4 artifacts when ffmpeg is available.
Extended workflow packets also keep optional related-evidence, direct Rigid IPC
shelf, and capture-first packet rows self-describing in manifest.json and
review_index.html: each optional row records its role, user question,
try-first action, inspect signals, healthy signal, and scope note. The manifest
also records guidance completeness, and the review index shows a guidance badge
plus a warning block if any selected row is missing those fields.
| Order | Scene id | User question | Primary controls | Visual diagnostics |
|---|---|---|---|---|
| 01/36 | rigid_body | What is the baseline World rigid-body path? | Solver, materials, replay, force drag, reset | Speed, height, energy, contacts, step timing |
| 02/36 | rigid_body_modes | Which body mode should I choose? | Executor, gravity, force, kinematic speed | Dynamic fall, static drift, kinematic path error |
| 03/36 | rigid_free_flight | Do initial velocity, gravity, and spin evolve? | Executor, launch speed/angle, gravity, spin/inertia | Path error, momentum residual, energy drift, spin ratio |
| 04/36 | rigid_frame_hierarchy | Where is a sensor/tool frame on a moving body? | Executor, body yaw/path, local offset/yaw | Parent frame, world pose, relative/world residuals |
| 05/36 | rigid_external_loads | How do loads and impulses move/spin bodies? | Force/torque, direct impulse, mass/inertia, executor | Acceleration, impulse momentum, angular speed, static drift |
| 06/36 | rigid_link_point_loads | Do point forces create lever-arm torque? | Force, point offset, body yaw, executor | Translation, yaw acceleration, pulse clear, frame split |
| 07/36 | rigid_timestep_sensitivity | How does time step size change a drop? | Executor, base time step, gravity scale | Free-fall error, contact timing, clearance, step time |
| 08/36 | rigid_step_diagnostics | Where does a World step spend time and memory? | Executor, reset | Stage/domain/backend status, ECS, scratch, contacts |
| 09/36 | rigid_contact_scale_budget | How much contact fits in my frame budget? | Executor, frame budget, friction | Contact count, wall ms, per-contact cost, scratch |
| 10/36 | rigid_restitution_ladder | How does restitution change bounce height? | Executor, launch height, restitution scale | Height, vertical speed, contact, energy trend |
| 11/36 | rigid_material_mixing | Which material owns bounce or friction response? | Impact/tangent speed, low/high e and mu, executor | Effective max restitution, sqrt friction, swap deltas |
| 12/36 | rigid_contact_inspector | Which contact pairs and manifold fields exist? | Shape pair, penetration | Contact count, point, normal, depth, shape ids, metrics |
| 13/36 | rigid_collision_query_options | Which body-kind pairs does a query include? | Query toggles, ignored-pair selector | Active/ignored contacts, body kinds/casts, shape ids |
| 14/36 | rigid_collision_casts | Where do rays and swept probes hit? | Ray offset, all-hit, sphere/capsule sweep controls | Ray fractions, TOI, hit point/normal, cast margins, metrics |
| 15/36 | rigid_solver_compare | What changes between sequential impulse and IPC? | Executor, launch speed, friction, restitution | Speed, wall clearance, solver divergence, step time |
| 16/36 | rigid_executor_equivalence | Does parallel execution preserve the same physics? | Fixed SI solver, launch speed, friction, restitution | Pose/velocity divergence, contact count, step time, metrics |
| 17/36 | rigid_contact_solver_compare | What changes when contact solver policy changes? | Executor, launch speed, friction, restitution, tilt | Contact count, depth, clearance, speed, divergence |
| 18/36 | contact | Do articulated links contact like rigid bodies? | Executor, friction, restitution, drop/slide/push | Link contacts, rebound, slide travel, target travel |
| 19/36 | rigid_friction_threshold | Where is the stick/slip boundary? | IPC fixed, executor, ramp angle, controlled friction | Friction-threshold axis, drift, speed, clearance, metrics |
| 20/36 | rigid_spin_roll_coupling | Does friction couple sliding and spin? | SI fixed, executor, friction, speed, backspin | Spin/roll axis, slip speed, roll ratio, spin change, metrics |
| 21/36 | rigid_stack_stability | Does a top-heavy stack jitter or collapse? | SI vs IPC, executor, top mass ratio, friction | Solver-family axis, top drift, clearance, divergence, metrics |
| 22/36 | rigid_contact_manipulation | Can a pusher move an object through contact? | SI vs IPC, pusher speed, friction, pusher mass | Pusher-contact axis, travel divergence, contact/proximity |
| 23/36 | rigid_kinematic_driver | Does prescribed motion carry objects by contact? | IPC grip/slip vs SI caveat, speed, friction, executor | Tangential axis, box travel, slip, caveat, contacts |
| 24/36 | rigid_kinematic_normal_push | Can prescribed normal motion push a target? | IPC vs SI caveat, push speed, target mass, executor | Normal-contact axis, travel divergence, depth, contacts |
| 25/36 | rigid_fixed_joint | Does a fixed joint preserve its captured pose? | Sequential joints, static base, perturbation, reset | Fixed-transform axis, pose error, payload speed, Replay marks |
| 26/36 | rigid_joint_breakage | What happens when a fixed joint breaks? | AVBD joints, weak break force, static base | Break-force axis, broken state, release distance, reset |
| 27/36 | rigid_distance_spring | How do distance springs enforce rest length? | Executor, rest length, initial stretch, gravity | Distance-spring axis, lane stretch, offset spin |
| 28/36 | rigid_limited_joints | Do one-DOF joints keep only their free axis? | Sequential joints, static bases, z axis | One-DOF axis, locked errors, free-axis motion |
| 29/36 | rigid_joint_motor_limits | Do joint motors and limits clamp commands? | World joints, velocity/position/effort limits | Actuator axis, motor clamp, force gap |
| 30/36 | rigid_joint_passive_parameters | Do passive joint parameters shape motion? | Executor, spring/rest/damping, friction, drive forces | Passive axis, energy decay, slip, armature lag |
| 31/36 | rigid_screw_joint_pitch | Does screw pitch couple rotation and translation? | World screw joints, pitch, mass, inertia | Screw axis, pitch ratios, travel gap, reverse sign |
| 32/36 | rigid_multibody_dynamics_terms | What do generalized dynamics terms mean? | World dynamics, acceleration, impulse, gravity | Dynamics axis, coupling, torque gap, response ratio |
| 33/36 | rigid_link_center_of_mass | How do COM offsets change gravity torque? | World links, COM offset, mass, gravity | COM axis, torque sign, mirror sum, inertia lag |
| 34/36 | rigid_link_jacobian | What does a link Jacobian map? | World Jacobian motion, elbow phase, wrench controls | Jacobian axis, link speed, gap, torque, residual |
| 35/36 | rigid_multibody_solver_family | Which multibody solver family supports solves? | Multibody solve policy, gravity, executor | Solver-family axis, residual ratio, lane errors |
| 36/36 | rigid_loop_closure | Which loop-closure family should I use? | Closure family/policy, gravity, executor | Closure axis, ratios, family-specific residuals |
For the focused IPC no-tunneling capability view, use
rigid_ipc_tunnel from the Rigid IPC shelf. It is kept outside the
numbered World Rigid Body workflow because it is an IPC-only capability scene,
not a broad side-by-side solver row. In the viewer, the Rigid Solver Compare
row exposes it as a Related shelf route. Its capture metrics report wall
clearance, through-wall margin, velocity, contact count, step timing, and
whether the IPC barrier held the fast box before it tunneled through the thin
wall.
For the focused IPC degenerate edge-contact capability view, use
rigid_ipc_edge_drop from the Rigid IPC shelf. It is also routed from
Rigid Solver Compare as related evidence. Its panel and capture metrics report
barrier gap, tilt, angular speed, contact count, step timing, and edge-barrier
status as a cube tips near a single edge while IPC keeps positive separation.
The rest of the Rigid IPC shelf is also capture-metric backed for direct
inspection. rigid_ipc records basic box/ground barrier-settle height, speed,
gap, contact, and timing evidence; rigid_ipc_slide records friction-braked
tangential travel and barrier gap; rigid_ipc_incline records tilted-ramp
down-slope speed, travel, and ramp gap; and rigid_ipc_pile records multi-box
pile speed, height, clearance, span, contact count, and timing evidence. These
direct shelf scenes keep shared replay controls enabled while recording those
metrics.
The older floating_base and articulated rows stay in the broader
World Rigid Body catalog outside the numbered verifier block. In the
viewer, Rigid Free Flight routes to floating_base for the floating-joint
SE(3) drift/spin example, and Rigid Multibody Dynamics Terms routes to
articulated for the compact two-link arm example. Their capture metrics keep
the related routes from being screenshot-only evidence by recording
floating-joint speed/position histories and articulated arm speed, height, and
damping diagnostics.
For AVBD-specific rigid constraint variants, use the AVBD Rigid Constraints
(sx) shelf. In the viewer, the Contact, Rigid Joint Breakage, and Rigid Joint Motor Limits rows expose Related shelf routes to
avbd_rigid_fixed_joint_contact, avbd_rigid_breakable_joint,
avbd_rigid_spherical_breakable_joint, avbd_rigid_revolute_motor,
and avbd_rigid_prismatic_motor. These remain outside the numbered World
Rigid Body workflow because they are AVBD capability rows, not broad World
solver comparisons.
Rigid body baseline
The rigid_body scene is the default front door for DART 7 rigid-body
World dynamics. It keeps the first run simple: falling spheres and a box,
static ground, live replay, viewport force drag, fixed-solver context, named
material presets, an explicit reset path, and a compact panel for baseline
speed, height, energy, contact, material, and step-timing state. Use the
focused rows below when a material,
contact-query, solver, executor, friction, stacking, manipulation, body-mode,
kinematic, external-load, point-load, time-step, or joint behavior needs deeper
inspection.
The rigid_body_modes scene compares the three public rigid-body modes in
one contact-free World. The dynamic lane integrates gravity and force, the
static lane keeps its transform fixed while still reporting the applied load,
and the kinematic lane follows a prescribed path while exposing the mode flag
and path error. The panel and capture metrics now label the rigid-body mode
semantics comparison axis and held-fixed solver/executor/gravity/force/body-mass
context before the lane diagnostics. Use rigid_kinematic_driver later in the
workflow when the question is contact-driven prescribed motion.
Rigid free flight
The rigid_free_flight scene keeps contacts out of the question while
showing initial rigid-body state evolution directly. Separate no-contact lanes
show zero-gravity linear drift, a gravity arc against analytic trajectory and
momentum references, and low/high-inertia spin bars with the same angular
velocity. The panel exposes executor, launch speed, launch angle, gravity
scale, spin speed, inertia ratio, position error, momentum residual, energy
drift, spin momentum/energy ratios, contact count, and step timing.
Rigid frame hierarchy
The rigid_frame_hierarchy scene keeps contacts and forces out of the
question while making rigid frame composition visible. A kinematic rigid body
moves on a simple path with a body-fixed sensor/tool frame attached by a local
offset and yaw. The panel exposes executor, body yaw speed, path radius, local
offset, local yaw, parent-frame name, body and sensor world pose, world-transform
residual, relative-transform residual, orientation error, and step timing.
Rigid external loads
The rigid_external_loads scene keeps contacts and gravity out of the
question so users can inspect external rigid-body load semantics directly.
Matched lanes show persistent apply_force() response on light and heavy
bodies, direct linear impulse response through
RigidBody.apply_linear_impulse(), a one-step force pulse that is explicitly
cleared, persistent apply_torque() response on low- and high-inertia bodies,
direct angular impulse response through RigidBody.apply_angular_impulse(),
and a static body that retains force/torque accumulators while remaining fixed.
The panel exposes force magnitude, torque magnitude, direct linear impulse,
direct angular impulse, mass ratio, inertia ratio, executor choice, speed,
linear impulse momentum, acceleration versus expected acceleration, angular
response, angular impulse momentum, static drift, and step timing.
Rigid link point loads
The rigid_link_point_loads scene covers the public one-shot
Link.apply_force(force, point, force_in_world_frame, point_in_world_frame)
path for floating rigid links. It complements rigid_external_loads by showing
that centered forces translate without spin, world-space off-center point
forces add lever-arm torque, two force applications before one World.step()
accumulate, a one-shot point force is consumed by the next step, and yawed
links respond differently to world-frame and local-frame forces. The panel
exposes force magnitude,
point offset, yaw angle, executor choice, translation acceleration versus
expected acceleration, yaw acceleration versus expected yaw acceleration,
displacement, and step timing.
Rigid time-step sensitivity
The rigid_timestep_sensitivity scene makes time-step and gravity tuning
visible without changing the displayed simulation-time advance per frame.
Three matched Worlds drop identical spheres with fine, medium, and coarse
integration steps while using substeps so all lanes reach the same displayed
time. The panel uses the fixed realtime solver and exposes executor, base time
step, gravity scale, free-fall error against the analytic no-contact reference,
clearance, first contact time, contact count, coarse/fine error ratio, and
step-profile timing.
It is a convergence and parameter-sensitivity diagnostic, not a solver
correctness proof or exact contact-threshold claim.
Rigid step diagnostics
The rigid_step_diagnostics scene makes World.last_step_profile and
World.memory_diagnostics visible in the GUI. Three side-by-side Worlds run a
single free body, an active contact pair, and a small stack under the same fixed
realtime solver and selected executor so users can inspect how scene complexity
changes wall time, stage totals, top stage, worker count, ECS entity/component
counts, contact count, frame-scratch peak usage, and overflow/reset counters.
The top
stage also reports its domain, backend-neutral acceleration mask, and whether
any accelerated backend stage was active, so users can separate executor choice
from actual accelerator use. If step profiling is compiled out, the row still
reports memory and contact diagnostics and marks profile timing as unavailable.
py-demo-capture records the same profiling, memory, contact, worker, and
backend-status metrics into the manifest sidecar.
Rigid contact scale budget
The rigid_contact_scale_budget scene keeps performance inspection on the
same live-GUI surface as the rest of the workflow. Three matched Worlds run one-,
four-, and nine-box contact workloads under the fixed realtime solver, executor,
frame budget, and friction value. The panel reports contact-point count, bodies,
contacts per body, wall time, per-contact cost, top profile stage, frame-scratch
peak usage, ECS counters, worker count, dense/single wall-time ratio, and whether
each lane is within the selected budget. It is a bounded frame-budget diagnostic,
not a benchmark suite or heavy IPC stress packet.
py-demo-capture records the same contact workload, frame-budget, wall-time,
scratch-memory, ECS, and budget-status metrics into the manifest sidecar.
Rigid restitution ladder
The rigid_restitution_ladder scene makes the public restitution material
parameter visible without mixing it into a broader contact scenario. Three
matched lanes drop identical rigid spheres onto separate ground pads with
low, medium, and high restitution. The panel uses the fixed realtime solver and
exposes executor, launch height, and restitution scale, then plots height,
vertical velocity, contact
count, rebound height, and mechanical-energy trends as diagnostics rather than
exact conservation claims.
Rigid material mixing
The rigid_material_mixing scene shows what happens when the rigid body and
its contact surface disagree on material values. Two swapped bounce lanes show
that sequential-impulse rigid contact uses the larger restitution value, while
two swapped flat sliding lanes show that friction uses the geometric mean of
the body and surface coefficients. The panel computes the expected pair values
from public RigidBody.restitution and RigidBody.friction properties, plots
rebound and tangential speed loss, and treats the swapped lanes as an ownership
check rather than a duplicate restitution ladder or incline threshold proof.
Rigid contact inspector
The rigid_contact_inspector scene is the contact-observability row for
the rigid workflow. It keeps static targets and kinematic probes in stable
overlap so World.collide() can be inspected directly across representative
public shape families: sphere/box, box/ground, plane/sphere, capsule/sphere,
cylinder/sphere, mesh/sphere, and compound/sphere. The panel shows selected
pair count, total contact count, representative point, normal, depth, local
points, and shape indices, including the compound-child index path, while a
marker highlights the selected contact point in the scene. Docked captures now
carry the same selected-pair manifold fields through scene-owned capture metrics.
Rigid collision query options
The rigid_collision_query_options scene makes the public
World.collide(options) body-kind filters and persistent ignored-pair table
visible. Four matched sphere-overlap lanes cover rigid/rigid, rigid/link,
same-multibody link/link, and cross-multibody link/link contacts. The panel
toggles each CollisionQueryOptions include flag, selects one ignored pair,
shows baseline, option-filtered, pair-ignored, and active contact counts, marks
filtered lanes explicitly, and keeps shape-index diagnostics available without
turning the row into a solver comparison.
py-demo-capture records the same include-toggle, ignored-pair, contact-count,
body-kind, cast, lane-status, and shape-index metrics into the manifest sidecar.
Rigid collision casts
The rigid_collision_casts scene turns public collision cast queries into a
visual debugging row before users compare solver behavior. It shows
CollisionGroup.raycast_result() with nearest-hit versus all-hit behavior and
CollisionGroup.sphere_cast_result() plus
CollisionGroup.capsule_cast_result() time-of-impact queries. The panel
exposes ray lateral offset, all-hit mode, sphere radius, capsule radius, capsule
offset, and capsule cylinder height, then reports target names, hit fractions,
first hit point/normal, time of impact, cast margins, and histories without
claiming contact-solver or CCD time-step behavior. The capsule lane is for
elongated swept-volume debugging, such as robot links, tools, and character
controller proxies that a ray or sphere can under-explain.
Rigid body solver comparison
The rigid_solver_compare scene is the first rigid-body visual-debug bench
that runs two matched DART 7 Worlds side by side: sequential impulse on the left
and rigid IPC on the right. It keeps the scene intentionally small, a sliding
box approaching a thin wall, so users can inspect solver-family differences,
clearance, speed, position divergence, and per-step profile timing without
waiting on heavier stack scenes. The panel names the comparison axis as the
rigid-body solver family and also exposes the shared executor choice
(Sequential or Parallel (2 workers)) so execution changes are framed as
performance/equivalence checks rather than as different physics. Its capture
metrics record the same comparison axis, solver pair, case order, executor
selection, controls, per-solver response metrics, and divergence ranges.
Rigid executor equivalence
The rigid_executor_equivalence scene answers the executor question
directly: two matched DART 7 Worlds run the same rigid-body tray with one fixed
realtime physics solver, while the left world steps with the sequential executor
and the right world steps with a parallel executor. The panel names the physics
solver and keeps friction, restitution, and launch speed explicit, then plots
pose divergence, velocity divergence, contact-count delta, and per-executor step
time so users can tell executor performance changes apart from physics changes.
The panel names the comparison axis as executor-only. Its capture metrics record
the same comparison axis, same-solver identity, selected solver index, controls,
per-executor contact/timing metrics, divergence ranges, and fallback executor
label when parallel execution is unavailable. The shared Replay panel uses
pose divergence as the timeline signal and marks frames where executor
divergence or contact-count mismatch appears, matching the solver-family and
contact-policy comparison rows.
Rigid contact solver comparison
The rigid_contact_solver_compare scene separates the contact-solver policy
axis from the broader rigid-body solver family. Both lanes use the same
sequential-impulse rigid-body pipeline and the same tilted plank falling into
four-corner ground contact; the left lane keeps the default sequential-impulse
contact policy, while the right lane opts into boxed LCP contacts. The panel
names the comparison axis as contact solver method, keeps executor, launch
speed, friction, restitution, and initial tilt explicit, then plots contact
count, penetration depth, analytic corner clearance, speed, kinetic energy,
pose divergence, and per-step timing. Its capture metrics record the same
comparison axis, contact-policy pair, case order, executor selection, controls,
per-policy response metrics, and divergence ranges.
Capture rows 15-17 together when reviewing the core solver decision path:
pixi run py-demo-capture -- --rigid-workflow --workflow-start-row 15 \
--workflow-end-row 17 --output-dir /tmp/dart_capture_rigid_solver_contact
That packet keeps the solver-family, executor-only, and contact-policy axes
adjacent in review_index.html, while each row card preserves its live open
command, workflow rerun command, direct capture command, guidance, Replay track,
scene-owned metric keys, held-fixed/control values, and the latest decision
signals such as solver pair, executor pair, contact-policy pair, divergence,
and step/contact counters.
Capture rows 19-21 together when reviewing the common contact-failure path:
pixi run py-demo-capture -- --rigid-workflow --workflow-start-row 19 \
--workflow-end-row 21 --output-dir /tmp/dart_capture_rigid_contact_failures
That packet keeps the friction-threshold, spin/roll, and stack-stability rows adjacent. Their row cards show the comparison axis, held-fixed solver/executor or solver-family controls, user-editable controls, and latest signals such as threshold-lane drift, contact slip/spin change, solver pair, top-x divergence, and solver clearance.
Rigid link contact
The contact scene is the articulated-link contact row in the numbered
rigid workflow. It keeps the stable scene id but now shows three multibody-link
lanes: a prismatic link dropping and rebounding on ground, a link sliding until
friction brakes it, and a prismatic pusher link transferring motion to a rigid
target. The panel exposes executor, ground friction, restitution, drop height,
slide speed, and push speed, then plots link contact counts, rebound, slide
travel, target travel, and step timing. It is a public multibody-link contact
verifier, not a contact-impulse, compliance, or solver-internal force row.
Rigid friction threshold
The rigid_friction_threshold scene turns the inclined-ramp friction law
into a three-lane visual verifier. The upper lane uses friction below
tan(angle) and should slide, the lower lane uses friction above that threshold
and should stick, and the middle lane is user-controlled. The panel keeps the
threshold calculation visible, resets the run when the controlled friction or
ramp angle changes, names friction relative to the static threshold as the
comparison axis, and lists IPC/executor/time step as held fixed. It plots
down-slope drift and speed so users can debug stick/slip behavior without
relying on exact-at-threshold claims. Capture metrics record the threshold,
controlled-friction delta, per-lane friction, drift, speed, clearance, status,
held-fixed values, step timing, and compact history ranges.
Rigid spin/roll coupling
The rigid_spin_roll_coupling scene shows the rotational side of contact
friction after the stick/slip threshold row: matched rolling, no-spin sliding,
backspin scrub, and a low-friction slip baseline move on the same surface. The
panel names spin/roll initial condition as the comparison axis, keeps the
sequential-impulse solver, executor, and time step held fixed, then exposes
contact friction, launch speed, and backspin ratio. It plots contact slip, roll
ratio, travel, kinetic energy, contact count, and step timing. It is a
sequential-impulse visual diagnostic for linear/angular coupling, not a
rolling-resistance or torsional-friction parameter surface. Capture metrics
record the solver/executor, controls, held-fixed values, contact count,
per-lane slip, roll ratio, spin delta, travel, energy, friction, status, step
timing, and compact history ranges.
Rigid stack stability
The rigid_stack_stability scene is a compact resting-contact stress test:
sequential impulse and rigid IPC solve the same two-block top-heavy stack side
by side. The stack is intentionally small so it remains usable in the live GUI
while still showing the mass-ratio failure mode users care about: residual
jitter, lateral drift, clearance/overlap, and per-step solve cost. The panel
names the rigid-body solver family as the comparison axis, lists executor, top
mass ratio, friction, and time step as held fixed, lets users tune the top mass
ratio and friction, resets the stack, and compares max speed, top-block drift,
minimum analytic clearance, and solver divergence. Capture metrics record the
solver pair, executor, controls, held-fixed values, per-solver speed, drift,
clearance, height error, step timing, top-x divergence, and compact history
ranges. The shared Replay panel uses top-x divergence as its value track and
marks frames where overlap, low clearance, visible top-block drift, or
solver-family divergence make the stack worth scrubbing.
Rigid contact manipulation
The rigid_contact_manipulation scene turns the rigid workflow from
isolated micro-cases into a small task-like push. Sequential impulse and rigid
IPC solve matched table scenes side by side: a heavier moving pusher block
drives a lighter target box toward a goal strip. The panel names the rigid
pusher contact response as the comparison axis, keeps the matched table/goal,
target mass, executor, and time step visible as held fixed, exposes pusher
launch speed, table friction, pusher mass, and executor choice, then plots
target travel, pusher-target gap, contact/proximity evidence, target speed,
lateral drift, solver divergence, and per-step timing.
Capture metrics record the comparison axis, solver pair, executor, held-fixed
values, controls, per-solver target travel, pusher gap, contact count, target
speed, lateral drift, goal error, step timing, travel divergence, and compact
history ranges. The workflow review card surfaces travel divergence, both
solver lanes' target travel, contact counts, and solver pair as latest signals.
The shared Replay panel uses travel divergence as its value track and marks
pusher contact, proximity, target-motion, and solver-divergence frames for fast
scrubbing.
Rigid kinematic driver
The rigid_kinematic_driver scene verifies the public prescribed-motion
rigid-body path. Three lanes make the expected behavior and caveat visible: IPC
with grip friction carries a box on a moving kinematic support, IPC with zero
friction lets the support slip under the box, and the sequential-impulse lane
shows the current static-like caveat for kinematic bodies. The panel exposes
the prescribed tangential contact-response comparison axis, held-fixed
executor, tangential support, box mass, and time step, then shows driver speed,
grip friction, executor choice, driver travel, box travel, slip, speed ratio,
support gap, and step timing.
Capture metrics record the comparison axis, solver/case pair, held-fixed
values, IPC grip/slip lanes, the sequential-impulse caveat lane, solver enums,
friction modes, controls, per-lane driver travel, box travel, slip, speed
ratio, support gap, contact count, status, step timing, and compact history
ranges. The workflow review card surfaces IPC grip box travel, grip speed
ratio, low-friction slip, sequential-impulse caveat driver travel, IPC grip
proximity gap, and solver pair as latest signals. The shared Replay panel
uses the IPC grip lane's box travel as its value track and marks contact,
carried-progress, slip, and static-like caveat frames.
The rigid_kinematic_normal_push scene keeps the next prescribed-motion
question separate: what happens when a kinematic paddle moves normally into a
target? It is a caveat verifier. Sequential impulse pushes the target forward,
while IPC normal and heavier-target lanes expose the current penetration
failure mode instead of silently promoting it as a supported manipulation path.
The panel names prescribed normal contact response as the comparison axis,
keeps executor, normal kinematic paddle, zero friction, and time step visible
as held fixed, and then shows push speed, target mass, driver travel, target
travel, analytic gap, penetration depth, contact count, speed ratio, and step
timing. Capture metrics record lane order, solver pair, controls, held-fixed
values, IPC penetration depth, SI push travel, contact counts, target-travel
divergence, and compact history ranges. The shared Replay panel uses
target-travel divergence as its value track and marks contact, IPC penetration,
SI push-progress, and divergence frames.
Capture rows 22-24 together when reviewing the task-like contact branch:
pixi run py-demo-capture -- --rigid-workflow --workflow-start-row 22 \
--workflow-end-row 24 --output-dir /tmp/dart_capture_rigid_kinematic_push
That packet keeps the rigid pusher, tangential kinematic driver, and normal kinematic push caveat adjacent. The row-24 card shows the prescribed normal contact axis, held-fixed kinematic-paddle context, push controls, IPC penetration depth, SI target travel, and target-travel divergence.
Rigid joint constraints
The rigid_fixed_joint scene is a focused fixed-constraint verifier. Its
panel labels the fixed-relative-transform recovery axis and held-fixed
sequential joint context, can deliberately perturb the child body away from the
captured relative transform, then plots relative offset error, orientation
error, and residual payload speed as the constraint projects the payload back
to the fixed pose. Capture metrics expose the same axis, held-fixed context,
top-level translation/orientation error, payload speed, angular speed, and
nested history summaries so the workflow review card can show the final
fixed-joint pose-recovery signals directly. The shared Replay panel uses
fixed-joint offset error as its value track and marks pose-error or
residual-motion frames during recovery.
The rigid_joint_breakage scene is the next fixed-joint lifecycle row. It
is explicitly AVBD-pinned: a very weak fixed joint starts intact, crosses a
break-force threshold, turns the connector red when is_broken becomes true,
and exposes reset_breakage() behavior without claiming sequential-impulse or
IPC parity. The panel includes a log-scale break-force threshold control plus
reset paths for the current threshold, locked reset, and weak re-arm. The panel
and capture metrics label the fixed break-force lifecycle comparison axis, the
held-fixed AVBD/static-base context, active threshold diagnostics, and top-level
breakage signals for release distance, broken state, captured-offset error,
payload speed, and status. The shared Replay panel uses payload release
distance as its value track and marks broken or released frames so saved-state
scrubbing jumps to the breakage event.
The rigid_distance_spring scene shows the public
World.add_rigid_body_distance_spring() path on free rigid bodies before users
move to one-DOF joints. It keeps the solver scope explicit: distance springs
are AVBD-backed rows in the sequential rigid-body World path, while IPC and
multibody Worlds reject this API. The panel compares an unsprung baseline,
soft and stiff center springs, and an off-center anchor lane with editable
rest length and per-lane stiffness controls, stretch, payload speed, angular
speed, and step timing. The panel, replay state, and capture metrics label the
distance-spring response-family comparison axis, the held-fixed
executor/rest-length/payload/time-step context, lane order, public spring
parameters, and top-level review signals for free, soft, stiff, and offset
absolute stretch plus off-center angular speed. The shared Replay panel uses
maximum spring stretch as its value track and marks high-stretch or off-center
spin frames.
The rigid_limited_joints scene verifies the public revolute and prismatic
rigid-body joint rows without making motor or limit claims. The hinge lane
tracks locked anchor radius and z error while its free z-axis spin continues;
the slider lane tracks locked lateral error while its z-axis travel remains
free. Both lanes expose perturb/reset controls so the bounded errors are
visible in the same live GUI workflow as the contact scenes. The panel and
capture metrics label the one-DOF joint constraint-family axis, held-fixed
sequential-joint/static-base/z-axis context, lane names, and top-level review
signals for locked hinge radius/z error, locked slider orthogonal error, hinge
yaw, slider travel, and free-axis speeds. The shared Replay panel uses
locked-axis error as its value track and marks constraint-error or free-axis
motion frames.
The rigid_joint_motor_limits scene covers the public World multibody joint
actuator path for rigid links. It keeps three compact lanes visible at once: a
prismatic velocity motor whose commanded speed is clamped by a velocity limit,
a gravity-driven revolute link settling at a position stop, and capped versus
reference force sliders showing the acceleration gap created by an effort
limit. The panel exposes the command and limit values directly, then plots
motor speed, position-limit error, and force-response histories.
py-demo-capture records the same row identity, actuator scope, control values,
joint names, motor clamp, position-stop, force/effort-cap, acceleration-gap,
step-timing, and compact history metrics into the manifest sidecar. The panel
and capture metrics label the World multibody actuator/limit comparison axis,
held-fixed x-axis prismatic rail and y-axis revolute-stop context, lane names,
and top-level review signals for motor speed, expected speed, speed error,
position-limit angle/error, force travel gap, and force acceleration gap. The
shared Replay panel uses force travel gap as its value track and marks
velocity-clamp, position-stop, and effort-cap frames.
The rigid_joint_passive_parameters scene covers the public passive
multibody joint parameters for rigid links without contacts or gravity. Matched
prismatic lanes show a spring-only oscillator, the same spring with damping,
Coulomb stiction versus slip under held efforts, and direct versus
armature-loaded drive. The panel exposes spring stiffness, rest position,
damping, Coulomb friction, separate hold/slip/armature drive forces,
armature, acceleration-versus-expected diagnostics, energy histories, and
step timing.
py-demo-capture records the same lane order, executor, spring/rest/damping,
Coulomb friction, hold/slip/armature drive forces, armature, acceleration,
energy, step-timing, and compact history metrics into the manifest sidecar.
The panel and capture metrics label the passive joint-parameter comparison
axis, held-fixed World-prismatic/gravity-off/contact-free/mass/time-step
context, lane names, and top-level review signals for spring energy, damped
energy, damped-energy ratio, slip speed, armature position gap, and armature
acceleration gap. The shared Replay panel uses armature position gap as its
value track and marks damping energy separation, Coulomb slip, and
armature-lag frames.
The rigid_screw_joint_pitch scene shows the public screw-joint pitch
semantics: pitch is axial translation per radian of rotation. Zero, fine,
coarse, and reverse-pitch lanes run under gravity so users can see rotation
sign, axial travel, travel-per-radian ratio, effective mass, and
expected-versus-actual acceleration from mass and axial inertia.
py-demo-capture records lane order, executor, pitch/gravity/mass/inertia
controls, per-lane pitch, angle, axial travel, travel-per-radian, acceleration,
effective mass, mass matrix, step-timing, and compact history metrics into the
manifest sidecar. The panel and capture metrics label the screw pitch coupling
comparison axis, held-fixed contact-free World screw-joint/mass/inertia/time
step context, lane names, and top-level review signals for zero-pitch axial
travel, fine/coarse/reverse pitch, coarse/fine travel gap, reverse angle, and
fine-lane acceleration residual. The shared Replay panel uses coarse/fine
travel gap as its value track and marks pitch-spread, zero-pitch contrast, and
reverse-sign frames.
The rigid_multibody_dynamics_terms scene makes the public generalized
dynamics accessors visible before the solver-family and loop-closure rows. A
single hinge, a coupled two-link arm, and a heavy-distal two-link arm show
mass_matrix, inverse_mass_matrix, compute_inverse_dynamics(), and
compute_impulse_response() under one contact-free World. The panel keeps the
diagnostics compact: matrix shape and conditioning, one off-diagonal coupling
term, inverse-dynamics residual, joint-space impulse residual, torque norm, and
response norm.
py-demo-capture records lane order, executor, target-acceleration, impulse,
heavy-mass, gravity, per-lane mass/coupling/conditioning/residual/torque/
response fields, heavy-versus-coupled ratios, step timing, and compact history
metrics into the manifest sidecar. The panel and capture metrics label the
joint-space dynamics term comparison axis, held-fixed contact-free World
dynamics/fixed-base/revolute-link/target-acceleration/impulse/gravity/time step
context, lane names, and top-level review signals for the single-hinge mass
diagonal, coupled off-diagonal mass term, heavy-load torque gap,
coupled-versus-heavy response gap, heavy response ratio, and residual checks.
The shared Replay panel uses coupled-versus-heavy response gap as its value
track and marks response-separation, off-diagonal-coupling, and heavy-load
torque frames.
The rigid_link_center_of_mass scene keeps the link visual geometry fixed
while moving Link.center_of_mass in the link frame. Centered, +X, -X, and
high-inertia lanes show when gravity torque is zero, why mirrored COM offsets
accelerate in opposite directions, and how the same offset produces a smaller
acceleration when the link inertia is larger. Yellow markers show the actual
center of mass, and the panel reports gravity torque, mass matrix, hinge
acceleration, expected acceleration, COM position, energy, and step timing.
py-demo-capture records lane order, executor, COM/gravity/mass/inertia
controls, per-lane link/joint/local-COM metadata, mirrored torque/angle/
acceleration sums, reflected mass and acceleration ratios, COM marker position,
energy, step timing, and compact histories into the manifest sidecar.
The panel and capture metrics label the link center-of-mass offset comparison
axis, held-fixed contact-free World revolute-link/fixed-visual-geometry/mass/
gravity/time step context, lane names, and top-level review signals for
centered/positive/negative gravity torque, mirrored angle sum, high-inertia
mass and acceleration ratios, and acceleration residual. The shared Replay
panel uses mirrored COM angle spread as its value track and marks
offset-driven angle divergence, centered-lane stillness, and high-inertia lag
frames.
The rigid_link_jacobian scene makes link-origin Jacobians concrete before
users move from generalized dynamics terms into solver-family routing. A
contact-free two-link arm shows get_world_jacobian(link) @ qdot as the
end-link origin twist, compares it against a finite-difference velocity, and
uses get_world_jacobian(link).T @ wrench to show joint torque power
consistency. It is intentionally scoped to the link origin: it does not claim
arbitrary point, COM, contact, IK, or operational-space controller behavior.
py-demo-capture records controls, joint names, link-origin position, twist,
finite-difference error, wrench force, transpose-mapped torques,
joint-versus-wrench power, world/body Jacobian gap, and compact histories into
the manifest sidecar.
The panel and capture metrics label the link-origin Jacobian mapping
comparison axis, held-fixed contact-free World two-revolute-link/time-step/
finite-difference context, the Jacobian term family, and top-level review
signals for link linear/angular speed, world/body Jacobian gap,
finite-difference error, transpose-mapped torques, and power residual.
The shared Replay panel uses link-origin speed as its value track and marks
high-twist, wrench-load, world/body Jacobian gap, and residual-alert frames.
The rigid_multibody_solver_family scene makes the World multibody
integration-family choice visible before users enter the loop-closure family
row. It compares semi-implicit residual-only closure diagnostics, variational
residual-only diagnostics, and variational dynamic closure solving on the same
three-link chain. The panel exposes executor and gravity controls, residual
norms, tip error, tip height, joint speed, step timing, and the residual solve
ratio so users can see why solved loop closures are routed to the variational
path.
py-demo-capture records executor/gravity controls, case order, integration
family and closure policy labels, residuals, tip errors/heights, joint speeds,
step timing, residual solve ratio, and compact history metrics into the
manifest sidecar.
The panel and capture metrics label the multibody integration solve-policy
comparison axis, held-fixed contact-free World point-closure/three-link-chain/
gravity/time-step context, solver-family lane names, and top-level review
signals for residual-only residual, solved residual, residual solve ratio,
semi-implicit and variational residuals, solved tip error, and maximum step
profile time.
The shared Replay panel uses residual solve ratio as its value track and marks
solve-advantage, residual-only drift, and solved-tight frames while residual
rows remain loose.
The rigid_loop_closure scene compares public POINT, DISTANCE, and RIGID
loop-closure families under the variational rigid multibody path. Each family
has residual-only and solved lanes: POINT locks the endpoint position,
DISTANCE holds only the tether length to an anchor, and RIGID welds the full
endpoint pose. The panel plots residual ratios and reports tip error,
distance error, orientation residual, tip height, and joint speed so users can
choose the narrowest closure family that matches the model.
py-demo-capture records executor/gravity controls, family and policy order,
per-case family/policy labels, residuals, tip/distance/orientation errors,
joint speeds, step timing, solved ratios, and compact history metrics into the
manifest sidecar.
The panel and capture metrics label the loop-closure family/policy comparison
axis, held-fixed contact-free variational rigid-multibody/four-link-chain/
gravity/time-step context, closure family and policy lane names, and top-level
review signals for POINT/DISTANCE/RIGID residual ratios, distance-family
distance/tip error, RIGID orientation error, and maximum step profile time.
The shared Replay panel uses max closure residual ratio as its value track and
marks solve-advantage, residual-versus-solved separation, distance-family tip
drift, and rigid-orientation frames.
Use the workflow mode to plan or run the full numbered rigid capture set. It
writes a top-level manifest that points at every per-scene manifest and a
review_index.html contact sheet for scanning the 36 screenshots, row
questions, try-first guidance, scope notes, live open commands, capture
commands, workflow-row rerun commands, and metric summaries from one page: the
in-viewer Rigid Workflow panel also shows the full numbered packet,
current-row rerun, contact-baseline, material-example, AVBD showcase, and
extended related/IPC-shelf/packet commands.
Numbered rows carry their workflow phase and focus axis in the manifest and
review card, while the contact-baseline packet, material-example packet, AVBD
showcase, and optional related, direct IPC shelf, and capture-first packet rows
carry row-guidance fields in the manifest and review index, so non-numbered
packets remain readable without opening the live GUI. The same outputs also
include a guidance-completeness audit and the exact top-level workflow command
for the selected packet.
pixi run py-demo-capture -- --rigid-workflow --dry-run
pixi run py-demo-capture -- --rigid-workflow \
--output-dir /tmp/dart_capture_rigid_workflow
For long review packets, add --continue-on-failure when later rows should
still be captured after one row fails. The manifest records
continue_on_failure=true plus a failed_rows list, and
review_index.html shows a Failed Rows summary with workflow row-range rerun
commands that preserve the packet flags and absolute row numbering. The final
workflow status and process exit code still report failure if any selected row
failed.
pixi run py-demo-capture -- --rigid-workflow --include-related \
--include-ipc-shelf --include-packets --continue-on-failure \
--output-dir /tmp/dart_capture_rigid_workflow_resilient
Add --include-related when the review packet should also capture the
non-numbered related evidence routes after the 36-row workflow:
pixi run py-demo-capture -- --rigid-workflow --include-related --dry-run
pixi run py-demo-capture -- --rigid-workflow --include-related \
--output-dir /tmp/dart_capture_rigid_workflow_with_related
Add --include-ipc-shelf when the packet should also capture the direct
metric-backed Rigid IPC shelf scenes after the numbered rows and any related
evidence routes:
pixi run py-demo-capture -- --rigid-workflow --include-ipc-shelf --dry-run
pixi run py-demo-capture -- --rigid-workflow --include-related \
--include-ipc-shelf --output-dir /tmp/dart_capture_rigid_workflow_with_ipc_shelf
Add --include-packets when the packet should also include capture-first
rigid IPC evidence that is intentionally outside the live 36-row workflow.
Capture-first packets are appended after related evidence and direct Rigid IPC
shelf rows when those groups are requested:
pixi run py-demo-capture -- --rigid-workflow --include-packets --dry-run
pixi run py-demo-capture -- --rigid-workflow --include-related \
--include-packets --output-dir /tmp/dart_capture_rigid_workflow_with_packets
Use --contact-baseline-only when the target is the M1 World contact-policy
baseline. The packet captures the flagship rigid_body scene twice: the
default Sequential Impulse contact path and the same scene restored with the
boxed-LCP contact method before the first frame. Both rows keep stable capture
labels and state metadata in the workflow manifest and review index.
pixi run py-demo-capture -- --rigid-workflow --contact-baseline-only --dry-run
pixi run py-demo-capture -- --rigid-workflow --contact-baseline-only \
--output-dir /tmp/dart_capture_rigid_contact_baseline
Use --material-examples-only when the target is the M1 rigid_body
front-door material examples. The packet captures Default, Slide, and Bounce
variants of the same scene, preserving named material-preset state and capture
labels in the manifest and review index, plus the resolved material-preset name
in the latest scene metrics.
pixi run py-demo-capture -- --rigid-workflow --material-examples-only --dry-run
pixi run py-demo-capture -- --rigid-workflow --material-examples-only \
--output-dir /tmp/dart_capture_rigid_material_examples
Use --avbd-showcase-only when the target is the curated AVBD
rigid-constraint showcase rather than the numbered World rigid workflow. The
packet captures the current fixed-joint/contact, breakable-joint, spherical
breakable-joint, revolute-motor, and prismatic-motor AVBD rows as a
complementary M1 showcase beside the World contact-policy and boxed-LCP
baseline; it is not a head-to-head solver enum comparison.
pixi run py-demo-capture -- --rigid-workflow --avbd-showcase-only --dry-run
pixi run py-demo-capture -- --rigid-workflow --avbd-showcase-only \
--output-dir /tmp/dart_capture_rigid_avbd_showcase
Capture the direct Rigid IPC shelf routes with the docked UI visible:
These commands are also included after the numbered rows, and after related
evidence when present, by
py-demo-capture -- --rigid-workflow --include-ipc-shelf.
pixi run py-demo-capture -- --scene rigid_ipc --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_ipc_slide --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_ipc_incline --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_ipc_pile --frames 72 \
--width 960 --height 540 --show-ui
For targeted reruns after a failed or manually inspected row, keep the same
workflow packet but bound the row range. Row numbers stay absolute, so row 37
still writes under scenes/37_<scene> when related evidence is included. With
--include-related --include-packets, rows 49-50 are the two
capture-first stack packets. If --include-ipc-shelf is also requested, those
packet rows become 53-54.
pixi run py-demo-capture -- --rigid-workflow \
--workflow-start-row 15 --workflow-end-row 17 --dry-run
pixi run py-demo-capture -- --rigid-workflow --include-related \
--include-packets --workflow-start-row 49 --workflow-end-row 50 \
--output-dir /tmp/dart_capture_rigid_workflow_packet_rerun
For row-range packets, manifest fields such as include_related,
include_avbd_showcase, include_ipc_shelf, and include_packets record the
requested packet shape; selected_include_related,
selected_include_avbd_showcase, selected_include_ipc_shelf, and
selected_include_packets record which optional groups are present in the
selected row range. The generated review_index.html header mirrors this with
row-span, requested-groups, and selected-groups badges.
Capture the focused rigid verifier scenes with the docked UI visible:
pixi run py-demo-capture -- --scene rigid_body --frames 180 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_body_modes --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_free_flight --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_frame_hierarchy --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_external_loads --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_link_point_loads --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_timestep_sensitivity --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_step_diagnostics --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_contact_scale_budget --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_restitution_ladder --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_material_mixing --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_contact_inspector --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_collision_query_options --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_collision_casts --frames 48 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_solver_compare --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_executor_equivalence --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_contact_solver_compare --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene contact --frames 144 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_friction_threshold --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_spin_roll_coupling --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_stack_stability --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_contact_manipulation --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_kinematic_driver --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_kinematic_normal_push --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_fixed_joint --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_joint_breakage --frames 48 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_distance_spring --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_limited_joints --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_joint_motor_limits --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_joint_passive_parameters --frames 120 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_screw_joint_pitch --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_multibody_dynamics_terms --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_link_center_of_mass --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_link_jacobian --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_multibody_solver_family --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_loop_closure --frames 72 \
--width 960 --height 540 --show-ui
Capture the related Rigid IPC no-tunneling or degenerate edge-contact views when those focused capabilities are the target:
pixi run py-demo-capture -- --scene rigid_ipc_tunnel --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_ipc_edge_drop --frames 72 \
--width 960 --height 540 --show-ui
Capture the heavier Rigid IPC stack packets when the question is what happens
beyond the live workflow budget. These scenes stay in the Rigid IPC shelf,
outside the numbered workflow, and their panels show min clearance, contact
count, top drift, height error, max speed, wall time, top mass, and the
bm_rigid_ipc_solver benchmark pointer:
pixi run py-demo-capture -- --scene rigid_ipc_stack_packet --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_ipc_heavy_stack_packet --frames 12 \
--width 960 --height 540 --show-ui
These packets are included after the numbered rows, optional related evidence
routes, and optional direct Rigid IPC shelf routes by
py-demo-capture -- --rigid-workflow --include-packets.
For scenes that expose SceneSetup.info["capture_metrics"],
py-demo-capture also writes scene_metrics.jsonl and summarizes the full
scene-owned physics/runtime stream in manifest.json: first and latest events,
per-key presence counts, numeric ranges for top-level metrics, and the
resolved_solver_identity derived from the latest solver/contact/executor
metrics. Workflow captures treat those metrics as required evidence for
completed rows. The step diagnostics and contact-scale budget rows use that path
for profiling, memory, contact, and frame-budget evidence; the IPC no-tunneling
route uses it for clearance and through-wall margin evidence; and the stack
packet uses it for clearance, drift, wall time, and benchmark metadata. The
differentiable contact-gradient routes use it for target/rest height, analytic
versus complementarity-aware thrust/final-height/loss values, height and
target-error gaps, pre-contact counts, identical forward-state evidence,
analytic-freefall error, surrogate block magnitude, vertical sensitivity,
fallback status, and compact history summaries. The AVBD showcase routes use it
for fixed-joint contact offset/clearance/contact counts, breakable fixed and
spherical-joint state, anchor/orientation drift, and free-rigid
revolute/prismatic motor tracking. The early numbered rigid workflow rows use
it for body-mode flags, free-flight
momentum/energy residuals, frame-transform residuals,
force/torque accumulator response, point-load lever-arm response,
time-step error ratios, restitution rebound, and pair-material mixing fields,
so the first-run fundamentals now preserve physics diagnostics in capture
artifacts instead of only screenshots.
When forward rigid contact looks correct but a differentiable optimization is
stuck, jump to diff_drone_liftoff in the Differentiable shelf. It uses
the same rigid World contact-gradient modes to show ANALYTIC stalling at a
clamping contact while COMPLEMENTARITY_AWARE escapes, with thrust, loss,
gradient, and height histories. Its capture metrics report the optimized
mode outcome when diff bindings are enabled. When the body is approaching but
not touching, jump to diff_pre_contact_surrogate. It shows identical
forward motion for ANALYTIC and PRE_CONTACT_SURROGATE while the surrogate
lane adds a backward-only pre-contact Jacobian block. Both scenes record finite
fallback payloads when the default build has DART_BUILD_DIFF=OFF. In the
viewer, the Rigid Contact Solver Compare row exposes them as Related shelf
routes:
pixi run py-demo-capture -- --scene diff_drone_liftoff --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene diff_pre_contact_surrogate --frames 24 \
--width 960 --height 540 --show-ui
Capture every non-numbered related-evidence route with the docked UI visible:
These commands are also included after the numbered rows by
py-demo-capture -- --rigid-workflow --include-related.
pixi run py-demo-capture -- --scene deactivation_sleeping --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene floating_base --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene articulated --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_ipc_tunnel --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene rigid_ipc_edge_drop --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene diff_drone_liftoff --frames 96 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene diff_pre_contact_surrogate --frames 24 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene avbd_rigid_fixed_joint_contact --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene avbd_rigid_breakable_joint --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene avbd_rigid_spherical_breakable_joint \
--frames 72 --width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene avbd_rigid_revolute_motor --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene avbd_rigid_prismatic_motor --frames 72 \
--width 960 --height 540 --show-ui
Capture every AVBD showcase route with the docked UI visible:
These commands are also included in the dedicated AVBD packet by
py-demo-capture -- --rigid-workflow --avbd-showcase-only.
pixi run py-demo-capture -- --scene avbd_rigid_fixed_joint_contact --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene avbd_rigid_breakable_joint --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene avbd_rigid_spherical_breakable_joint \
--frames 72 --width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene avbd_rigid_revolute_motor --frames 72 \
--width 960 --height 540 --show-ui
pixi run py-demo-capture -- --scene avbd_rigid_prismatic_motor --frames 72 \
--width 960 --height 540 --show-ui
The lower-level viewer still accepts --screenshot and --out directly when
you need raw PPM output. Inspect the generated PNG or MP4 before calling a
visual change done.
LCP Physics
The lcp_physics scene is the Python demo baseline for DART 7 contact LCP
work. It runs two matched World instances side by side: the default
sequential-impulse contact path and the boxed-LCP contact path. Both worlds run
the same representative packets:
| Packet | Shows | Metric surfaced in the panel |
|---|---|---|
| Sliding friction | Tangential Coulomb response on a flat slab | Sliding speed and contacts |
| Static-friction ramp | Hold/slip behavior near the friction limit | Ramp-parallel slide |
| Billiard collision | Symmetric contact impulse transfer | Momentum and kinetic-energy error |
| High-mass-ratio stack | Contact stability under large mass ratios | Stack lateral drift and per-step wall time |
| Thin card pile | Thin high-aspect-ratio stacked contacts | Card spread and height loss |
This scene compares the DART 7 public contact methods. The panel also surfaces
the 24-solver standalone LCP manifest, solver support matrix, and benchmark
packet map used for apples-to-apples solver work. It runs the flat dartpy
standalone LCP binding on a shared standard smoke problem for every solver, so
the panel can show status, iteration count, and solution error without going
through a contact World. The representative problem table lists every solver
on each packet and separates native support from delegated fallback solves, with
the fastest native solve highlighted for quick triage. The detailed table also
surfaces residual and complementarity so accuracy comparisons do not rely only
on solution error. A per-solver profile rolls those rows back up by solver so
native surfaces, delegated coverage, pass counts, worst error, worst residual,
and total demo-measured solve time are visible in one apples-to-apples matrix.
Its standard-LCP packet set includes well-conditioned, ill-conditioned,
near-singular, and moderate scale cases so conditioning and size changes are
visible without changing the solver roster. Its friction-index rows include both
a simple normal-scaled contact and a coupled two-contact active-bound packet.
The benchmark packet map includes per-packet benchmark filters, including the
active friction-index microbenchmark and the native world_card_pile packet for
high-aspect-ratio card-pile contact scaling.
Authoritative performance runs remain owned by
tests/common/lcpsolver, tests/unit/math/lcp, and tests/benchmark/lcpsolver.
The panel also points to the checked performance-profile CSVs under
docs/background/lcp/figures and summarizes the current leader/laggard
families per Standard, Boxed, and FrictionIndex profile row family. Refresh
those artifacts with:
pixi run python scripts/lcp_performance_profile.py --run \
--cache build/lcp_profile_full.json \
--output docs/background/lcp/figures \
--benchmark-timeout 900
For a quick profile-pipeline smoke that allows partial native solver coverage without rewriting checked artifacts, write to a scratch output directory:
pixi run python scripts/lcp_performance_profile.py --run \
--allow-partial \
--benchmark-filter BM_LcpCompare/Standard/Dantzig/12 \
--benchmark-min-time 0.01 \
--cache build/lcp_profile_smoke.json \
--output build/lcp_profile_smoke \
--benchmark-timeout 120
Run the benchmark smoke with:
pixi run bm lcp_compare -- --benchmark_filter=BM_LCP_COMPARE_SMOKE
The lcp_physics scene metadata exposes the derived
representative_benchmark_command for the full representative packet filter;
keep the long generated filter list in the scene metadata instead of copying it
into this README.
DART 7 Body Deactivation
deactivation_sleeping showcases the opt-in automatic body deactivation path:
quiet rigid bodies sleep, an active striker wakes them through contact, and an
untouched reference body remains asleep. The scene exposes is_sleeping and
deactivation_group_index in a diagnostics table and works with the shared
headless capture path. The rigid workflow filter routes sleep wake and
island activation searches here as related evidence without a deferred API
caveat:
pixi run py-demo-capture -- --scene deactivation_sleeping --show-ui \
--frames 150 --width 1280 --height 720
AVBD Rigid Constraints (sx)
The dedicated AVBD Rigid Constraints (sx) category groups the first
user-visible Augmented VBD rigid-constraint scenes from PLAN-104:
The fixed-contact, spherical breakable, revolute-motor, and prismatic-motor free-rigid rows are also related evidence from the numbered rigid workflow. They expose scene-owned capture metrics so docked captures preserve the constraint/contact/motor signal instead of relying on screenshots alone.
| Scene id | Shows | AVBD capability exercised |
|---|---|---|
avbd_empty_baseline | An empty variational-integrator World stepping with render-only axes | Source-demo corpus baseline with 2D/3D empty-row revision/default metadata |
avbd_demo2d_ground | The avbd-demo2d Ground source scene as its static 2D ground slab | Source-demo static ground row with matched source geometry and metadata |
avbd_demo2d_motor | The avbd-demo2d Motor source scene as a pinned rigid bar with a velocity motor | First non-empty source-demo row using public AVBD revolute motor rows |
avbd_demo2d_dynamic_friction | The avbd-demo2d Dynamic Friction source scene as sliding boxes over a ground slab | Source-demo rigid friction row with matched source geometry and metadata |
avbd_demo2d_static_friction | The avbd-demo2d Static Friction source scene as rotated 2D boxes on an inclined slab | Source-demo inclined-slab friction row with matched source geometry/metadata |
avbd_demo2d_pyramid | The avbd-demo2d Pyramid source scene as a triangular pile of 2D rigid boxes | Source-demo rigid stacking row with matched source geometry and metadata |
avbd_demo2d_cards | The avbd-demo2d Cards source scene as a thin-card rigid contact tower | Source-demo card-tower contact row with matched source geometry and metadata |
avbd_demo2d_stack | The avbd-demo2d Stack source scene as falling 2D boxes over a ground slab | Source-demo rigid stacking row with matched source geometry and metadata |
avbd_demo2d_stack_ratio | The avbd-demo2d Stack Ratio source scene as geometric-size 2D rigid boxes | Source-demo size-ratio stacking row with matched source geometry and metadata |
avbd_demo2d_rod | The avbd-demo2d Rod source scene as a horizontal all-axis fixed-joint chain | Source-demo rod row with matched hard constraints, geometry, and metadata |
avbd_demo2d_soft_body | The avbd-demo2d Soft Body source scene as two finite-stiffness box lattices | Source-demo soft-body row with finite all-axis joint stiffness and metadata |
avbd_demo2d_joint_grid | The avbd-demo2d Joint Grid source scene as a 25x25 fixed-joint box lattice | Source-demo large joint-grid row with matched hard constraints and metadata |
avbd_demo2d_rope | The avbd-demo2d Rope source scene as a horizontal point-jointed rigid chain | Source-demo rope row with matched anchors, geometry, and metadata |
avbd_demo2d_heavy_rope | The avbd-demo2d Heavy Rope source scene with a large endpoint block | Source-demo high-ratio rope row with matched anchors, geometry, and metadata |
avbd_demo2d_hanging_rope | The avbd-demo2d Hanging Rope source scene as vertical point-jointed links | Source-demo long rope row with matched anchors, geometry, and metadata |
avbd_demo2d_spring | The avbd-demo2d Spring source scene as one radial rigid distance spring | Source-demo finite-stiffness spring row with matched anchors and metadata |
avbd_demo2d_spring_ratio | The avbd-demo2d Spring Ratio source scene as alternating-stiffness radial springs | Source-demo stiffness-ratio row with matched anchors, geometry, and metadata |
avbd_demo2d_net | The avbd-demo2d Net source scene as endpoint-pinned links under falling rigid blocks | Source-demo net row with matched anchors, geometry, and metadata |
avbd_demo2d_fracture | The avbd-demo2d Fracture source scene as falling 2D boxes over weak fixed joints | Source-demo breakable fixed-joint row with public AVBD break thresholds |
avbd_demo3d_ground | The avbd-demo3d Ground source scene as a falling rigid box over a static ground box | Source-demo rigid contact row with matched source geometry and metadata |
avbd_demo3d_dynamic_friction | The avbd-demo3d Dynamic Friction source scene as sliding rigid boxes over ground | Source-demo rigid friction row with matched source geometry and metadata |
avbd_demo3d_static_friction | The avbd-demo3d Static Friction source scene as rigid boxes on an inclined ramp | Source-demo inclined-ramp friction row with matched source geometry/metadata |
avbd_demo3d_pyramid | The avbd-demo3d Pyramid source scene as a triangular pile of rigid boxes | Source-demo rigid stacking row with matched source geometry and metadata |
avbd_demo3d_rope | The avbd-demo3d Rope source scene as anchored rigid links with linear-only point joints | Source-demo rope row with matched anchors, geometry, and metadata |
avbd_demo3d_heavy_rope | The avbd-demo3d Heavy Rope source scene with a large endpoint block | Source-demo high-ratio rope row with matched anchors, geometry, and metadata |
avbd_demo3d_stack | The avbd-demo3d Stack source scene as ten rigid boxes over a static ground box | Source-demo vertical stacking row with matched source geometry and metadata |
avbd_demo3d_stack_ratio | The avbd-demo3d Stack Ratio source scene as a four-box geometric size tower | Source-demo size-ratio stacking row with matched source geometry and metadata |
avbd_demo3d_soft_body | The avbd-demo3d Soft Body source scene as three finite-stiffness box lattices | Source-demo 3D soft-body row with finite all-axis joint stiffness and metadata |
avbd_demo3d_bridge | The avbd-demo3d Bridge source scene with paired point-jointed planks and load boxes | Source-demo bridge row with matched anchors, geometry, and metadata |
avbd_demo3d_breakable | The avbd-demo3d Breakable source scene as rigid boxes, contact shapes, and weak joints | Source-demo breakable fixed-joint row with public AVBD break thresholds |
avbd_rigid_fixed_joint_contact | A fixed rigid payload sliding against static contact | Public fixed-joint rows plus ordinary contact |
avbd_rigid_revolute_motor | A bounded revolute motor driving a free hinge | Public velocity actuator mapped to AVBD motor rows |
avbd_rigid_prismatic_motor | A bounded prismatic motor driving a free rigid slider | Public linear velocity actuator mapped to AVBD motor rows |
avbd_articulated_revolute_motor | A bounded revolute motor reversing an articulated floating link | Public articulated velocity motor updates through the bridge |
avbd_articulated_prismatic_motor | A bounded prismatic motor reversing an articulated floating carriage | Public articulated linear motor updates through the bridge |
avbd_articulated_motor_breakable_joint | A weak articulated revolute motor releasing and re-engaging an articulated floating link | Public articulated motor break/reset lifecycle through the bridge |
avbd_articulated_prismatic_pair_motor_breakable_joint | A weak same-multibody prismatic motor releasing and re-engaging an articulated carriage | Public articulated linear motor break/reset lifecycle through the bridge |
avbd_articulated_prismatic_motor_breakable_joint | A weak world-anchored prismatic motor releasing and re-engaging an articulated carriage | Public articulated linear motor break/reset lifecycle through the bridge |
avbd_articulated_world_revolute_motor_breakable_joint | A weak world-anchored revolute motor releasing and re-engaging an articulated floating link | Public world-anchored articulated motor break/reset lifecycle through the bridge |
avbd_articulated_high_ratio_chain | A five-link variational chain swinging with a 200:1 heavy tip | Narrow articulated high mass-ratio smoke for the AVBD paper gap |
avbd_paper_scale_high_ratio_chain | A 50-link variational chain swinging with a 50,000:1 heavy tip | Paper-scale articulated high mass-ratio visual smoke for the AVBD paper gap |
avbd_rigid_breakable_joint | A weak fixed joint releasing and re-engaging a rigid payload | Public break-force threshold, reset, and broken-state path |
avbd_rigid_spherical_breakable_joint | A weak spherical point joint releasing and re-engaging only a rigid payload anchor | Public free-rigid spherical break/reset while orientation stays free |
avbd_articulated_breakable_joint | A world-anchored floating link released and reset through a public articulated fixed joint | Public articulated world-link break/reset path through the variational bridge |
avbd_articulated_fixed_pair_breakable_joint | A same-multibody fixed joint releasing and restoring a captured relative pose | Public articulated link-link fixed break/reset through the variational bridge |
avbd_articulated_spherical_breakable_joint | A world-anchored floating socket that releases and resets only its anchor | Public articulated spherical break/reset with orientation left free |
avbd_articulated_spherical_pair_breakable_joint | A same-multibody floating socket that releases and resets only its anchor | Public articulated link-link spherical break/reset with orientation left free |
This is an early AVBD rigid-row showcase, not a paper-complete reproduction. The remaining AVBD corpus still needs the full 2D/3D reference demos, paper figures, video/headline scenes, CPU/GPU benchmark packets, and performance comparisons recorded in PLAN-104.
Planned World Ports
The Planned World Ports category keeps important DART 6 demo concepts
visible without keeping the removed DART 6 implementations in the catalog. These
entries are lightweight launchable placeholders with status panels. Each panel
now tells users which current py-demo row to try first, which World/API or asset
gap blocks the full port, and what condition will replace the placeholder with a
usable scene. They track World-native follow-ups for inverse kinematics,
SIMBICON walking, operational-space control, robot puppets, and mobile
manipulation. The old collision sandbox placeholder is retired: use
rigid_contact_inspector, rigid_collision_query_options, and
rigid_collision_casts for concrete collision debugging workflows.
PLAN-083 CPU Corpus
The PLAN-083 Mixed Corpus, PLAN-083 Constraints Corpus,
PLAN-083 Robot Corpus, and PLAN-083 ABD Corpus categories expose
launchable placeholders for the unified Newton-barrier paper/deck scene rows.
Each placeholder records its manifest row IDs, smoke command, long-horizon
visual capture command, benchmark packet target, and current limitation. They
are not paper-scene reproductions yet; the checked corpus sidecar lives at
docs/plans/083-unified-newton-barrier-multibody/cpu-scene-corpus.json and
keeps the py-demo, visual evidence, and CPU benchmark obligations explicit until
runtime mixed-domain stepping and ABD scene support land.
IPC Deformable scenes
The dedicated IPC Deformable category groups the deformable-body
scenes driven by the dartpy IPC solver
(point-mass/spring with IPC-style clamped-log barriers, sparse projected Newton,
lagged smoothed-Coulomb friction, and conservative CCD). They live in their own
category so the IPC showcases stay together:
| Scene id | Shows | IPC capability exercised |
|---|---|---|
ipc_deformable_net | A pinned spring net sagging/swaying under gravity | Projected-Newton elastodynamics |
ipc_deformable_drape | A mat draping over a step onto a ground barrier | Ground + self-contact clamped-log barrier |
ipc_deformable_trampoline | A corner-pinned membrane sagging and rebounding | Taut-membrane projected-Newton dynamics |
ipc_deformable_friction_slide | A launched mat skidding to rest on a frictional floor | Lagged smoothed-Coulomb ground friction |
ipc_deformable_fem_bar | A tetrahedral cantilever sagging under gravity | Stable neo-Hookean FEM elasticity |
ipc_deformable_fem_twist | A tetrahedral bar twisted at both ends, then released | FEM volumetric shear (toward Fig 4/14) |
ipc_deformable_fem_drop | A FEM cube dropped onto a ground barrier, settling | FEM volumetric body + IPC contact |
ipc_deformable_fem_sphere | A FEM slab draping over a sphere obstacle | FEM + sphere obstacle barrier (Newton) |
ipc_deformable_fem_box | A FEM slab draping over a box "table" obstacle | FEM + box obstacle barrier (Newton) |
ipc_deformable_fem_msh | A FEM cantilever loaded from a GMSH .msh tet mesh | FEM body from an imported tet mesh |
ipc_deformable_scripted_dirichlet | A banner billowing under a scripted Dirichlet BC | Scripted Dirichlet boundary conditions |
These are DART-native showcases, not faithful IPC paper-figure
reproductions. The contact, barrier, friction, and projected-Newton machinery
is genuine IPC; most scenes use a mass-spring elasticity model, while the
ipc_deformable_fem_* scenes (cantilever, twist, ground-barrier drop) exercise
the new opt-in stable neo-Hookean FEM volumetric elasticity (PLAN-081 M1,
the keystone toward the paper's volumetric scenes), including a volumetric body
in IPC contact. Codimensional collision and the upstream mesh corpus are still
needed for true figure reproduction. The catalog of upstream paper scenes lives at
docs/plans/081-deformable-implicit-barrier-solver/ipc_scene_corpus_manifest.json;
faithful corpus reproduction stays planned (it needs vendored assets,
codimensional collision, and broader FEM coverage), so these scenes evoke the
paper's themes (volumetric elasticity, draping, self-contact, friction,
scripted boundaries) rather than reproducing
its figures.
The scenes share _ipc_deformable_bridge.py, which builds the grid topology and
mirrors each deformable onto the render world as per-node spheres plus a spring
wireframe (the dynamic surface-mesh render path is not yet exposed through
dartpy.gui.run_demos). IpcDeformableBridge.build_diagnostics_panel(...)
adds shared solver diagnostics such as node counts, fixed nodes, z-range, and a
minimum-height plot to custom scene panels. Add another deformable scene by
building its DeformableBodyOptions with build_grid_options(...) and
rendering it through IpcDeformableBridge.
Simulation Replay
replay_scrubber demonstrates the DART 7 World replay recorder:
the scene records a rigid-body rollout once, restores the first frame, and
exposes a bottom-docked replay timeline with a scrubber, frame marks, a cursor
track, transport controls, loop/rate controls, and cursor details. The scene
uses the reusable PanelBuilder.timeline(...) widget from dartpy.gui for the
timeline lanes. Moving the scrubber calls World.restore_replay_frame(...) at
timestep resolution and does not re-run physics.
The same saved-state replay path is injected by the runner into every
SceneSetup that exposes a DART 7 World in info["sx_world"] or
info["physics_world"]. The shared panel stores only bounded mutable World
snapshots plus optional small scene-provided mutable controller snapshots;
static topology, geometry, materials, and scene construction data remain owned
by the scene and render bridge.
The shared demos toolbar uses the same timeline widget for captured-frame
playback after Capture records viewer frames. That path stores only the
captured image files and derives bounded marker/cursor tracks for the UI each
frame, so large capture directories do not require an equally large in-memory
timeline cache.
Add a scene
- Create
scenes/<name>.pydefining a module-levelSCENEof typePythonDemoScenewhosebuild()returns aSceneSetup(aworldplus an optional custompre_step,step(n),force_drag, scene panels, andinfodict). A scene that wants capture manifests to include scene-owned physics evidence may put a zero-argument metrics callable ininfo["capture_metrics"]. - Import it in
registry.pyand append it to the ordered list inmake_demo_scenes(), placed within its category group.
That's the only change needed; no CMake edits, no test edits beyond the cycle smoke (which iterates the registry).
Scene-specific controls use renderer-neutral ScenePanel callbacks:
def build_panel(builder, context):
builder.text(f"time: {world.time:.3f} s")
changed, friction = builder.slider("Friction", body.friction, 0.0, 1.0)
if changed:
body.friction = friction
return SceneSetup(
world=bridge.render_world,
pre_step=bridge.pre_step,
panels=[ScenePanel("Rigid IPC Slide", build_panel)],
)
The callback receives DART's PanelBuilder abstraction, not ImGui. Use the
builder for text, buttons, checkboxes, sliders, selects, plots, and tables. Use
context for viewer state and lifecycle requests such as pause, single-step,
or switching to another demo scene.