Skip to content

48c: L5 hardpoint, camber and toe output; rack_per_rad key (0.8.2) - #38

Open
Onlyti wants to merge 6 commits into
mainfrom
feat/l5-hardpoint-output
Open

Onlyti wants to merge 6 commits into
mainfrom
feat/l5-hardpoint-output

Conversation

@Onlyti

@Onlyti Onlyti commented Nov 7, 2026

Copy link
Copy Markdown
Owner

L5 per-wheel camber, toe and hardpoint-coordinate output on the strut path with a corner model, and one VehicleParams.rack_per_rad key in place of the two rack-per-radian constants (work order 48c, 0.8.2). Dynamics unchanged: without the new key and without reading the new outputs every level is bit-identical to 645780c.

What changes

  • SimOutput: wheel_camber, wheel_toe [rad] (equal to free_3d_wheel_camber/toe, product toe of theory 14 §14.16), wheel_kin_valid, hardpoints (per wheel, count points [m]). L1-L4 and wheels without a corner model: 0, valid false, no points.
  • Frame (PO verdict D1 + origin verdict, option 1): vehicle design frame, x forward, y left, z up, origin on the ground below the front-axle centre. Rear part YAML shifted by axle_offset_x = -wheelbase - w_rear.x; right wheels are the left part mirrored in y. wheel_center_dy = w.y - track/2 is recorded, coordinates are not moved in y.
  • free_3d_hardpoint_layout() (names, axle_offset_x, wheel_center_dy, excluded), free_3d_wheel_kin_valid(), free_3d_wheel_hardpoints(), free_3d_rack_dy(); all exposed to Python.
  • VehicleParams.rack_per_rad (default 0.08 m/rad), used by L4 and L5 roadwheel mode; YAML / Python / to_yaml round trip, invalid values raise.
  • Python: vdsim.attach_l5_hardpoints(...); vdsim_lab.attach_kinematics delegates to it on L5. The L3/L4 attach keeps returning False on L5.
  • .vdtrace schema stays 0.5: opt-in wheel_camber, wheel_toe (4,) and hp_<wheel>_<key> (3,) channels (regex ^hp_(fl|fr|rl|rr)_[a-z0-9_]+$), manifest hardpoints block; an invalid wheel is NaN.
  • Five-link corner (PO K4 verdict, option 1): points not exported (count 0, layout names empty, excluded reason; manifest points: {} + excluded). Camber and toe are still reported (they are the values the tyre uses).

Gates (48c sec. 4, fixed in 5ec3702 before the implementation)

ID Result (local, HEAD 4b47562)
K1 bit identity vs 645780c 24/24 serialized runs identical (L1-L4, L3/L4 with native kinematics, L5 penalty / strut / three corner-model pairs; generic_sedan and fs_aero_example). RL pedal and accel obs+reward digests identical. Closed-loop deterministic arrays identical (only wall-clock t_compute_s / compute_* differ)
K2 camber/toe = free functions every tick pass, both pairs
K3 static coordinates, attach and after reset() pass, 1e-9 m
K4 link lengths, bump +-30 mm x rack +-22.5 mm MacPherson, trailing arm, double wishbone pass (prescribed sweep and every session tick); five-link: see below
K5 mirror pass
K6 rack_per_rad 0.08 given = absent bit-identical (L4, L5); 0.04 gives exactly half the rack
K7 negative per-tick hardpoint refresh removed -> K4 session test fails; restored -> passes
K8 Python = C++ bit-identical, L5 attach l5_hardpoints ctest passes
K9 RL preset throughput, A/B 5 rounds alternating, cores 0-9,12-21 median change within the 3 % line, no opt-out switch needed. L5 corner-model single session cost recorded as information

C++ and Python counted separately: C++ 16 new tests (unit 4, integration 12), Python 1 new ctest.

Changed after measurement

  • Five-link (PO verdict on the K4 halt, option 1; line unchanged): the five-link driven pose is a least-squares fit with 7 residuals for 6 unknowns, so its links do not hold their lengths to the K4 line. Implementation commit 51cad6d stops exporting its points; test commit c895d4f judges K4 on the three other topologies, asserts the exclusion (FiveLinkCornerExportsNoPoints, Python manifest check) and keeps the five-link sweep runnable as L5HardpointKnownFailure.K4FiveLinkPrescribedSweep (label known_failure, excluded from the validation preset). 5ec3702 is untouched.
  • K5 on the session output skips an axle that exports no points; the prescribed K5 on the five-link corner model still runs.

Documentation impact (W1)

CHANGELOG [0.8.2] (Added, Known limitations: L4 no output, five-link exclusion, wheel_center_dy), docs/theory/14_hardpoint_kinematics.md §14.17 (frame, point lists, rack_per_rad, trace channels and manifest), docs/EXPERIMENT_API.md trace channel note, docs/VALIDATION.md currency PENDING. Doc audit: FAIL set on HEAD equals 645780c (pre-existing A1 only).

Shared files with work order 47

free_3d_dynamics.cpp, params.*, bindings.cpp: whichever lands second merges main (no rebase).

Local verification

ctest --preset validation --parallel 4: all passed (main 595 + 17 new). ctest -L known_failure: the two R2 items and the five-link K4 item, as labelled.

CI measurement

PENDING: same-head complete successes x3, currency confirmation, final run and wheels. No merge, tag or publication performed.

🤖 Generated with Claude Code

Onlyti and others added 6 commits November 7, 2026 22:18
…ation

Gate code for work order 48c, committed ahead of the implementation:
camber/toe output equal to the free functions every tick, product-toe sign,
static coordinates against the part YAML plus the per-axle x offset at attach
and after reset, rigid link lengths over a bump x rack sweep, left/right mirror,
rack_per_rad default/half/round trip, L4 and non-hardpoint paths exporting
nothing, and the Python attach, bit-equality and trace checks.

This commit does not build on its own; the next commits add the API it uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SimOutput carries per-wheel camber, toe, validity and hardpoint coordinates in
the vehicle design frame on the L5 strut path; the two rack-per-radian constants
become VehicleParams.rack_per_rad; Python reads the new fields and attaches L5
hardpoints through vdsim.attach_l5_hardpoints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The five-link driven pose is a least-squares fit, so its link lengths are not
held exactly. The corner model reports an exclusion reason; the L5 session then
exports no points for that axle and the layout and trace manifest record why.
Camber and toe are still reported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Changed after measurement on the PO verdict for the 48c K4 halt (option 1):
thresholds unchanged, five-link exclusion asserted in C++ and Python, the
five-link link-length sweep kept runnable under the known_failure label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant