Geometric Reinforcement Learning for Simultaneous Navigation and Mapping
Reference paper: Ellendula, Wang, Nguyen, Bajaj — arXiv:2601.00116v1 (Dec 2025)
GRL-SNAM is a framework for navigating a robot from a start position to a goal in an unknown 2D environment without a pre-built global map. Instead of constructing a full map and planning on it, the robot only senses a small local window around itself at each moment and makes navigation decisions based on that partial information. The key innovation is formulating this problem using Hamiltonian mechanics: the robot learns an energy landscape where valleys correspond to safe, efficient paths, and navigation reduces to following the energy gradient downhill.
The framework is evaluated on two tasks:
- Hyperelastic ring navigation — a deformable ring robot that can squeeze through gaps narrower than its resting diameter.
- Dungeon point-agent navigation — a point mass navigating indoor maze layouts.
The most important architectural concept to understand is stagewise decomposition. Rather than planning a single long path from start to goal, GRL-SNAM decomposes the journey into a chain of short hops through overlapping rectangular regions called stages.
A stage is an axis-aligned bounding box (AABB) — a rectangular region of the 2D workspace — with:
- A center — the geometric midpoint of the box
- A size — default
(W=2.6, H=2.0)meters (width along the path direction, height orthogonal) - An entry point — where the robot enters the stage (the previous stage's exit)
- An exit point — where the robot must reach to graduate to the next stage
- bounds —
(xmin, xmax, ymin, ymax)derived from center and size
The full navigation path looks like:
START → [Stage 0] → exit₀ → [Stage 1] → exit₁ → ... → [Stage N-1] → GOAL
Adjacent stages overlap by a configurable fraction (default 30% of width = 0.78m). The exit point of stage i lies within this overlap region, ensuring a smooth handoff. This overlap zone is sometimes referred to informally as the stageline — the frontier or boundary between consecutive stages where the robot transitions from one local planning context to the next.
Offline StageManager (used in training data generation and evaluation — spline_stagewise6.py):
- Computes the direction vector from start to goal
- Places stage centers uniformly along this line, spaced by
W × (1 - overlap_ratio) - For each consecutive stage pair, finds a collision-free exit point in the overlap region using Dijkstra on a KNN visibility graph
Online StageManager (src/utils/online_stage_manager.py):
- Builds stages reactively, one at a time, as the robot moves
- When the robot reaches the boundary of its current stage, it proposes a new box ahead in the direction of travel + goal
- Includes stuck detection and recovery: if progress stalls, it tries random relocations of the next-box center
Stage advancement triggers when either:
- The robot center is within a threshold of the current exit point (0.45m offline, 0.15m online)
- The robot has overshot the stage center in the goal direction
The term stageline is used informally to refer to the boundary between adjacent stages — specifically the edge of the overlap region where the robot transitions from one stage to the next. In the codebase, this manifests as the exit_point of each Stage object (which equals the entry_point of the next stage). There is no explicit Stageline class; the concept is encoded in:
stage_exit— the per-frame subgoal stored in training data checkpointsStageManager.advance_if_needed()— the logic that detects when the robot crosses the stageline- The overlap rectangle computed between adjacent stages in
_rect_overlap()
Conceptually, crossing a stageline means: the robot has completed its current local planning task and is ready to receive a new local goal (the next stage's exit point) and a new local obstacle context.
The paper's central insight: instead of learning a policy
Where:
-
$\beta \geq 0$ — goal attraction strength (how strongly the robot is pulled toward the current stage exit) -
$\alpha_j \geq 0$ — per-obstacle barrier weight (how strongly obstacle$j$ repels the robot) -
$\gamma \geq 0$ — damping coefficient (energy dissipation for stability) -
$b(d_j)$ — IPC (Incremental Potential Contact) barrier function, a log-barrier that activates when distance$d_j < \hat{d}$
The resulting force field is:
Navigation then becomes forward integration of these dynamics — no Bellman equation, no value function, no reward engineering.
The workspace is a 2D rectangular region. For the hyperelastic ring task:
- Default bounds:
$x \in [-0.5, 9.0]$ ,$y \in [-1.8, 1.8]$ - Start: e.g.
[0.0, 2.5], Goal: e.g.[9.0, -1.2]
All obstacles are circles defined by:
-
Center
$c_j \in \mathbb{R}^2$ — position in the 2D plane -
Radius
$r_j$ — geometric radius -
Weight
$w_j$ — scaling factor for the barrier potential (controls repulsion strength)
For planning (exit-point finding), obstacles are inflated by a tube radius (default 0.05m) to ensure clearance. For the surrogate dynamics, obstacles are further inflated by margin_factor × robot_radius (default 0.5 × robot radius).
Obstacles are generated procedurally via:
sample_obstacles_case1_tight()— creates a corridor with narrow gates, intruder obstacles, and Poisson-distributed cluttersample_obstacles_case2_harder()— sinusoidal corridor, more gates, clustered clutter, wall belts
The robot is a periodic cubic B-spline ring with:
-
nctrl = 20control points — defining the ring shape -
K = 240sample points — for force evaluation and collision checking - A uniform scale parameter
$s(t) > 0$ — the single deformation DOF (squeeze or expand) -
Translation
$o(t) \in \mathbb{R}^2$ and rotation$\theta(t)$
Reference shape: control points form a unit circle of radius rbase, transformed to world coordinates by
At each timestep, the robot observes obstacles within a local window
GRL-SNAM achieves ~10-11% mapping ratio while maintaining near-planner path quality.
GRL-SNAM/
├── train_coef_energy.py # Main training script
├── eval_coef_energy.py # Evaluation and visualization
├── surrogate_robust.py # Radius-aware surrogate dynamics
├── scripts/
│ ├── spline_stagewise6.py # Core planner: robot model, stage manager, force field
│ ├── stagewise_dataset.py # Dataset generation (environments + episodes)
│ ├── ring_dataset_maxmin.py # Dataset utilities
│ └── ...
├── experiments/
│ ├── e1.py ... e10.py # Experimental configurations
├── src/utils/
│ ├── dijkstra.py # Grid-based exit solvers (Dijkstra, BFS, exhaustive)
│ ├── online_stage_manager.py # Online reactive stage manager
│ └── tensorboard_logger_mixin.py
┌─────────────────────────────────┐
│ stagewise_dataset.py │
│ - Generate random environments │
│ - Run episodes with planner │
│ - Save .pt + .jsonl per episode│
└───────────────┬──────────────────┘
│
┌───────────────▼──────────────────┐
│ train_coef_energy.py │
│ ShortRollouts dataset │
│ - Random short windows from │
│ stagewise checkpoints │
│ - Horizon H ∈ [2,6] steps │
└───────────────┬──────────────────┘
│
┌───────────────▼──────────────────┐
│ CoefEnergyNet │
│ - Obstacle encoder (MLP) │
│ - Goal encoder (MLP) │
│ - Transformer fusion (2L, 4H) │
│ - α, β, γ prediction heads │
└───────────────┬──────────────────┘
│
┌───────────────▼──────────────────┐
│ surrogate_robust.py │
│ integrate_surrogate_v2 │
│ + multi_start_penalty │
│ → predicted (oT, vT, clearance) │
└───────────────┬──────────────────┘
│
Loss = w_traj·‖oT-o_tgt‖²
+ w_vel·‖vT-v_tgt‖²
+ w_friction·‖γ-γ₀‖²
+ w_multi·L_multi
| Class | File | Purpose |
|---|---|---|
CoefEnergyNet |
train_coef_energy.py |
Neural network predicting (α,β,γ) from obstacle/goal context |
ShortRollouts |
train_coef_energy.py |
Dataset: random short trajectory windows from stagewise episodes |
Trainer |
train_coef_energy.py |
Training loop: forward → integrate → loss → backprop |
HyperelasticRingSystem |
scripts/spline_stagewise6.py |
The deformable robot: B-spline ring with scale, rotation, translation |
StageManager |
scripts/spline_stagewise6.py |
Offline stage chain builder (pre-plans all stages at init) |
StageForceFieldTorch |
scripts/spline_stagewise6.py |
Per-stage force field: goal + radial + tangent + flow + boundary |
IPCBarrier |
scripts/spline_stagewise6.py |
IPC log-barrier energy and force computation |
StagewiseHyperelasticPlanner |
scripts/spline_stagewise6.py |
Top-level planner wrapping StageManager + RingSystem + ForceField |
StageManagerOnline |
src/utils/online_stage_manager.py |
Online reactive stage builder with stuck detection |
HistSecantController |
eval_coef_energy.py |
Online correction via rank-1 secant Jacobian estimation |
OnlineFinetuner |
eval_coef_energy.py |
Test-time fine-tuning of prediction heads |
- Generate obstacles: procedural placement of corridor walls, gates, intruders, and Poisson clutter
- Build planner: create
StagewiseHyperelasticPlannerwith the offlineStageManager - Run episode: step the planner for up to 2000 timesteps at dt=0.03
- Each step: compute forces (IPC barriers + stage field + bulk energy), integrate dynamics, check for stage advancement
- Log each frame to
stagewise_checkpoints.jsonlwith: robot state(o, v, θ, s), currentstage_exit,obstacles_effective(centers, radii, weights in the current stage window),d_hat
- Save: episode
.ptfile + manifest
-
Load dataset:
ShortRolloutsreads.jsonlcheckpoint files, builds an index of extractable short windows -
Sample batch: for each item, randomly pick an episode and time offset, extract a window of
$H \in [2,6]$ steps- Input features: per-obstacle
[cx, cy, r, w, dx_goal, dy_goal](6D) + goal[dg_x, dg_y, ‖dg‖, 1.0](4D) - Target:
(o_target, v_target)at the end of the window
- Input features: per-obstacle
-
Forward:
CoefEnergyNetpredicts(α[B,N], β[B], γ[B]) -
Integrate:
integrate_surrogate_v2runs the surrogate dynamics forward$H$ steps from(o0, v0)using the predicted coefficients -
Multi-start penalty:
multi_start_penaltysamples 20 perturbed starts near the nearest obstacle, runs short rollouts, penalizes any penetrations - Loss: weighted sum of position MSE, velocity MSE, friction matching, and multi-start penalty
- Backprop: gradient through the differentiable integrator, clip at 5.0, Adam update
- Load checkpoint: restore trained
CoefEnergyNet - Create environment: sample obstacles, build planner with
StageManager - Rollout loop (e.g. 800 steps):
planner.stage_slice()crops obstacles to current stage window- Build features, predict
(α, β, γ)with the trained network - Map α to world: scale obstacle weights (
W_j ← W_j × α_j) and/or inflate radii (R_j ← R_j + k·α_j) - Inject
β→ stage field goal weight,γ→ robot damping - Rebuild world obstacles, step planner forward
- Optionally apply
HistSecantControllerfor online correction (after 5 steps in a stage) - Optionally apply
OnlineFinetunerfor test-time head tuning - Detect stage transitions → reset correction controller
- Capture PNG frames
- Output: GIF/MP4 animation of the rollout
When deployed in a new environment, the frozen network may produce suboptimal coefficients. Two lightweight online mechanisms correct this without retraining:
HistSecantController: Observes a 3D signal
OnlineFinetuner: Freezes all network parameters except the prediction heads. Runs 1-2 Adam steps on a rollout + constraint loss (speed limits, clearance) with proximal regularization to the checkpoint weights.
The paper decomposes navigation into three policies operating at different timescales (Figure 9 of the paper):
| Policy | Controls | Timescale | What It Does |
|---|---|---|---|
|
Sensor |
Slow (once per stage) | Queries environment, establishes obstacle constraints |
|
|
Frame/Path |
Medium (within each stage) | Computes waypoints toward stage exit, controls translation | |
|
Shape |
Fast (every integration step) | Adapts robot morphology (scale |
This creates a temporal hierarchy: shape equilibrates within each frame update, frame settles before the sensor policy evolves. In the codebase:
- The sensor policy maps to stage transitions and obstacle context updates
- The frame policy maps to the
StageForceFieldTorchdriving translation - The shape policy maps to the bulk energy term in
HyperelasticRingSystemthat drives uniform scaling
| Parameter | Default | Description |
|---|---|---|
stage_size |
(2.6, 2.0) |
Width × Height of each stage box (meters) |
overlap |
0.30 |
Fraction of width shared by adjacent stages |
inflate |
0.05 |
Obstacle inflation for collision-free path planning |
d_hat |
0.5–1.0 |
IPC barrier activation distance |
dt |
0.03 |
Integration timestep |
radius |
0.30–0.50 |
Nominal robot ring radius |
nctrl |
20 |
B-spline control points on the ring |
K |
240 |
Sample points on the ring boundary |
epochs |
50 |
Training epochs |
bs |
128 |
Batch size |
lr |
1e-4 |
Learning rate |
w_traj |
1.0 |
Position matching loss weight |
w_vel |
1.0 |
Velocity matching loss weight |
w_friction |
0.1 |
Damping matching loss weight |
w_multi |
0.5 |
Multi-start robustness penalty weight |
margin_factor |
0.5 |
Obstacle radius inflation = margin_factor × robot_radius |
ms_count |
20 |
Number of perturbed starts for multi-start penalty |
mass |
1.0 |
Robot translational mass |
k_bulk |
1.5 |
Bulk modulus (area stiffness) for hyperelastic ring |
python -m scripts.stagewise_dataset \
--root ./nav_stagewise_hyperring \
--num-episodes 500 \
--case case1-tightpython -m train_coef_energy \
--root ./nav_stagewise_hyperring \
--epochs 50 --bs 128 --lr 1e-4 \
--w_friction 0.1 --w_multi 0.5 \
--outdir checkpoints/coef_energypython -m eval_coef_energy \
--ckpt checkpoints/coef_energy/best.pt \
--case case1-tight \
--steps 800 --fps 20 \
--alpha_mode weightAlpha modes for evaluation:
-
weight— map α to obstacle weights:$W_j \leftarrow W_j \times \alpha_j$ -
radius— map α to effective radii:$R_j \leftarrow R_j + k \cdot \alpha_j$ -
both— apply both mappings -
none— ablation mode (ignore α)
| Method | Type | Map Access | Description |
|---|---|---|---|
| Rigid A* | Global planner | Full | A* on inflated grid (rigid disc) |
| Deformable A* | Global planner | Full | Clearance-aware A* with deformation cost |
| Potential Fields (PF) | Local reactive | Stagewise | Attractive + repulsive potentials |
| Control Barrier Functions (CBF) | Local reactive | Stagewise | QP-based safety filter |
| Dynamic Window Approach (DWA) | Local reactive | Stagewise | Velocity sampling + scoring |
| PPO / SAC / TRPO | Deep RL | Full or stagewise | Standard RL with Kin/Dyn/Coef parameterizations |
All stagewise baselines share the same stage manager and local sensing window as GRL-SNAM.
| Method | SPL ↑ | Detour ↓ | Min. Clearance ↑ | Mapping % ↓ |
|---|---|---|---|---|
| PF | 0.77 | 1.42 | 0.18 | 10.3 |
| CBF | 0.96 | 1.04 | 0.32 | 11.2 |
| GRL-SNAM | 0.95 | 1.09 | 0.26 | 10.7 |
| Best RL (TRPO-Coef) | 0.57 | 1.44 | 0.004 | 15.3 |
GRL-SNAM matches CBF-level path efficiency with PF-level mapping budget — the best of both worlds.
The barrier uses piecewise log form (Equation 26 in the paper):
This produces smooth repulsion that increases as the robot approaches an obstacle surface, with a hard penalty for actual penetration.
The training dynamics use semi-implicit Euler (velocity updates first, position uses new velocity):
a = (F_barrier + F_goal - γ * v) / mass
v ← v + dt * a # velocity update first
o ← o + dt * v # position uses new velocityThis provides better energy conservation than explicit Euler and makes the full pipeline differentiable end-to-end through PyTorch autograd.
Per-obstacle features (6D): [cx, cy, r, w, dx_goal, dy_goal] where (dx_goal, dy_goal) is the vector from the obstacle center to the goal.
Goal features (4D): [dg_x, dg_y, ‖dg‖, 1.0] where (dg_x, dg_y) is the vector from robot to goal.
The constant 1.0 is a bias term.
The experiments/ directory contains scenario configs:
| File | Description |
|---|---|
e1.py |
Basic tight corridor navigation |
e3.py |
Multi-gap cluttered environments |
e5.py |
Out-of-distribution generalization |
e7.py |
Dense obstacle fields |
e10.py |
Full comparison suite (Table 1 results) |
Run via: python -m experiments.e1
| Term | Definition |
|---|---|
| Stage | Rectangular region (AABB) the robot navigates through; part of a chain from start to goal |
| Stage exit / stageline | The handoff point between adjacent stages in the overlap region |
| IPC | Incremental Potential Contact — log-barrier function for smooth collision avoidance |
| CoefEnergyNet | Neural network that predicts Hamiltonian coefficients (α, β, γ) from local context |
| Surrogate dynamics | Simplified rigid-point dynamics used for differentiable training |
| DfPO | Differential Policy Optimization — the paper's term for gradient-based Hamiltonian learning |
| Mapping ratio | Fraction of workspace area ever observed through local sensing windows |
| SPL | Success-weighted Path Length — path efficiency metric relative to a reference planner |
| Multi-start penalty | Robustness term: samples perturbed starts near obstacles and penalizes penetrations |
| Secant controller | Online adaptation mechanism using rank-1 Jacobian estimation from consecutive observations |
This guide was generated from the codebase and the reference paper (arXiv:2601.00116v1). For theoretical details, see Sections 3–4 of the paper. For experimental methodology, see Section 5.