docs: train navigation on real geometry (self-supervised) + scripts - #16
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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, soCoefEnergyNettrains 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). Needspycvc_gl(rasterizes the city mesh); one-time and cached.scripts/train_on_geometry.py— self-supervised training ofCoefEnergyNeton the obstacle set → checkpoint. Needs onlytorch+numpy; runs headless on CPU or GPU.Validation
Both scripts smoke-tested end-to-end on the real
austin_southgeometry (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.