Track API
Tracks are timestamp-indexed, multi-modal streams: robot poses, sensor readings, per-step state. Each entry carries a float timestamp and an arbitrary dict payload, and entries that share a timestamp on the same topic merge into one row.
Tracks vs. Metrics
Use a track when entries are timestamp-indexed and the schema may vary across topics (poses, cameras, lidar, RL transitions). Use a metric when you have step-indexed scalars for plotting (loss, accuracy). See /metrics.
Basic Usage
exp.tracks(topic) returns a TrackBuilder bound to a topic path (e.g. "robot/pose"). append(**fields, _ts=...) writes one entry.
Timestamps
_ts is required on every append call and must be numeric (cast to float internally). There is no auto-generated or inherited timestamp — omitting _ts raises ValueError. Pick a consistent clock per experiment (simulator time, wall clock, sensor timestamp).
Two append calls to the same topic at the same _ts merge: later fields overwrite earlier ones at the same keys. This lets you split a sample across calls without duplicating rows:
Different topics keep independent timestamp tables, so log multi-modal samples at the same _ts across topics to align them later.
Flexible Schema
The data dict is free-form per call — different fields per entry are allowed. The backend reconciles columns at read time.
Reading
read() returns the topic's entries (optionally filtered by timestamp range and projected to selected columns). Flush before reading in the same process.
Flushing
Appends are non-blocking and batched by the background uploader. See /buffering for batch size and flush interval configuration.
Aligning with Frames
To pair a track entry with an image, log the filename alongside the data and use a consistent zero-padded index. See /images.
In MDX prose, wrap path templates like {step} or {i:05d} in backticks so the renderer doesn't treat them as expressions.