Skip to content

docs: the vehicle plant in port-Hamiltonian form, a whitepaper for GRL-SNAM - #137

Merged
transfix merged 2 commits into
mainfrom
docs/vehicle-ph-whitepaper
Oct 28, 2026
Merged

transfix merged 2 commits into
mainfrom
docs/vehicle-ph-whitepaper

Conversation

@transfix

Copy link
Copy Markdown
Contributor

Adds docs/vehicle-ph-plant.tex and its PDF (21 pages): a standalone whitepaper on the vehicle under GRL-SNAM's controller, the dynamic single-track plant, written as a port-Hamiltonian system. It is for researchers who want to check the theory and the implementation themselves.

What it covers

  • The pH form, exact at every slip:

    • the Lie-Poisson J(p) on se(2)*;
    • the tires' secant dissipation R, PSD even when a tire slides;
    • the axle forces as the port, with y = G^T v;
    • why steering is not a power port;
    • the speed floor's f_eps and grade, booked as power lines of their own;
    • tangent against secant.

    A proposition, with its proof.

  • The discrete step's energy books, whose residual is second order per step, and the live plant cvc::physics::dyn_bike_plant.

  • The learned plant cvc::ph:

    • RFF Matern GP levels and Cholesky SPD factors;
    • the Lie-IMEX step;
    • E[dH] including the noise power;
    • the rollout objective. The EKF-ELBO stage is pending.
  • The navigator: the per-step energy identity, its cheap bound and sharp check, and context and projection work at each tick.

  • External ports: how the form takes externally defined ports in general, with a navigation force as the worked example.

  • GRL-SNAM's side:

  • Future work: dyn_4w in pH form, and other limitations.

Validation

Each claim maps to a test, with its tolerance, the measured value and the commit that added it (Section 9). The measured values come from:

  • libcvc master c1f104c0 (nav/ph/physics identical to v3.7.1): nav_dyn_bike_test 21, ph_se2_test 14, ph_se2_train_test 8, nav_potential_test 16 and physics_dyn_bike_plant_test 3, all passed.
  • This repo at 0e21085: test_dyn_bike_parity.py, test_nav_potential_parity.py, test_dyn4_parity.py, test_dyn4_ext_rollout_parity.py and test_material_ext_parity.py, 53 passed. 2 skipped because the local pycvc lacks the material external-force channel.

The libcvc side is transfix/libcvc#831, #832 and #833, all released in 3.7.1.

Build

pdflatex vehicle-ph-plant.tex, three passes. The log has no warnings: no undefined references and no overfull or underfull boxes.

…L-SNAM

docs/vehicle-ph-plant.tex and its PDF (21 pages): the dynamic single-track
vehicle that GRL-SNAM's controller drives, written as a port-Hamiltonian
system on se(2)* at every tire slip, for researchers who want to check it.

- The pH form: H = 1/2 v^T M v, the Lie-Poisson J(p), the tires' secant
  dissipation R (PSD sliding or not), the axle forces as the port with
  y = G^T v, why steering is not a power port, the speed floor's f_eps and
  grade as booked power lines, and tangent against secant.
- The discrete step's per-step energy books (residual second order per
  step) and the live plant, cvc::physics::dyn_bike_plant.
- The learned plant cvc::ph: RFF Matern GP levels, Cholesky SPD factors,
  the Lie-IMEX step, E[dH] with the noise power, the rollout objective;
  the EKF-ELBO stage is pending.
- The navigator's per-step energy identity, its two checks, and context
  and projection work at each tick.
- GRL-SNAM's side: the torch twins and their parity tiers, what is not
  twinned yet, and how a rollout or trainer can use the plant and its books.
- A validation table: test, what it shows, tolerance, measured value and
  commit, measured on libcvc c1f104c0 (nav/ph/physics as in v3.7.1) and
  on GRL-SNAM 0e21085.

Built with pdflatex (three passes, no warnings).
@transfix
transfix merged commit 3a38ae4 into main Oct 28, 2026
4 checks passed
transfix added a commit that referenced this pull request Oct 28, 2026
…t slip in its wheel's frame (#138)

Two commits, for Joe to review before merging:
1. a torch twin of libcvc's single-track vehicle in port-Hamiltonian form, with its per-step energy books;
2. `dyn_bike`'s front slip moved into its wheel's frame, following libcvc.

They sit beside `dyn_plant` in `grl_snam/dyn_bike.py`. The whitepaper (#137, `docs/vehicle-ph-plant.tex` §8.2–8.3 and §10) lists the twin as missing.

**1. The pH twin** (held to libcvc's `DynBikePH.Golden`, transfix/libcvc#848). New in `grl_snam/dyn_bike.py`, mirroring libcvc's `dyn_ph_*` in `cvc/nav/detail/dyn_bike.h`:
- `dyn_ph_parts_at`: everything the form is built from at a state:
  - the axle forces (the port);
  - the tires' lateral forces and secant stiffnesses;
  - `u`, `sg`, `uf` and `Dx`;
  - the vectors `n_f`, `n_r`, `t_f`, `t_r`.
- `dyn_ph_rates_at`: the power balance dH/dt = supplied − dissipated + floor + grade.
- `dyn_ph_hamiltonian`: ½ vᵀMv.
- `dyn_plant_books`: `dyn_plant`'s step, unchanged, plus its books:
  - the trapezoid of the rates between the step's start (with the actuators' outputs δ₁, a₁) and the twist the step reached before its limiters;
  - `limiter`: dH across the speed clamp and the low-speed blend;
  - `residual`: the rest.
- `dyn_plant(..., with_free=True)` also returns the pre-limiter twist (libcvc's `dyn_step_free`).
- `dyn_plant`'s step 2 moves into `_axles`, which the parts share.

`tests/test_dyn_bike_ph_parity.py` checks the twin against `dyn_bike_ph_golden.json`, double tier, 1e-9 relative, on eight Humvee cases. Each case checks:
- the parts and the rates;
- one step's next state, pre-limiter twist and books;
- the autograd gradient of a weighting of the books against libcvc's forward-mode duals.

The file also tests that a batch books like its rows. A torch-only gate checks that the books close to second order on a swerve.

**2. The wheel-frame front slip** (follows transfix/libcvc#852, approved by Joe). The front slip becomes the wheel-frame slip `dyn4`'s tires use:
- alpha_f = −atan2(w_f, u_f);
- w_f = cos δ (vy + lf r) − sin δ vx, which is n_f·v;
- u_f is the floored forward speed in the wheel's frame;
- the secant is rooted at w_f = 0.

The implicit step's Jacobian takes the front tire's −S_f cos² δ (1, lf) on the body's y. In the pH twin, R's front term becomes S_f n_f n_fᵀ, and f_ε is round-off. Three fixtures are regenerated from libcvc#852:
- `dyn_bike_golden.json`;
- `dyn_bike_ph_golden.json`;
- `material_ext_golden.json`: only its dynamic case changes; the surrogate and bicycle cases are byte-identical.

**Measured** (torch 2.8, CPU, after both commits):
- Worst relative difference from libcvc:

  | Values | Worst relative difference |
  |---|---|
  | Plant next state | 0 |
  | Plant gradient | 2.8e-16 |
  | pH parts | 3.4e-16 |
  | pH rates | 3.4e-16 |
  | Books | 7.1e-14 |
  | Books gradient | 4.4e-14 |
- On the golden's cases, the floor power is at most 6e-13 W.
- On the swerve, the mean |residual| per step falls 3.94× and then 3.97× per halving of the step.
- `test_dyn_bike_parity`, `test_dyn_bike_ph_parity`, `test_material_ext_parity`, `test_dyn4_parity` and `test_material_bike_parity` give 57 passed and 6 skipped. The skips are live-pycvc checks that this machine's pycvc lacks.
- ruff and black are clean on the changed files.

pycvc has no dynamic binding, so none of this depends on a pycvc release.
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