VDSim v0.4 — stunt physics (jump → vertical loop)¶
Status: near-complete (updated 2026-06-09, branch feat/v0.4-slope-jump-m5). Core
stunt (jump + vertical loop + Ld5 + loop validation) shipped; M3 banked curve descoped
to v0.5, theory doc 20_ld5_stunt.md outstanding. See "Milestones" for the close-out
list. v0.3.0 remains drivetrain + LuGre only (V0.2_DRIVETRAIN.md, V0.2_TIRE_LUGRE.md).
Baseline at v0.4 entry¶
- v0.2 done: composable subsystems, scene GUI (
app.html), multi-vehicle runtime. - v0.3.0 done: engine inertia + torque-RPM, LuGre tire, ISO re-validation pass.
- L3 today: small-angle heave/roll/pitch about static equilibrium; no airborne.
- T23 Python jump spec exists (
docs/tasks/T23_jump_14dof/REPORT.md); not in C++/GUI.
v0.4 theme — 3D contact + Ld5 + loop MVP¶
One release adds ramp jump (airborne), curved/banked track, full 3D chassis
attitude (Ld5), and a single vertical loop scenario playable from GUI/batch/
vdsim_realtime. Road L2/L3 behaviour on flat ground stays the default; stunt modes
are opt-in (level=L5, stunt scenario YAML).
Workstreams (all v0.4.0)¶
| WS | Name | Delivers |
|---|---|---|
| WS-A | 3D contact foundation | T23 → C++; is_valid wired; world-z L3+; bump/droop |
| WS-B | Ground & track | ramp / banked curve / loop mesh; IContactProvider extensions |
| WS-C | Ld5 dynamics | 6-DOF body + wheels; quaternion; tire at arbitrary attitude |
| WS-D | Runtime & GUI | scenarios, /app stunt presets, STATE fields, telemetry |
| WS-E | Validation | T23 regression tests + loop sanity suite (separate from ISO) |
Internal build order (same tag v0.4.0)¶
WS-A (contact + jump) ──► WS-B (geometry) ──► WS-C (Ld5) ──► loop on Ld5
│ │
└──── GUI (WS-D) ────┴──► WS-E
WS-A — 3D contact foundation (jump)¶
Port T23 spec into C++ (fourteen_dof_dynamics.cpp + L2 coupling):
| Item | From | To |
|---|---|---|
| z state | perturbation about static eq | world z (sprung + unsprung) |
| gravity | g_z_effective ≈ 0 |
full -g on sprung/unsprung |
| tire vertical | linear | max(0, k·((z_road+r)−z_u)) → airborne Fz=0 |
| L2 contact | is_valid ignored |
off-ground → no Fx/Fy; no quasi-static Fz |
| springs | linear only | droop + bump (progressive, not hard clip) |
state.position.z |
unused | published in STATE / Python / FMI |
Exit: tests/stunt/test_jump_l3.cpp — five T23 sanity checks green.
WS-B — Ground & track geometry¶
| Provider | Use |
|---|---|
RampGround |
T23 half-cosine + lip + cliff (1D profile) |
CurvedGround |
arc / spline segment; per-wheel z + surface normal |
MeshGround |
triangle mesh raycast (loop surface) |
Scenarios under configs/scenarios/:
jump_ramp.yaml— straight jump (L3+ or Ld5)banked_oval.yaml— moderate banking (L3+ on curves)vertical_loop.yaml— loop primitive (Ld5 only)
Builder/GUI: stunt track panel — ramp height, loop radius R, entry speed hint
v_min ≈ √(5gR) (friction-free estimate).
WS-C — Ld5 (6-DOF chassis)¶
New dynamics level L5 / Ld5_Full3D (Ld4 stays hardpoint kinematics).
- State: position, quaternion, v, ω; wheel spin; suspension internals (reuse L3 or Ld4).
- Integration: RK4 with substeps; no small-angle linearization for body attitude.
- Tire: Pacejka/LuGre in wheel contact frame (works inverted at loop apex).
- Airborne: WS-A branch reused.
- Flat road: L2/L3 unchanged;
level=L5opt-in only.
Exit: jump regression passes on Ld5; energy conserved in ballistic phase (spot check).
WS-D — Runtime, GUI, batch¶
vdsim_realtime:--scenario=loads stunt YAML; loop + ramp worlds.- VDS1 STATE: full quaternion already partial — verify ω, no gimbal issues in clients.
gui/app.html: setup → Stunt preset (ramp / loop); L5 level selector; Fz + z telemetry.vdsim_batch/vdsim_lab:Experiment(level="L5")+ stunt scenario.- CARLA bridge (optional v0.4.0):
is_valid+ mesh height feed-through if low cost.
WS-E — Validation & positioning¶
| Suite | Scope |
|---|---|
| ctest 190 | unchanged on default L2/L3 flat (no stunt in default path) |
tests/stunt/* |
jump (T23), banked curve, loop minimum-speed pass/fail |
docs/VALIDATION.md |
new Stunt section — not ISO 4138; demo/education tier |
docs/theory/20_ld5_stunt.md |
Ld5 equations + loop entry speed |
Loop MVP acceptance (v0.4.0):
- With design entry speed → completes loop without rail (or with optional light guide rail behind a flag; default off for “physics loop”).
- Below
v_min→ fails to crest (rolls back or falls — no silent teleport). - Apex: inverted, all wheels
Fz > 0or documented flight-only apex (either documented). - No NaN / runaway energy over 3 laps.
Milestones (single release v0.4.0)¶
| # | Milestone | WS | Status (2026-06-09) |
|---|---|---|---|
| M1 | T23 C++ jump + contact wired | A | ✓ done (Stunt.JumpAirborneInterval, JumpLandingNoSink) |
| M2 | RampGround + ramp scene + GUI | A,B,D | ✓ done (RampGround, jump_ramp_demo.yaml, app.js render) |
| M3 | CurvedGround + banked scenario | B | → moved to v0.5 (banked curve groups with terrain) |
| M4 | Ld5 core + jump on Ld5 | C | ✓ done (Free3DDynamics, L5CoastOnFlatNoSink) |
| M5 | loop ground + vertical_loop scene |
B,C | ✓ done (LoopGround, vertical_loop_demo.yaml, FreeLoopCompletesLap) |
| M6 | Loop validation suite + theory doc | E | partial — validation tests ✓ (loop 4 + jump); theory 20_ld5_stunt.md not written |
Tag v0.4.0 when M1, M2, M4, M5, M6 are green. M3 (banked curve) is descoped to
v0.5 (see V0.5_TERRAIN_L5.md M5/M5b) — CurvedGround arc/spline
and a banked-oval scenario belong with the terrain/L5 work, not stunt presets.
Confirmed gaps at v0.4 close (2026-06-09 audit)¶
- theory
docs/theory/20_ld5_stunt.md(M6) — Ld5 EOM + loop entry speedv_min ≈ √(5gR). Documents already-shipped behaviour; write before the tag. - GUI stunt authoring preset panel (WS-D) — confirmed absent:
app.html/app.jsrender loaded stunt scenes (ramp/loop mesh, z/pitch/roll telemetry) but there is no setup panel to author a ramp/loop scene from the GUI. Descoped to v0.5 GUI work. - M3 banked curve (above) — to v0.5.
Explicit non-goals (v0.4.0)¶
- V2V collision, double loop, corkscrew (v0.5+ backlog).
- Production sign-off of loop loads (bump-stop model stays educative).
- Replacing default L3 for normal road sims.
- Full loop track editor (parametric R + entry only).
Dependencies¶
LuGre should land before M4 (landing grip). T23 port (M1) can start in parallel with v0.3.0 tail if interfaces are frozen.
Risks¶
| Risk | Mitigation |
|---|---|
| Ld5 destabilizes flat L3 | separate create_full_3d(); default level unchanged |
| Loop only works with rail | ship rail as debug flag; document physics loop as goal |
| ISO numbers move | stunt tests isolated; v0.3 already re-baselined drivetrain/tire |
| GUI scope creep | M2/M5 = presets only, not general track CAD |
Links¶
docs/tasks/T23_jump_14dof/REPORT.md— jump specification to portdocs/theory/06_ld3_fourteen_dof.md— current L3 vertical modeldocs/SUMMARY.md— T23/T24 stunt tier summaryV0.2_PLAN.md— v0.2 scope; v0.3 items listed there move to v0.3.0 only