Runtime utilities¶
Beyond generating tracks and gates, track_gen ships a family of
GPU-batched runtime utilities for the sim loop:
Out-of-bounds & obstacle collision — oriented boxes vs the drivable band (exact or SDF backends) and vs disc obstacles such as gate posts.
Boundary props — cone lines and wall pieces along the boundaries, for rendering-only instancing.
Checkpoints & progress — ordered course goals from gate sequences or subsampled track centerlines, with pass/lap events and reward-ready distances.
Track-frame localization — arc-length
sand signed lateral offsetnper env, plus centerline curvature and curvature-limited speed profiles.The Course facade — one object bundling generation, collision, and progress per mode.
Cones and walls placed by track_gen.props, the effect of spacing,
and track_gen.collision’s SDF field with boxes classified by the
exact backend.¶
Family conventions¶
Every utility follows the same contracts, so learning one teaches all:
Flat batched layouts — arrays are flat
[E * stride]Warp arrays, NaN-padded past each env’s real count.Preallocated in-place results — per-step methods return the SAME result object every call, overwritten in place; call
clone()for a snapshot.Eager, NaN-proof validation — shapes, dtypes, and devices are checked when you construct or bind, never in the hot path.
Input binding — latch a tool onto your sim’s stable pose buffers once (constructor kwargs or
bind/bind_inputs) and callupdate()/query()with no arguments thereafter.Undefined for invalid envs — gate on
validfrom the generator result, as everywhere in the library.
CUDA graphs¶
All utilities preallocate their state and results once (stable pointers) and
never allocate in the hot path. Per-step inputs can be BOUND once instead of
passed per call — ProgressTracker(cps, position=buf),
DiscChecker(..., position=..., orientation=..., half_extents=...), and
CollisionChecker.bind_inputs(...) — after which update()/query()
take no arguments and read the buffers in place. Under graph capture this is
the intended pattern: the sim writes its stable pose buffers, then replays
the captured update. (Per-call mode also works under capture, but the SAME
arrays must be passed at capture and every replay.)
Outside capture, every utility follows a per-call wp.synchronize() after
its kernel launch (blocking, but simple — the codebase idiom). To record
query()/update()/sample() into YOUR OWN CUDA graph — instead of
relying on the Course facade’s built-in capture — call
track_gen.set_capturing(True) before opening the capture region so those
per-call syncs are skipped, then restore it (set_capturing(False), or
the value you saved beforehand) once the capture region is closed.
After regenerating¶
What needs refreshing after regenerating when wiring tools by hand is listed below.
Course refreshes only its integrated checkpoint, progress, and collision helpers.
External TrackLocalizer and PropSampler instances remain caller-owned and
require manual reset or resampling.
Tool |
After a regeneration |
|---|---|
|
Nothing — reads the current |
|
Call |
|
Call |
|
Call |
|
Call |
|
Call |
|
Nothing — aliases the |
|
|