Skip to content

docs: train navigation on real geometry (self-supervised) + scripts - #16

Merged
transfix merged 7 commits into
mainfrom
docs/training-navigation-on-geometry
Jul 26, 2026
Merged

docs: train navigation on real geometry (self-supervised) + scripts#16
transfix merged 7 commits into
mainfrom
docs/training-navigation-on-geometry

Conversation

@transfix

Copy link
Copy Markdown
Contributor

What

Documents the end-to-end process for teaching the GRL-SNAM navigation policy to drive a specific real-world scene (terrain + city mesh), and adds the two reproducible scripts the doc references.

The key point: no expert demonstrations and no pre-generated dataset are required. The navigation surrogate (integrate_surrogate_v2) is fully differentiable, so CoefEnergyNet trains itself directly on the scene by backpropagating a reach-goal + no-penetration + speed objective through the H-step rollout.

Contents

  • docs/training-navigation-on-geometry.md — the process: the two training modes (imitation vs self-supervised), why self-supervised for new geometry, the differentiable-surrogate pipeline, the scale-normalization (working-region) step, measured training time, and running the trained policy with online adaptation.
  • scripts/extract_obstacles.py — ingest a geometry bundle (terrain.json + buildings.glb) into an obstacle set + free-point pool (obstacles.npz). Needs pycvc_gl (rasterizes the city mesh); one-time and cached.
  • scripts/train_on_geometry.py — self-supervised training of CoefEnergyNet on the obstacle set → checkpoint. Needs only torch + numpy; runs headless on CPU or GPU.

Validation

Both scripts smoke-tested end-to-end on the real austin_south geometry (10,355 obstacles, ~185k free points); a full 5000-step self-supervised run reproduces the same setup and converges (goal loss ~100 → ~4). Measured ~270–310 ms/step on CPU (6 threads); ~22–26 min for 5000 steps.

Docs-and-scripts only; no changes to existing modules.

transfix added 7 commits July 26, 2026 05:25
Document the end-to-end path from a real geometry bundle (terrain + city
mesh) to a trained navigation policy, with no expert labels and no
pre-generated dataset: the differentiable surrogate lets CoefEnergyNet
train itself on the scene by backpropagating a reach-goal + no-penetration
+ speed objective through the rollout.

Add two reproducible scripts the doc references:
  - scripts/extract_obstacles.py  scene bundle -> obstacle set (needs pycvc_gl)
  - scripts/train_on_geometry.py   obstacle set -> checkpoint (torch only)

Covers the scale-normalization (working-region) step, measured training
time (~22-26 min/5000 steps CPU, ~10-20x faster on GPU), and running the
trained policy with online adaptation (HistSecantController).
…Austin demo

The initial self-supervised recipe collapsed to degenerate policies. Fixed,
each confirmed by probing the trained dynamics:
  - drop the speed cap (it forced gamma>>beta -> the agent crawls, cannot reach)
  - penalize COLLISION only, not proximity (streets need low positive clearance;
    a proximity penalty makes staying put beat moving)
  - keep the IPC barrier LOCAL (--d-hat-world 25m, not a 172m 'sea of repulsion')
  - finer obstacle circles (--block 2, ~7m) so streets stay navigable
  - anchor coefficients to the known-good regime (regularizer) for stability
  - reachable local goals (1.0-2.0 units within the horizon)

Add the honest SCOPE finding: the circular-obstacle surrogate navigates a dense
rectilinear city poorly regardless of coefficients (measured: hand-set good
coefficients reach 0-1/4 with heavy penetration). The paper's answer is
stagewise -- an A* occupancy route for the global path + the learned policy for
local reactive control. New example volrover_grl_snam_austin_learned.py does
exactly that on real Austin; the planner example remains the native
sparse-obstacle showcase.
The circular-obstacle surrogate cannot drive a dense rectilinear city (barriers
conflict, agent pushed through corners regardless of coefficients). Replace the
obstacle model with a signed distance field: the barrier repels along the true
wall normal, so the learned surrogate navigates streets/corners cleanly. On
Austin, stagewise + SDF reaches 3/4 with ~0 penetration and the learned surrogate
DRIVES every step (circles drove none).

  - sdf_nav.py: differentiable SDF surrogate (grid_sample), CoefMLP (biased to the
    known-good regime), and TWO field sources, configurable:
      * build_sdf   — grl-snam's own exact footprint EDT (2-D, default, no deps)
      * build_sdf_cvc — CVC's mesh-exact 3-D SDF via pycvc.sdf (SDF_V2), sliced to
        the ground plane; returns the 3-D volume too (the bridge to 3-D GRL-SNAM)
  - scripts/build_sdf.py (--source edt|cvc) + scripts/train_sdf.py
  - the Austin demo now drives with the SDF surrogate (genuinely navigating), with
    the A* route for global topology + a footprint guard
  - trains self-supervised through the differentiable rollout; ~90 ms/step CPU,
    near-optimal from step 0 thanks to the coefficient bias (GPU auto if present)

Fixes the honest limitation documented earlier: the learned policy now navigates
the real city, not just modulates a route.
The learned SDF policy finds its own way START->GOAL across real Austin purely
by reacting to the buildings (moving carrot toward the goal + SDF barrier), no
precomputed route. Validated headless: a 550-626 m end-to-end drive with 0
building penetration. Complements the stagewise demo (which uses an A* spine for
adversarial pairs); a pure potential field can stall in a local minimum, so the
START/GOAL are chosen navigable.
When end-to-end progress toward the goal stalls (a potential-field local
minimum), the carrot switches to following the wall tangentially (a bug-style
boundary follow) until the agent rounds the obstacle, then resumes seeking.
Measured on Austin: reach 1/6 -> 3/6 and penetration 1102 -> 365 vs the plain
carrot. Answers 'can the carrot get out of local minima' — yes, by sweeping it
along the wall rather than re-aiming at the trap.
scripts/capture_drive_video.py runs the end-to-end SDF navigator (with the
wall-follow escape) START->GOAL, then renders the ACTUAL 3-D scene (terrain
relief + glTF buildings + vehicle + beacon) from a chase camera OFFSCREEN via
VTK and ffmpegs it to mp4 — the real 3-D drive captured to video without a live
window (same geometry + renderer as cvcGL/VolRover3). This is how the demo video
was produced.
Add a section covering the build_sdf -> train_sdf prep and running the drive
demos (freedrive / stagewise / planner) inside volrover3 via the Jobs tab or
--run-job, with the GRL_SNAM_* env vars, plus the offscreen capture tool.
@transfix
transfix merged commit bdb9995 into main Jul 26, 2026
1 check passed
@transfix
transfix deleted the docs/training-navigation-on-geometry branch July 26, 2026 23:02
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