Calibration Walkthrough¶
The problem¶
Manufacturing tolerances and assembly errors give every physical robot systematic geometric errors — joint zero-offsets, link length/orientation deviations from CAD, tool-center-point misalignment — typically 5-10mm at the end-effector. That's enough to make precision tasks (contact-rich manipulation, vision-guided grasping, multi-robot coordination) unreliable.
Kinematic calibration corrects this using external measurements (motion capture, a tracked marker, a camera) of the end-effector at a set of known joint configurations.
The model¶
P_measured = forward_kinematics(q, θ_nominal + Δθ) + ε
q— measured joint configurations (document any use of commanded substitutes)θ_nominal— nominal kinematic parameters from the URDFΔθ— parameter corrections FIGAROH solves forP_measured— external sensor measurement of the end-effector (or another tracked frame) at eachqε— measurement noise
FIGAROH minimizes the residual between P_measured and the predicted pose
over Δθ using Levenberg-Marquardt, then reports which corrections are
well- vs. poorly-observed given your measurement set.
Running it¶
Every robot in figaroh-examples
provides a BaseCalibration subclass (e.g. TiagoCalibration) that
supplies the robot-specific frame/marker configuration; the shape is the
same for every robot:
from examples.tiago.utils.tiago_tools import TiagoCalibration
from figaroh.tools.robot import load_robot
robot = load_robot("path/to/robot.urdf", load_by_urdf=True)
calibrator = TiagoCalibration(robot, "config/tiago_unified_config.yaml")
calibrator.initialize()
result = calibrator.solve(plotting=False, html_report=True)
solve() always prints a terminal quality report (condition number,
per-DOF residual RMSE, outlier count). html_report=True additionally
writes a self-contained diagnostic page — see
Reporting & Verification.
From the command line, the TIAGo example wraps this in one script:
cd examples/tiago
python calibration.py # full pipeline: calibrate → plot → save → export → viser viz
python calibration.py --calibrate-only # just solve, skip URDF export
python calibration.py --update-model # export a corrected URDF from a saved result
What you configure¶
The calibration: section of your unified config
declares:
base_frame/tool_frame— the kinematic chain endpointsmarkers— which frame(s) are measured, and which of their 6 DOF are observable (measure: [x, y, z, roll, pitch, yaw]) — a wrist-mounted 6-DOF tracker measures all six; a hand-mounted marker seen by a fixed camera might only give 3-DOF positionnb_sample— number of configurations in your measurement set (more isn't always better — see Optimal Experiment Design for how to pick the best set instead of the largest)calibration_levelandestimation— which corrections exist (joint_offsetorfull_params) and which of them are estimated, and how (structuralby default;excitation,map,map_cv,cv_subset). With few postures this choice matters as much as the data: see Choosing what to estimate
Interpreting results¶
Compare nominal and calibrated prediction on unused configurations. Report translation and rotation components in explicit units; position-only or contact measurements cannot establish full pose accuracy. Analyze gauge, identifiable corrections and prior sensitivity before interpreting individual parameters.
Verification defaults are task checks, not guaranteed accuracy. Inspect which validation metrics were available, and reload any exported model to check FK against the selected calibrated stage. See Plan, Fit and Validate for acquisition, split design, residual interpretation and acceptance evidence.
Next steps¶
- Choosing what to estimate — pick and check the estimation method for your robot and postures.
- Identification Walkthrough — once kinematics are corrected, identify the dynamic parameters (mass, inertia, friction) for control and simulation.
- Reporting & Verification — turn this run into a shareable report and a CI-gateable pass/fail check.
- Examples Gallery — complete calibration scripts for UR10, TIAGo, and TALOS.