Tracking-scenario simulator and replay visualizer over a shared JSONL stream contract
Project description
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
AGENTS.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 (estimate / association / predicted), association keyed back to the inputid. Mode-sequence replays also carrysettled_t/settled_mode_probabilities: the fixed-lag smoothed mode mix a few scans behind the playhead (the "settled" complement to the instantmode_probabilities); eachpredictedentry names themodelthat produced it.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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gri_tracksim-0.3.0.tar.gz.
File metadata
- Download URL: gri_tracksim-0.3.0.tar.gz
- Upload date:
- Size: 164.4 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27feea25fe755f6dc28bf3d14d6f6984b38e5628c26413cbf35da41fb54a9cb1
|
|
| MD5 |
6d1f10b2da9626257e035087ca0e1e4d
|
|
| BLAKE2b-256 |
a8b435472510288cb7e61212b09710d218cc58b707995b1bf99a95948ab553a4
|
File details
Details for the file gri_tracksim-0.3.0-py3-none-any.whl.
File metadata
- Download URL: gri_tracksim-0.3.0-py3-none-any.whl
- Upload date:
- Size: 135.7 kB
- Tags: Python 3
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6fdb39f02c193fc91507d8c81f5fa1010034ed6a662ba5d5a0169f9931eb330d
|
|
| MD5 |
90fa6c38eca137e217a51fe1168cdd13
|
|
| BLAKE2b-256 |
87c9653a420a156580bda7fa5378e0e7442224c0b5368eb70919411ac811f842
|