TrackSim (Tracking-Scenario Simulation)
Tracking-scenario simulator and replay visualizer over a shared JSONL stream contract. Generate labeled truth, degrade it into observables across fidelity tiers, replay it through a reference estimator, and scrub the result on a timeline. Requires Python 3.12+.
gri-tracksim is two paired tools joined by one file contract: a simulator
that emits truth / input / output streams, and a Dash/Plotly replay
viewer that reads them. The boundary is the JSONL contract alone, so the viewer
renders the output of any contract-conformant tracker, not just this package's.
The viewer is a 2D replay tool. The 3D analyst app ("Crucible") is a separate, closed product and is not part of this repository.
Key Features
- Scenario simulator: leg-based truth (straight / turn / climb / hold), degraded observables (geo / TDOA / FDOA / AOA / altitude), and a four-tier fidelity ladder (T0..T3) driven from one physical scene.
- Declarative scenarios: author scenarios in YAML from the shipped vocabulary - no source checkout required.
- Reference replay: a single-target IMM replay produces the
outputstream with forward-prediction horizons. - Replay viewer: a 2D top-down ENU map plus linked time-series panes, with a play/scrub timeline.
- Self-contained contract: a language-agnostic JSONL wire format you can emit from your own tracker and render here.
Capability Tiers
gri-tracksim is built around three ways to use it:
- Viz-only consumer - you already have a tracker. Emit the JSONL contract
and run
gri-tracksim-vizto scrub it. - Scenario author - write scenario YAML from the shipped vocabulary
(emitters, legs, tiers, collector presets, noise) and generate the
truth/input/outputtriple. Needs the package; no source. - Vocabulary developer - add new leg primitives, collector geometries,
fidelity tiers, or parametric sweeps. These live in registries in the source
and require a checkout (see
CLAUDE.md).
Installation
pip install gri-tracksim # simulator + replay viewer
Quick Start
Generate a scenario (CLI)
gri-tracksim --list # list bundled example scenarios
gri-tracksim air_racetrack # render a bundled scenario
gri-tracksim air_racetrack --tier T3 # same scene, harder tier
gri-tracksim air_racetrack --seed 7 # same scene, new realization
gri-tracksim my_scenario.yaml # render your own YAML
The scene name (air_racetrack) describes the physical scenario; --tier
(T0-T3) and --seed are orthogonal run knobs layered over it. Each defaults
to the scene's own value (a --seed-less scene with no seed: draws a random
one), and the effective tier and seed are folded into the output directory so
sweeps never clobber: streams land in
_scratch/<name>_<tier>_s<seed>/. The output root defaults to _scratch/ (a
gitignored scratch dir); override it with -o <dir>.
Scrub a run (viewer)
gri-tracksim-viz _scratch/air_racetrack_T2_s3
Author a scenario in Python
from gri_tracksim.sim import load_scenario, write_scenario_streams
scenario = load_scenario("my_scenario.yaml")
n_truth, n_input, n_output = write_scenario_streams(
scenario, "_scratch/my_scenario", predict_horizons_s=(10.0, 30.0),
)
Read the contract from your own tracker
from gri_tracksim.contract import Header, load_stream, write_jsonl
header, records = load_stream("output.jsonl") # parsed Header + event records
You only need gri_tracksim.contract to emit or read the streams - it has no
dependency on the simulator or the viewer.
Scenario YAML
A scenario is a single declarative file. All keys but name, origin_lla,
dt, and emitters are optional:
name: air_racetrack
origin_lla: [38.0, -77.0, 0.0] # ENU anchor [lat_deg, lon_deg, alt_m]
dt: 2.0 # grid step (s)
seed: 3 # default realization (--seed overrides; random if omitted)
tier: T2 # default tier (--tier overrides): T0 | T1 | T2 | T3
collectors: diverse # good | weak | diverse | null
motion: air # level (cruise) | air (climb-aware IMM)
noise:
altitude_std_m: 200.0
emitters:
E1:
start_enu: [0.0, 0.0, 1000.0]
azimuth_deg: 90.0
speed_mps: 120.0
legs:
- {type: straight, duration_s: 30.0}
- {type: climb, duration_s: 20.0, climb_rate_mps: 10.0}
- {type: turn, delta_azimuth_deg: 180.0, radius_m: 2000.0}
The leg types (straight, turn, climb, hold), fidelity tiers
(T0..T3), collector presets (good, weak, diverse), and replay motion
banks (level, level_fx, air) are fixed vocabularies; adding to them is the
source-only developer path.
Reference Replay Options
The replay tracker has three orthogonal knobs (defaults are the validated configuration; legacy values remain available for comparison runs):
- Motion bank (
motion:in the YAML):level(cv / turn / static),air(adds a climb mode so altitude changes read as a mode),level_fx(adds a fixed +/- nominal-rate turn pair -- instant turn discrimination when the platform's maneuver-rate class is known; harmful off-nominal). - Segmentation (
segmentation=):mode_sequence(default) -- a retrospective MAP decode over the whole track, recomputed each scan, which also emits settled (fixed-lag smoothed) mode probabilities per scan; orlocked, the online residual-trigger segmenter. - Prediction (
prediction=):locked(default) -- predict under the current settled segment's model (settle-gated, speed-guarded);evolvedorblendfor comparison.
Evaluation Harness
Two console scripts score tracker configurations against truth, corpus-wide:
# render + score scenario x seed runs (metrics.json per run, summary.json per sweep)
gri-tracksim-eval --seeds 10 --tier T2 -o _scratch/eval_new
gri-tracksim-eval --seeds 10 --tier T2 --segmentation locked --prediction blend \
--model-selection mean_ll -o _scratch/eval_legacy # the legacy stack
# paired (scenario, seed) comparison: median delta, bootstrap CI, sign test
gri-tracksim-compare _scratch/eval_legacy _scratch/eval_new
gri-tracksim-compare _scratch/eval_legacy _scratch/eval_new --scenario boat_racetrack
Per-run metrics cover segmentation (count, boundary error, label accuracy), characterization (instant and settled mode agreement, lock latency, thrash), smoothing (RMS and straight-leg bow, with a truth-boundary oracle bound), and prediction (per-horizon RMS plus the phantom-curve ratio vs a CV extrapolation).
The Stream Contract
Each stream is JSON Lines: a self-describing header record followed by one record per event.
truth-{"t", "emitter_id", "pos_enu", "vel_enu", "leg_mode"}input-{"t", "id", "type", ...}wheretypeis one ofgeo | tdoa | fdoa | aoa | altitude; the stableid(obs_0000...) is what the output'sassociationreferences.output- the estimator replay, in two record kinds per scan:- per-track records
{"t", "track", "pos_enu", "cov_enu", "vel_enu", "existence", "mode_probabilities", "stationary_locked", "resolved", "predicted", ...}- the track estimate (position + velocity in the ENU frame), onepredictedentry per requested horizon, each naming themodelthat produced it. Mode-sequence replays also carrysettled_t/settled_mode_probabilities(the fixed-lag smoothed mode mix a few scans behind the playhead). - one
scenerecord per scan{"t", "scene", "count_distribution", "association", "events", "worlds"}. The per-observation dispositions live atassociation.dispositions- one entry per input observation{"obs_id", "verdict", "track", "prob", "variant", "repaired"}, whereverdictisassigned | birthed | clutter | healed(the outlier / unused observations are theclutterverdicts, and ahealedone was absorbed under the alternative reading named byvariant).associationalso holdsgates/marginals/hypotheses/variants(the per-reading marginal probabilities).worldscarries the MFA's surviving global hypotheses with weights (empty for the committal GNN).
- per-track records
smoothed(optional) - one retrospective snapshot per scan: the smoothed trajectory the tracker had settled on by that playhead, plussegments({model, t_start, t_end}) naming the motion model the smoother used per leg. Segments revise as data accrues, so scrubbing replays the boundary back-dating.
The wire format is plain JSON (no gri types on the wire), so any tracker, in any language, can emit a stream the viewer will render.
Dependencies
A top-tier package in the GRI FOSS ecosystem; a sibling consumer of the same
mid-tier libraries as gri-multitrack.
- gri-geosim (iterative locate), gri-kalman (reference IMM replay), gri-trajectory (legs), gri-obs, gri-pos, gri-ell, gri-utils
- gri-plot, dash, plotly (the replay viewer)
- numpy, scipy, pyyaml
Other Projects
Current list of other GRI FOSS Projects we are building and maintaining.
License
MIT License. See LICENSE for details.
Release files for gri-tracksim 0.3.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gri_tracksim-0.3.4.tar.gz | 191.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gri_tracksim-0.3.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 344.1 kB
Release files / gri_tracksim-0.3.4.tar.gz
| Download URL | gri_tracksim-0.3.4.tar.gz |
|---|---|
| Size | 191.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c4d29ed1155af56be2255b6dc06659feddcc426e92c5bbd866b84fe718e5d4af
|
|
BLAKE2b-256 checksum How to use checksums |
fbad1e76729f5009c318c6f2364e8a551e19ffbd381dc491ec744bbadad83a5f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / gri_tracksim-0.3.4-py3-none-any.whl
| Download URL | gri_tracksim-0.3.4-py3-none-any.whl |
|---|---|
| Size | 152.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c3e0e534b2691801a39ac28fa04e44289061353b117607a8099f0fe3268c5fc2
|
|
BLAKE2b-256 checksum How to use checksums |
5b6b44cac50e6a1603a55351bbfd0fb3aacce118c3a73bfe1099bb7ee85db4a9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|