Skip to content

Quickstart

Write one YAML file, run one command, read the HTML report. This is the whole loop — everything else in these docs is a variation on it.

You need CamCalib installed (Installation) and a set of images of an AprilGrid board.

Save this as config.yaml, pointing source_path at your images:

config.yaml
board:
board_type: apriltag # or chessboard
rows: 6
cols: 6
tag_size: 0.088 # metres
tag_spacing: 0.3 # gap as a fraction of tag_size
tag_family: t36h11
cameras:
- camera_id: 0
source_type: images # or rosbag_topic, euroc, ros2bag
source_path: /path/to/images
distortion_model: radtan # or equidistant, double_sphere, eucm, fov
shutter_type: global # rolling enables readout calibration
optimizer:
max_iterations: 15
pixel_sigma: 1.0
huber_threshold: 1.345
output_file: calibration_result.yaml
Terminal window
camcalib calibrate --config config.yaml

The pipeline runs seven stages — detection, quality gating, per-camera init, per-camera refinement, alignment, joint optimisation, and an outlier-driven rerun. Progress prints as it goes.

Two YAML files are written, on purpose:

FileUse
*_calib.yamlThe calibration itself — deploy this
*_full.yamlAdds board poses, so a run can be replayed

Alongside them is a self-contained HTML report: intrinsics and distortion tables, extrinsics with a 3D plot, per-frame and per-tag reprojection error, corner heatmaps, motion-excitation grades, and detection statistics — all in one file you can send to someone.

Open it. The number to check first is not the reprojection error but the motion-excitation grade: a calibration can fit its observations tightly and still have parameters that the recording never constrained.

radtan is a safe default, not the best fit for every lens. For fisheye, start with equidistant:

config.yaml
distortion_model: equidistant

Six models are available, and they are not interchangeable — which to pick, and how to tell when one has diverged, is in Camera model.