Skip to content

Testbed — Interactive Engine Feature Exerciser

API reference reflects testbed contract v1

The testbed feature is under active development. The REST endpoints and UI capabilities documented here reflect the testbed contract v1 authored alongside the v0.7.0 release. Implementation status may be ahead of or behind this document at any given commit.


Purpose

The testbed provides a browser-based UI for exercising real engine features through the pyjaguar Python bindings. Where the benchmark dashboard measures throughput, the testbed lets you interact with the engine in real time: start and pause scenarios, step frame by frame, inject faults, and observe entity state, events, and domain-specific behaviour.

The testbed tab in benchdash is hidden automatically when pyjaguar is unavailable, so there is no breakage for users who build without Python bindings.


Prerequisites

Build the engine with Python bindings enabled:

cmake -B build -DJAGUAR_BUILD_PYTHON=ON
cmake --build build -j$(nproc)

This produces pyjaguar.so (Linux / macOS) or pyjaguar.pyd (Windows) in the build output directory. The bindings must be on PYTHONPATH or in the same directory as run_bench.py.


Launch

python3 tools/benchdash/run_bench.py --serve

Navigate to http://127.0.0.1:8765/index.html and select the Testbed tab. If pyjaguar is not importable, the tab displays an installation notice instead.


Scenario Presets

Four scenario presets are available from the UI dropdown:

Preset Description
Multi-domain Air, land, and sea entities in a combined-arms exercise
Air patrol Flight of four aircraft flying a racetrack orbit
Orbit demo LEO satellite propagated with corrected SGP4
Custom User-configurable entity count, domain mix, and integrator

Playback Controls

Control Behaviour
Play Start the simulation clock
Pause Freeze the clock; state is preserved
Step Advance exactly one simulation tick
Time scale Multiplier applied to wall-clock dt (1×, 2×, 4×, 8×, 32×)

Live Entity Table

A sortable table shows every active entity updated each tick:

Column Description
ID Entity identifier
Name Entity name
Domain Air / Land / Sea / Space
Position (LLA) Latitude, longitude, altitude
Speed (m/s) Scalar velocity magnitude
Integrator Currently assigned integrator name
NaN flag Lit when NaN containment triggered

Clicking a row opens a detail panel with the full EntityState struct.

Charts

  • Trajectory — 2-D ground track (latitude vs longitude)
  • Altitude — altitude (m) vs simulation time
  • Speed — speed (m/s) vs simulation time

Charts update in real time and retain a configurable history window (default: 300 ticks).


Live Event Log

The event log streams all events dispatched by the engine during the current run. Each row shows:

Field Description
Tick Simulation tick number
Sim time Simulation clock value (s)
Type Event type (e.g., CollisionEnter, Stall, OrbitInsertion)
Source Entity ID that generated the event
Category Event category bitmask

The log is filterable by event type and entity ID. A maximum of 1000 entries are retained in the browser.


Feature Test Panels

Six feature-specific test panels are available from sub-tabs within the Testbed tab:

Atmosphere Profile

Plots the US Standard Atmosphere 1976 density, pressure, and temperature curves from 0 to 86 km. Verifies that the StandardAtmosphere model returns physically correct values at layer boundaries.

Integrator Comparison

Runs the same initial condition through two integrators (selectable: Euler, RK4, ABM4, DormandPrince, Symplectic) and plots position divergence over time. Useful for verifying that per-entity state isolation is working correctly — the two integrators must not share history.

DIS Encode / Decode Roundtrip

Encodes an EntityStatePDU with configurable position and velocity, decodes the bytes back, and displays:

  • Hex dump of the raw bytes
  • Field-by-field comparison of original vs decoded values
  • Pass / fail assertion for each field

NaN Containment Injection

Forces a NaN into a selected entity's velocity component on the next tick. The panel confirms that:

  1. The NaN is detected by PhysicsSystem.
  2. The entity is rolled back to its last valid state.
  3. A warn-once log message is emitted.
  4. The simulation continues without crashing.

REST API

All endpoints are served on the same port as the main dashboard (--port, default 8765).

GET endpoints

Endpoint Response Description
GET /api/testbed/capabilities JSON object Whether pyjaguar is available; supported feature flags
GET /api/testbed/state JSON object Current tick, sim time, all entity states
GET /api/testbed/history JSON array Position/speed history for all entities (last N ticks)
GET /api/testbed/events JSON array Event log since last poll
GET /api/testbed/atmosphere JSON array Atmosphere profile 0–86 km (200 sample points)

POST endpoints

Endpoint Body Description
POST /api/testbed/scenario {"preset": "air_patrol"} Load a scenario preset
POST /api/testbed/control {"action": "play"|"pause"|"step", "time_scale": 1.0} Playback control
POST /api/testbed/integrator_compare {"integrators": ["rk4", "euler"], "scenario": "orbit"\|"projectile", "steps": 500, "dt": 0.05} Run integrator comparison
POST /api/testbed/dis_roundtrip {"entity_id": 1} DIS encode/decode roundtrip
POST /api/testbed/nan_inject {"entity_id": 1, "steps": 5} Inject NaN into entity state

All POST endpoints return {"ok": true} on success or {"ok": false, "error": "..."} on failure.


Architecture Note

The testbed server runs in the same Python process as the benchdash pipeline. pyjaguar is imported lazily — if import fails, the /api/testbed/* endpoints return {"ok": false, "error": "pyjaguar not available"} and the front-end hides the tab.

The engine runs in a background thread managed by the testbed server; HTTP handlers and the engine tick loop communicate through a thread-safe queue. Engine state snapshots are copied under a lock before being serialised to JSON.