Overview
Camera calibration finds where a fixed (external) camera sits relative to a robot’s base — thecamera_wrt_base transform that skills such as pick-and-place
read to turn what the camera sees into where the arm should move. It runs from
the grid CLI, drives the arm hand-guided, and records the result on the
robot’s camera automatically.
This calibrates fixed cameras only — a camera mounted on a tripod or rig
looking at the workspace, not one riding the end-effector. The arm moves the
target through the camera’s view; the camera stays put.
Step 1: Print the calibration target
The calibration uses a 12×9 radon checkerboard with 16.5 mm squares. Generate it with OpenCV’sgen_pattern.py:
- Scale is exact — print at 100% (no “fit to page”), then measure a printed square; it must be 16.5 mm. Printer scaling silently shrinks the board and biases every result.
- There is a white border of at least one square-width on all sides.
- The surface is non-reflective, with no creases or unevenness.
- The mount is rigid (a 3D-printed mount is ideal; tape works). The board and camera must never wiggle during a run.
Step 2: Run the calibration
Calibration is offered at the end ofrobot add, from the grid CLI:
- Run
robot addand complete the setup for your robot. - At the final step the wizard flags any camera that has not been calibrated.
Press
cto calibrate now (or enter to skip and finish). If more than one camera is uncalibrated, pick the one to calibrate.
Hand-guide the arm to a variety of poses and collect a sample at each. Hold
the arm still at the instant you press space, so the pose and the frame match.
15–20 well-distributed samples generally suffice; more is better.
Amber always means still needed, never a fault. Red is reserved for the two
things that need you to act: a consistency check that failed, and a sample
the run rejected or dropped.

The four meters
Each meter is a track: white ticks are the samples you captured, the blue dot is
the pose you are holding now, and the amber band is the range still missing. A
meter gets a green dot once its samples span enough range with no large gap in
the middle, so a cluster of similar poses leaves it an empty ring however many
samples you take.
Axes decides whether the solve is well-posed at all. It needs the wrist to
turn about genuinely different axes between samples; if every move is a
variation on the same twist, the solve has nothing to pin the remaining
direction down. To fill it, between samples change at least two of these
three, by roughly 30–45° each — and move the board to a different part of the
frame as you go:
- tilt the board forward/back,
- tilt it sideways,
- twist it in its own plane (rotate it about the camera’s viewing direction — this is the one most people skip).
The live estimate
Est. erroris the reprojection error your current samples produce, re-solved after every capture and shown in px and mm. It is reported, not graded — see Step 3. It is badged preliminary until there are enough samples for it to mean anything. PressingCre-solves from exactly these samples, so the number you watched is the number that gets saved.Consistencyshows two checks that compare the data against itself and need no camera pose, so they are meaningful within the first few samples. Rotation red means the arm’s end-effector orientation is reported in a different convention than assumed, or the board is not rigidly fixed to the gripper. Scale red means a wrong printed square size, wrong units, or wrong camera intrinsics. Neither improves with more samples — stop and fix the cause.Next stepnames the single most useful next action. Follow it and ignore everything else.
Samples the run rejects for you
There is no undo key: bad samples are removed automatically, and every removal is announced in the panel.- Arm was moving when you pressed space — hold still and re-capture.
- Corners were not crisp (blur, or a mis-ordered detection) — steady the board and re-capture.
- Inconsistent sample dropped, once 8 or more samples exist — one sample disagreed with all the others. Re-capture at that pose if you want it back.
If the target isn’t detected, confirm it is non-reflective and that the board is
12×9 squares. OpenCV sometimes counts interior corners (one fewer per side).
Step 3: Read the result
PressC to solve. The reprojection error is the one you were already
watching on the Est. error tile — the solve runs over exactly the samples you
kept. The window closes and the terminal prints the final line only: the camera
name and the error, in pixels and in millimetres.
error_px × distance ÷ focal length). It is how far, per sample, the arm’s
reported pose and the camera’s view of the board disagree out in the world,
which is the number your task actually cares about.
The tool does not judge it. There is no good/bad threshold and no advice to
re-run, because only you know what your application tolerates — a few
millimetres is fine for one task and not another. What does flag a real problem
is the Consistency pills and the samples the run rejects for you; both catch
a wrong pose convention, scale or intrinsics without depending on the solve at
all. The CLI records the calibration on the robot’s camera and pushes it to the
robot’s config. Skills that need the extrinsic then read it over Nexus — no
copying by hand.
C is refused, with a notice and you left collecting, only when there is no
solution at all yet — too few samples, or a solve that degenerated. That is the
absence of a result, not a judgement on one.