The bug
arm101/hardware/profiles.py:JointCalibration persists per-joint encoder tick limits to disk. Its docstring says:
Raw STS3215 encoder tick limits for a single joint.
They are not raw. They are read straight from read_position, which returns reported ticks — (raw - Ofs) mod 4096, a view through the servo's current homing offset.
Why it matters right now, on our arm
elbow_flex has been re-zeroed (Ofs 85 -> 1073, PR #40/#41, hardware-confirmed). So any calibration profile captured before that re-zero is now wrong by ~1071 ticks for that joint — and nothing anywhere says so. The file loads clean, the numbers look plausible, and they name different physical angles than they did when they were written.
This is the same class of bug the arm limits spec exists to eliminate (#43), sitting in a second place with a longer fuse.
The fix
Persist raw ticks. Raw ticks are invariant under a re-zero — the offset changes, the encoder does not. That eliminates the failure mode rather than detecting it. arm101/hardware/ticks.py (landed in wave 0 of the #43 build) is the conversion boundary to route through.
An existing profile on disk cannot be migrated blind, because the offset it was captured under is not recorded. Two honest options, to be decided when the fix is built:
- Refuse a profile with no recorded calibration and require re-capture. Loud, safe.
- Add the offset to the persisted format going forward, and treat pre-format profiles as unknown-frame.
Silently reinterpreting old numbers as raw is not an option — the elbow's would be wrong by ~1071 ticks.
How it was found
Task t1 of the #43 build, while establishing the one-conversion-boundary rule. It is pinned as a known-outstanding site in _PERSISTED_TICK_SITES (tests/test_tick_frames.py), which has a discovery guard — a new tick table that is not classified fails the test — and a backlog that can shrink but never grow. So this cannot be forgotten, only fixed.
Related: #43, #35
The bug
arm101/hardware/profiles.py:JointCalibrationpersists per-joint encoder tick limits to disk. Its docstring says:They are not raw. They are read straight from
read_position, which returns reported ticks —(raw - Ofs) mod 4096, a view through the servo's current homing offset.Why it matters right now, on our arm
elbow_flexhas been re-zeroed (Ofs85 -> 1073, PR #40/#41, hardware-confirmed). So any calibration profile captured before that re-zero is now wrong by ~1071 ticks for that joint — and nothing anywhere says so. The file loads clean, the numbers look plausible, and they name different physical angles than they did when they were written.This is the same class of bug the
arm limitsspec exists to eliminate (#43), sitting in a second place with a longer fuse.The fix
Persist raw ticks. Raw ticks are invariant under a re-zero — the offset changes, the encoder does not. That eliminates the failure mode rather than detecting it.
arm101/hardware/ticks.py(landed in wave 0 of the #43 build) is the conversion boundary to route through.An existing profile on disk cannot be migrated blind, because the offset it was captured under is not recorded. Two honest options, to be decided when the fix is built:
Silently reinterpreting old numbers as raw is not an option — the elbow's would be wrong by ~1071 ticks.
How it was found
Task t1 of the #43 build, while establishing the one-conversion-boundary rule. It is pinned as a known-outstanding site in
_PERSISTED_TICK_SITES(tests/test_tick_frames.py), which has a discovery guard — a new tick table that is not classified fails the test — and a backlog that can shrink but never grow. So this cannot be forgotten, only fixed.Related: #43, #35