tune.friction) and gravity CoM (tune.gravity) for all 14 joints (both arms × 7) in one command. Also available from the diagnostics dashboard’s Tuning workbench (axol serve).
One bidirectional multi-velocity sweep per joint yields both fits — the half-difference of forward/backward torque gives the friction model (Fc, k, Fv), the average gives the gravity curve the CoM is fit to, with the friction offset Fo refit against the corrected model. Each arm runs distal → proximal (wrist_3 → … → shoulder_1) and every joint’s fit is saved before the next joint sweeps, so proximal sweeps see already-corrected distal links — the ordering tune.gravity asks the operator to keep by hand happens automatically here. Sweep safety and the gravity-load poses (base-collision caps, elbow raised for wrist_2, camera clearance, and axis-vertical joints posed so gravity actually loads them — see tune.gravity) match the individual tools.
Results are saved to ~/.almond/calibration.json (this machine uses them immediately) and uploaded to Supabase Storage keyed by the robot’s identity — the Axol hub adapter’s USB serial, which travels with the arms across compute-host swaps. The documents live in a public bucket (axol-calibrations/<hub_serial>.json), so fetching them needs no credentials at all — only uploading does.
The upload only happens when the write key is configured; without it the run calibrates locally and says so:
axol-calibrations and mark it public. No table or RLS policies are needed — write access comes from the service key.
The upload merges over what the cloud already stores, so a one-arm re-run never wipes the other arm’s data. An interrupted run keeps (and uploads) every joint that completed.
calibration.pull
Fetches a robot’s factory calibration from the public bucket into the local cache (~/.almond/factory_calibration.json) — no credentials needed. It also runs automatically at the end of can.setup, so a fresh machine picks up its robot’s calibration during first-time setup without any extra step. Run it manually to refresh:
AxolConfig then overlays the fetched values between the coded defaults and the local calibration file:
tune.friction --save, tune.pid --save, tune.gravity --save) still wins over the factory values, and the coded defaults remain the fallback for joints neither layer covers.