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:

FlagMeaning
--scene <id>Select the initial scene (default: rigid_body)
--cycle-scenesAdvance through every scene for --frames frames and exit
--frames NPer-scene step budget (default 60 single, 4 cycle)
--screenshot PATHWrite the final rendered frame as a binary PPM image
--out DIRWrite a numbered binary PPM frame sequence
--headlessRender without opening an interactive window
--show-uiInclude ImGui panels in headless screenshots
--listPrint 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.

OrderScene idUser questionPrimary controlsVisual diagnostics
01/36rigid_bodyWhat is the baseline World rigid-body path?Solver, materials, replay, force drag, resetSpeed, height, energy, contacts, step timing
02/36rigid_body_modesWhich body mode should I choose?Executor, gravity, force, kinematic speedDynamic fall, static drift, kinematic path error
03/36rigid_free_flightDo initial velocity, gravity, and spin evolve?Executor, launch speed/angle, gravity, spin/inertiaPath error, momentum residual, energy drift, spin ratio
04/36rigid_frame_hierarchyWhere is a sensor/tool frame on a moving body?Executor, body yaw/path, local offset/yawParent frame, world pose, relative/world residuals
05/36rigid_external_loadsHow do loads and impulses move/spin bodies?Force/torque, direct impulse, mass/inertia, executorAcceleration, impulse momentum, angular speed, static drift
06/36rigid_link_point_loadsDo point forces create lever-arm torque?Force, point offset, body yaw, executorTranslation, yaw acceleration, pulse clear, frame split
07/36rigid_timestep_sensitivityHow does time step size change a drop?Executor, base time step, gravity scaleFree-fall error, contact timing, clearance, step time
08/36rigid_step_diagnosticsWhere does a World step spend time and memory?Executor, resetStage/domain/backend status, ECS, scratch, contacts
09/36rigid_contact_scale_budgetHow much contact fits in my frame budget?Executor, frame budget, frictionContact count, wall ms, per-contact cost, scratch
10/36rigid_restitution_ladderHow does restitution change bounce height?Executor, launch height, restitution scaleHeight, vertical speed, contact, energy trend
11/36rigid_material_mixingWhich material owns bounce or friction response?Impact/tangent speed, low/high e and mu, executorEffective max restitution, sqrt friction, swap deltas
12/36rigid_contact_inspectorWhich contact pairs and manifold fields exist?Shape pair, penetrationContact count, point, normal, depth, shape ids, metrics
13/36rigid_collision_query_optionsWhich body-kind pairs does a query include?Query toggles, ignored-pair selectorActive/ignored contacts, body kinds/casts, shape ids
14/36rigid_collision_castsWhere do rays and swept probes hit?Ray offset, all-hit, sphere/capsule sweep controlsRay fractions, TOI, hit point/normal, cast margins, metrics
15/36rigid_solver_compareWhat changes between sequential impulse and IPC?Executor, launch speed, friction, restitutionSpeed, wall clearance, solver divergence, step time
16/36rigid_executor_equivalenceDoes parallel execution preserve the same physics?Fixed SI solver, launch speed, friction, restitutionPose/velocity divergence, contact count, step time, metrics
17/36rigid_contact_solver_compareWhat changes when contact solver policy changes?Executor, launch speed, friction, restitution, tiltContact count, depth, clearance, speed, divergence
18/36contactDo articulated links contact like rigid bodies?Executor, friction, restitution, drop/slide/pushLink contacts, rebound, slide travel, target travel
19/36rigid_friction_thresholdWhere is the stick/slip boundary?IPC fixed, executor, ramp angle, controlled frictionFriction-threshold axis, drift, speed, clearance, metrics
20/36rigid_spin_roll_couplingDoes friction couple sliding and spin?SI fixed, executor, friction, speed, backspinSpin/roll axis, slip speed, roll ratio, spin change, metrics
21/36rigid_stack_stabilityDoes a top-heavy stack jitter or collapse?SI vs IPC, executor, top mass ratio, frictionSolver-family axis, top drift, clearance, divergence, metrics
22/36rigid_contact_manipulationCan a pusher move an object through contact?SI vs IPC, pusher speed, friction, pusher massPusher-contact axis, travel divergence, contact/proximity
23/36rigid_kinematic_driverDoes prescribed motion carry objects by contact?IPC grip/slip vs SI caveat, speed, friction, executorTangential axis, box travel, slip, caveat, contacts
24/36rigid_kinematic_normal_pushCan prescribed normal motion push a target?IPC vs SI caveat, push speed, target mass, executorNormal-contact axis, travel divergence, depth, contacts
25/36rigid_fixed_jointDoes a fixed joint preserve its captured pose?Sequential joints, static base, perturbation, resetFixed-transform axis, pose error, payload speed, Replay marks
26/36rigid_joint_breakageWhat happens when a fixed joint breaks?AVBD joints, weak break force, static baseBreak-force axis, broken state, release distance, reset
27/36rigid_distance_springHow do distance springs enforce rest length?Executor, rest length, initial stretch, gravityDistance-spring axis, lane stretch, offset spin
28/36rigid_limited_jointsDo one-DOF joints keep only their free axis?Sequential joints, static bases, z axisOne-DOF axis, locked errors, free-axis motion
29/36rigid_joint_motor_limitsDo joint motors and limits clamp commands?World joints, velocity/position/effort limitsActuator axis, motor clamp, force gap
30/36rigid_joint_passive_parametersDo passive joint parameters shape motion?Executor, spring/rest/damping, friction, drive forcesPassive axis, energy decay, slip, armature lag
31/36rigid_screw_joint_pitchDoes screw pitch couple rotation and translation?World screw joints, pitch, mass, inertiaScrew axis, pitch ratios, travel gap, reverse sign
32/36rigid_multibody_dynamics_termsWhat do generalized dynamics terms mean?World dynamics, acceleration, impulse, gravityDynamics axis, coupling, torque gap, response ratio
33/36rigid_link_center_of_massHow do COM offsets change gravity torque?World links, COM offset, mass, gravityCOM axis, torque sign, mirror sum, inertia lag
34/36rigid_link_jacobianWhat does a link Jacobian map?World Jacobian motion, elbow phase, wrench controlsJacobian axis, link speed, gap, torque, residual
35/36rigid_multibody_solver_familyWhich multibody solver family supports solves?Multibody solve policy, gravity, executorSolver-family axis, residual ratio, lane errors
36/36rigid_loop_closureWhich loop-closure family should I use?Closure family/policy, gravity, executorClosure 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.

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.

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:

PacketShowsMetric surfaced in the panel
Sliding frictionTangential Coulomb response on a flat slabSliding speed and contacts
Static-friction rampHold/slip behavior near the friction limitRamp-parallel slide
Billiard collisionSymmetric contact impulse transferMomentum and kinetic-energy error
High-mass-ratio stackContact stability under large mass ratiosStack lateral drift and per-step wall time
Thin card pileThin high-aspect-ratio stacked contactsCard 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 idShowsAVBD capability exercised
avbd_empty_baselineAn empty variational-integrator World stepping with render-only axesSource-demo corpus baseline with 2D/3D empty-row revision/default metadata
avbd_demo2d_groundThe avbd-demo2d Ground source scene as its static 2D ground slabSource-demo static ground row with matched source geometry and metadata
avbd_demo2d_motorThe avbd-demo2d Motor source scene as a pinned rigid bar with a velocity motorFirst non-empty source-demo row using public AVBD revolute motor rows
avbd_demo2d_dynamic_frictionThe avbd-demo2d Dynamic Friction source scene as sliding boxes over a ground slabSource-demo rigid friction row with matched source geometry and metadata
avbd_demo2d_static_frictionThe avbd-demo2d Static Friction source scene as rotated 2D boxes on an inclined slabSource-demo inclined-slab friction row with matched source geometry/metadata
avbd_demo2d_pyramidThe avbd-demo2d Pyramid source scene as a triangular pile of 2D rigid boxesSource-demo rigid stacking row with matched source geometry and metadata
avbd_demo2d_cardsThe avbd-demo2d Cards source scene as a thin-card rigid contact towerSource-demo card-tower contact row with matched source geometry and metadata
avbd_demo2d_stackThe avbd-demo2d Stack source scene as falling 2D boxes over a ground slabSource-demo rigid stacking row with matched source geometry and metadata
avbd_demo2d_stack_ratioThe avbd-demo2d Stack Ratio source scene as geometric-size 2D rigid boxesSource-demo size-ratio stacking row with matched source geometry and metadata
avbd_demo2d_rodThe avbd-demo2d Rod source scene as a horizontal all-axis fixed-joint chainSource-demo rod row with matched hard constraints, geometry, and metadata
avbd_demo2d_soft_bodyThe avbd-demo2d Soft Body source scene as two finite-stiffness box latticesSource-demo soft-body row with finite all-axis joint stiffness and metadata
avbd_demo2d_joint_gridThe avbd-demo2d Joint Grid source scene as a 25x25 fixed-joint box latticeSource-demo large joint-grid row with matched hard constraints and metadata
avbd_demo2d_ropeThe avbd-demo2d Rope source scene as a horizontal point-jointed rigid chainSource-demo rope row with matched anchors, geometry, and metadata
avbd_demo2d_heavy_ropeThe avbd-demo2d Heavy Rope source scene with a large endpoint blockSource-demo high-ratio rope row with matched anchors, geometry, and metadata
avbd_demo2d_hanging_ropeThe avbd-demo2d Hanging Rope source scene as vertical point-jointed linksSource-demo long rope row with matched anchors, geometry, and metadata
avbd_demo2d_springThe avbd-demo2d Spring source scene as one radial rigid distance springSource-demo finite-stiffness spring row with matched anchors and metadata
avbd_demo2d_spring_ratioThe avbd-demo2d Spring Ratio source scene as alternating-stiffness radial springsSource-demo stiffness-ratio row with matched anchors, geometry, and metadata
avbd_demo2d_netThe avbd-demo2d Net source scene as endpoint-pinned links under falling rigid blocksSource-demo net row with matched anchors, geometry, and metadata
avbd_demo2d_fractureThe avbd-demo2d Fracture source scene as falling 2D boxes over weak fixed jointsSource-demo breakable fixed-joint row with public AVBD break thresholds
avbd_demo3d_groundThe avbd-demo3d Ground source scene as a falling rigid box over a static ground boxSource-demo rigid contact row with matched source geometry and metadata
avbd_demo3d_dynamic_frictionThe avbd-demo3d Dynamic Friction source scene as sliding rigid boxes over groundSource-demo rigid friction row with matched source geometry and metadata
avbd_demo3d_static_frictionThe avbd-demo3d Static Friction source scene as rigid boxes on an inclined rampSource-demo inclined-ramp friction row with matched source geometry/metadata
avbd_demo3d_pyramidThe avbd-demo3d Pyramid source scene as a triangular pile of rigid boxesSource-demo rigid stacking row with matched source geometry and metadata
avbd_demo3d_ropeThe avbd-demo3d Rope source scene as anchored rigid links with linear-only point jointsSource-demo rope row with matched anchors, geometry, and metadata
avbd_demo3d_heavy_ropeThe avbd-demo3d Heavy Rope source scene with a large endpoint blockSource-demo high-ratio rope row with matched anchors, geometry, and metadata
avbd_demo3d_stackThe avbd-demo3d Stack source scene as ten rigid boxes over a static ground boxSource-demo vertical stacking row with matched source geometry and metadata
avbd_demo3d_stack_ratioThe avbd-demo3d Stack Ratio source scene as a four-box geometric size towerSource-demo size-ratio stacking row with matched source geometry and metadata
avbd_demo3d_soft_bodyThe avbd-demo3d Soft Body source scene as three finite-stiffness box latticesSource-demo 3D soft-body row with finite all-axis joint stiffness and metadata
avbd_demo3d_bridgeThe avbd-demo3d Bridge source scene with paired point-jointed planks and load boxesSource-demo bridge row with matched anchors, geometry, and metadata
avbd_demo3d_breakableThe avbd-demo3d Breakable source scene as rigid boxes, contact shapes, and weak jointsSource-demo breakable fixed-joint row with public AVBD break thresholds
avbd_rigid_fixed_joint_contactA fixed rigid payload sliding against static contactPublic fixed-joint rows plus ordinary contact
avbd_rigid_revolute_motorA bounded revolute motor driving a free hingePublic velocity actuator mapped to AVBD motor rows
avbd_rigid_prismatic_motorA bounded prismatic motor driving a free rigid sliderPublic linear velocity actuator mapped to AVBD motor rows
avbd_articulated_revolute_motorA bounded revolute motor reversing an articulated floating linkPublic articulated velocity motor updates through the bridge
avbd_articulated_prismatic_motorA bounded prismatic motor reversing an articulated floating carriagePublic articulated linear motor updates through the bridge
avbd_articulated_motor_breakable_jointA weak articulated revolute motor releasing and re-engaging an articulated floating linkPublic articulated motor break/reset lifecycle through the bridge
avbd_articulated_prismatic_pair_motor_breakable_jointA weak same-multibody prismatic motor releasing and re-engaging an articulated carriagePublic articulated linear motor break/reset lifecycle through the bridge
avbd_articulated_prismatic_motor_breakable_jointA weak world-anchored prismatic motor releasing and re-engaging an articulated carriagePublic articulated linear motor break/reset lifecycle through the bridge
avbd_articulated_world_revolute_motor_breakable_jointA weak world-anchored revolute motor releasing and re-engaging an articulated floating linkPublic world-anchored articulated motor break/reset lifecycle through the bridge
avbd_articulated_high_ratio_chainA five-link variational chain swinging with a 200:1 heavy tipNarrow articulated high mass-ratio smoke for the AVBD paper gap
avbd_paper_scale_high_ratio_chainA 50-link variational chain swinging with a 50,000:1 heavy tipPaper-scale articulated high mass-ratio visual smoke for the AVBD paper gap
avbd_rigid_breakable_jointA weak fixed joint releasing and re-engaging a rigid payloadPublic break-force threshold, reset, and broken-state path
avbd_rigid_spherical_breakable_jointA weak spherical point joint releasing and re-engaging only a rigid payload anchorPublic free-rigid spherical break/reset while orientation stays free
avbd_articulated_breakable_jointA world-anchored floating link released and reset through a public articulated fixed jointPublic articulated world-link break/reset path through the variational bridge
avbd_articulated_fixed_pair_breakable_jointA same-multibody fixed joint releasing and restoring a captured relative posePublic articulated link-link fixed break/reset through the variational bridge
avbd_articulated_spherical_breakable_jointA world-anchored floating socket that releases and resets only its anchorPublic articulated spherical break/reset with orientation left free
avbd_articulated_spherical_pair_breakable_jointA same-multibody floating socket that releases and resets only its anchorPublic 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 idShowsIPC capability exercised
ipc_deformable_netA pinned spring net sagging/swaying under gravityProjected-Newton elastodynamics
ipc_deformable_drapeA mat draping over a step onto a ground barrierGround + self-contact clamped-log barrier
ipc_deformable_trampolineA corner-pinned membrane sagging and reboundingTaut-membrane projected-Newton dynamics
ipc_deformable_friction_slideA launched mat skidding to rest on a frictional floorLagged smoothed-Coulomb ground friction
ipc_deformable_fem_barA tetrahedral cantilever sagging under gravityStable neo-Hookean FEM elasticity
ipc_deformable_fem_twistA tetrahedral bar twisted at both ends, then releasedFEM volumetric shear (toward Fig 4/14)
ipc_deformable_fem_dropA FEM cube dropped onto a ground barrier, settlingFEM volumetric body + IPC contact
ipc_deformable_fem_sphereA FEM slab draping over a sphere obstacleFEM + sphere obstacle barrier (Newton)
ipc_deformable_fem_boxA FEM slab draping over a box "table" obstacleFEM + box obstacle barrier (Newton)
ipc_deformable_fem_mshA FEM cantilever loaded from a GMSH .msh tet meshFEM body from an imported tet mesh
ipc_deformable_scripted_dirichletA banner billowing under a scripted Dirichlet BCScripted 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

  1. Create scenes/<name>.py defining a module-level SCENE of type PythonDemoScene whose build() returns a SceneSetup (a world plus an optional custom pre_step, step(n), force_drag, scene panels, and info dict). A scene that wants capture manifests to include scene-owned physics evidence may put a zero-argument metrics callable in info["capture_metrics"].
  2. Import it in registry.py and append it to the ordered list in make_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.