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.

BAM rigkpicharttablea dashboard: 6 views of 3 linked datasets

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.