Examples › BAM rig › Trajectory tracking
Trajectory tracking
Target vs sim vs real error summaries on one page: real rack runs against two twins per motor, speed and trajectory kind; the 10-09 study of target vs sim per joint (its real slots were never run, and say so); and the traj_compare reports that hold the curves, linked rather than redrawn.
The .base file and its data
Every tab above is one entry of this file; the views read these rows. ⋯ in the toolbar copies the current view as YAML.
# Trajectory tracking: target vs sim vs real error summaries, per trajectory, speed and motor. The time series and
# their overlays stay in traj_compare's own reports (linked in the last panel, never re-rendered here).
# Data: source/build.py (real rack runs vs twins; the 10-09 sim study, whose real slots were not requested).
# Grammar: docs/peps/0004-dashboards.md.
data: rack.json
facets:
- motor
- model
- { property: speed, order: [slow, medium, fast] }
- kind
properties:
motor: { displayName: Motor }
model: { displayName: Compared with }
speed: { displayName: Speed }
kind: { displayName: Trajectory }
error: { displayName: RMS error }
floor_motor: { displayName: Motor floor }
rms_error: { displayName: RMS error }
max_error: { displayName: Max error }
domain: { displayName: Domain }
mode: { displayName: Control }
joint: { displayName: Joint }
title: { displayName: Report }
href: { displayName: Open }
datasets:
rack: rack.json
cells:
data: cells.json
label: The 10-09 sim study
facets: [domain, mode, joint]
reports: reports.json
layout:
panels:
- text: |
## How far each run lands from its target
**Real** rack runs compared with two twins (the identified one and the full one), per motor, speed and
trajectory kind; then the **10-09 study** of target vs sim for four joints, whose real slots were never run
("no rack board commissioned"): they show as "—" with that reason, not as zero. The curves themselves are in
traj_compare's reports (bottom), which this page links to rather than redraws.
w: 12
- { view: Median error by speed, w: 12, h: 3 }
- { view: Real vs twins per motor, w: 7, h: 5 }
- { view: Error against the floor, w: 5, h: 5 }
- { view: Target vs sim (10-09), w: 7, h: 5 }
- { view: Study cells, w: 5, h: 5 }
- { view: traj_compare reports, w: 12, h: 3 }
views:
- type: kpi
name: Median error by speed
groupBy: { property: speed }
groupOrder: [slow, medium, fast]
kpi:
value: { property: error, summary: Median }
- type: chart
name: Real vs twins per motor
select: motor
chart:
mark: bar
encoding:
x: { field: motor, title: null, sort: [CAN 14, CAN 15, CAN 1, CAN 4, CAN 11, CAN 12, CAN 13, CAN 21] }
y: { field: error, aggregate: median, scale: { type: log }, title: Median RMS error (mrad) }
color: { field: model, title: Compared with }
xOffset: { field: model }
- type: chart
name: Error against the floor
select: motor
chart:
mark: { type: point, size: 50 }
encoding:
x: { field: floor_motor, scale: { type: log }, title: Measurement floor of the motor (mrad) }
y: { field: error, scale: { type: log }, title: Run RMS error (mrad) }
color: { field: model, title: Compared with }
shape: { field: speed, title: Speed }
guides:
- { indexLine: { slope: 1, through: 1 }, label: "error = floor" }
hover: { title: run, fields: [motor, model, speed, kind, error, floor_motor] }
- type: chart
name: Target vs sim (10-09)
from: cells
chart:
mark: bar
encoding:
x: { field: joint, title: null }
y: { field: rms_error, title: RMS error vs target (mrad) }
color: { field: mode, title: Control }
xOffset: { field: mode }
column: { field: speed, sort: [slow, medium, fast], title: null }
hover: { title: situation, fields: [speed, joint, mode, rms_error, max_error, peak_torque] }
- type: table
name: Study cells
from: cells
order: [domain, speed, joint, mode, rms_error, max_error, final_error, peak_torque, status]
sort:
- { property: speed_order, direction: ASC }
- type: table
name: traj_compare reports
from: reports
order: [title, what, date, size_mb, path]
sort:
- { property: date, direction: DESC }
// rack.json: 134 rows, 88 KB; the first 3
{
"id": "trajectory-tracking-rack",
"properties": {
"can": {
"type": "number",
"width": 60
},
"error": {
"note": "RMS of (real - twin) joint angle for this run: measured, computed from the real recording.",
"type": "number",
"width": 120
},
"floor_motor": {
"note": "The motor's floor from the budget: measured for CAN 14, a sine cycle-to-cycle stand-in for the other seven.",
"type": "number",
"width": 120
},
"floor_speed_median": {
"note": "How far two identical real runs at this speed disagree (median). Only CAN 14 has repeated identical tapes; the others show the reason.",
"type": "number",
"width": 140
},
"kind": {
"display": "badge",
"note": "staircase, sine or tape.",
"type": "text",
"width": 90
},
"model": {
"display": "badge",
"note": "Which twin the real run is compared with: the full twin, or the earlier identified twin.",
"type": "text",
"width": 200
},
"motor": {
"type": "text",
"width": 80
},
"run": {
"note": "Run key: session_NN/runs/<run name>.",
"type": "text",
"width": 300
},
"speed": {
"note": "slow | medium | fast from the run name (tapes only).",
"type": "text",
"width": 80
},
"speed_order": {
"note": "0 slow, 1 medium, 2 fast.",
"type": "number",
"width": 70
}
},
"rows": [
{
"can": 1,
"error": {
"basis": "measured",
"source": "budget_can1.json:full_rms_per_run_mrad.session_16/runs/s02_can1_staircase",
"unit": "mrad",
"value": 2.1833
},
"floor_motor": {
"basis": "stand-in",
"note": "PROXY: sine cycle-to-cycle repeat (no repeated identical runs on this station)",
"source": "budget_can1.json:floor_rms_mrad",
"unit": "mrad",
"value": 0.4471
},
"floor_speed_median": {
"value": null,
"why": "not a speed-sweep tape (staircase or sine): no per-speed floor"
},
"id": "can1/session_16/runs/s02_can1_staircase/full",
"kind": "staircase",
"model": "real vs full twin",
"motor": "CAN 1",
"run": "session_16/runs/s02_can1_staircase",
"speed": null,
"speed_order": null
},
{
"can": 1,
"error": {
"basis": "measured",
"source": "budget_can1.json:reference_twins_rms_mrad.identified.per_run.session_16/runs/s02_can1_staircase",
"unit": "mrad",
"value": 4.0625
},
"floor_motor": {
"basis": "stand-in",
"note": "PROXY: sine cycle-to-cycle repeat (no repeated identical runs on this station)",
"source": "budget_can1.json:floor_rms_mrad",
"unit": "mrad",
"value": 0.4471
},
"floor_speed_median": {
"value": null,
"why": "not a speed-sweep tape (staircase or sine): no per-speed floor"
},
"id": "can1/session_16/runs/s02_can1_staircase/identified",
"kind": "staircase",
"model": "real vs identified twin",
"motor": "CAN 1",
"run": "session_16/runs/s02_can1_staircase",
"speed": null,
"speed_order": null
},
{
"can": 1,
"error": {
"basis": "measured",
"source": "budget_can1.json:full_rms_per_run_mrad.session_17/runs/s04_can1_sine",
"unit": "mrad",
"value": 2.3185
},
"floor_motor": {
"basis": "stand-in",
"note": "PROXY: sine cycle-to-cycle repeat (no repeated identical runs on this station)",
"source": "budget_can1.json:floor_rms_mrad",
"unit": "mrad",
"value": 0.4471
},
"floor_speed_median": {
"value": null,
"why": "not a speed-sweep tape (staircase or sine): no per-speed floor"
},
"id": "can1/session_17/runs/s04_can1_sine/full",
"kind": "sine",
"model": "real vs full twin",
"motor": "CAN 1",
"run": "session_17/runs/s04_can1_sine",
"speed": null,
"speed_order": null
}
],
"source": "/archive/datasets/bam_rig/rack_2026-10-23/analysis/budget_can*.json (full_rms_per_run_mrad, reference_twins_rms_mrad.identified.per_run, floor); real recordings of the rack, Oct 2026; read_on 2026-10-26",
"title": "Rack hardware: real runs vs twins, per run (real measurements)",
"titleProperty": "run"
}README.md
# Trajectory tracking
Target vs sim vs real error summaries on one page: real rack runs against two twins per motor, speed and trajectory
kind; the 10-09 study of target vs sim per joint (its real slots were never run, and say so); and the traj_compare
reports that hold the curves, linked rather than redrawn.
- **App:** BAM rig
- **Replaces:** the summary tables of traj_compare's reports (`traj_compare.write_comparison_report`, in bam_ws
`trajectory_generation/traj_compare`) and the per-run numbers inside `budget_can*.json`, for comparing across runs;
traj_compare stays the renderer of every time series (the trajectory-comparison skill: never a bespoke renderer).
- **Shows:** three unlinked datasets on one page (each with its own rail section, filtering only itself); KPI cards in
summary mode (median per speed); grouped bars (`xOffset`) whose click selects a motor; error against the
measurement floor on log-log axes with an `error = floor` guide; a target-vs-sim study faceted by speed, where the
24 real slots are "—" with "not requested", never 0; a table of the reports with their paths.
- **Data:** written by `source/build.py`, read-only: `rack.json` from `/archive/datasets/bam_rig/rack_2026-10-23/analysis/budget_can*.json`
(**real** runs vs the identified and full twins); `cells.json` from `~/bam_ws/reports/media/rack-tracking-2026-10-09/{metrics,manifest}.json`
(sim, a placeholder-gain run: the ff-only rows have zero peak torque, as in the source); `reports.json`, the six
traj_compare reports found on disk.
The original UI it replaces
the summary tables of traj_compare's reports (traj_compare.write_comparison_report, in bam_ws trajectory_generation/traj_compare) and the per-run numbers inside budget_can*.json, for comparing across runs; traj_compare stays the renderer of every time series (the trajectory-comparison skill: never a bespoke renderer).
What it shows
three unlinked datasets on one page (each with its own rail section, filtering only itself); KPI cards in summary mode (median per speed); grouped bars (xOffset) whose click selects a motor; error against the measurement floor on log-log axes with an error = floor guide; a target-vs-sim study faceted by speed, where the 24 real slots are "—" with "not requested", never 0; a table of the reports with their paths.
Data
written by source/build.py, read-only: rack.json from /archive/datasets/bam_rig/rack_2026-10-23/analysis/budget_can*.json (real runs vs the identified and full twins); cells.json from ~/bam_ws/reports/media/rack-tracking-2026-10-09/{metrics,manifest}.json (sim, a placeholder-gain run: the ff-only rows have zero peak torque, as in the source); reports.json, the six traj_compare reports found on disk.