[
](LICENCE) 
Modern C++ utilities for camera calibration, geometric vision, and robot–sensor alignment.
Highlights
- Modular targets exported as
calib::models, calib::estimation_linear, calib::estimation_optim, calib::datasets, calib::pipeline, calib::reports, and calib::io
- Intrinsic & extrinsic planar calibration with covariance estimation
- Homography and planar pose estimation (DLT, RANSAC, non-linear refinement)
- Hand-eye calibration starting from DLT seeds and refined via bundle adjustment
- Configurable pipeline stages (intrinsics, stereo, hand-eye, bundle) driven entirely by JSON
- Line-scan / laser plane calibration pipeline components with optional RANSAC plane fitting
- JSON configuration I/O helpers for reproducible calibration sessions
Repository Layout
include/calib/ Public headers organised by module
src/math/ Header-only math helpers (camera matrices, optimisation options)
src/models/ Camera model concepts and distortion primitives
src/io/ JSON/serialization helpers and glue
src/estimation/linear/ Linear solvers (DLT, closed-form)
src/estimation/optim/ Ceres-based refinement stages
src/datasets/ Dataset adapters and JSON bindings
src/pipeline/ Pipeline orchestration components
src/reports/ Report builders and formatting utilities
apps/cli/ Command line front-ends (e.g. calib_cli)
apps/examples/ Tutorial executables and sample JSON schemas
tests/unit/ GoogleTest unit + integration suites
cmake/ Shared CMake modules and package config templates
Each module re-exports headers under include/calib/ and can be consumed individually. A compatibility alias calibration points at the umbrella calib::calib interface target so downstream projects using the previous static library continue to link.
Dependencies
Installing dependencies
Ubuntu (22.04+ / 24.04 recommended)
sudo apt-get update
sudo apt-get install -y \
build-essential cmake ninja-build \
libeigen3-dev libceres-dev nlohmann-json3-dev \
libgtest-dev libgmock-dev libboost-dev libcli11-dev \
clang clang-tidy cppcheck
macOS (Homebrew)
brew update
brew install cmake ninja eigen ceres-solver nlohmann-json \
googletest boost cli11 llvm cppcheck
# expose brew's LLVM toolchain (clang-tidy, etc.) for the current shell and future sessions
export PATH="$(brew --prefix llvm)/bin:$PATH"
echo 'export PATH="$(brew --prefix llvm)/bin:$PATH"' >> "$HOME/.zprofile"
# optional: point CMake at brewed packages when configuring
export CMAKE_PREFIX_PATH="$(brew --prefix googletest):$(brew --prefix cli11):$(brew --prefix ceres-solver)"
Building
CMake options:
| Option | Default | Purpose |
CALIB_BUILD_APPS | ON | Build CLI tools under apps/cli |
CALIB_BUILD_EXAMPLES | ON | Build tutorial executables in apps/examples |
CALIB_BUILD_TESTS | ON | Enable GoogleTest targets in tests/unit |
CALIB_ENABLE_COVERAGE | OFF | Enable GCov/LLVM coverage instrumentation |
CALIB_ENABLE_WERROR | OFF | Treat warnings as errors on supported toolchains |
Linux / macOS
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
Quick homography sanity check:
./build/apps/examples/calib_example_homography <<'EOF'
4
0 0 10 20
100 0 110 18
100 50 120 70
0 50 8 72
EOF
Windows (vcpkg toolchain)
git clone https://github.com/microsoft/vcpkg $env:USERPROFILE/vcpkg
& $env:USERPROFILE/vcpkg/bootstrap-vcpkg.bat
& $env:USERPROFILE/vcpkg/vcpkg.exe install ceres eigen3 nlohmann-json gtest cli11 --triplet x64-windows
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release `
-DCMAKE_TOOLCHAIN_FILE="$env:USERPROFILE/vcpkg/scripts/buildsystems/vcpkg.cmake"
cmake --build build --config Release -j2
Installing
cmake --install build --prefix /desired/prefix
The install exports calibTargets.cmake and a calibConfig.cmake package so downstream projects can simply call find_package(calib CONFIG REQUIRED) and link against the calib:: targets they need.
Testing
After configuring the project you can execute the full GoogleTest suite:
cmake --build build --target tests
ctest --test-dir build --output-on-failure -j$(nproc)
These tests exercise the numerical solvers as well as higher level plumbing such as the JSON dataset loader. The latter now verifies that metadata from each JSON source is preserved, recorded in the pipeline summary and accessible through CalibrationDataset::raw_json for downstream tooling.
Using the Library
Most workflows live in calib::estimation and calib::pipeline:
#include <calib/estimation/handeye.h>
OptimOptions opts;
camera_target_poses,
initial_guess,
opts);
if (result.success) {
std::cout << result.report << '
'
<< result.g_se3_c.matrix() << std::endl;
}
auto optimize_handeye(const std::vector< Eigen::Isometry3d > &base_se3_gripper, const std::vector< Eigen::Isometry3d > &camera_se3_target, const Eigen::Isometry3d &init_gripper_se3_ref, const OptimOptions &options={}) -> HandeyeResult
Refines the hand-eye calibration transformation using an optimization process.
CLI utility
calib_cli executes declarative calibration jobs from JSON descriptions:
./build/apps/cli/calib_cli --config configs/planar_intrinsics.json --task intrinsics --output result.json
Examples
Tutorial executables reside in apps/examples/. The planar intrinsics walkthrough expects a configuration JSON and detector output following the schema shipped alongside the example:
./build/apps/examples/calib_example_planar_intrinsics \
--config apps/examples/planar_intrinsics_config.json \
--features path/to/planar_detections.json \
--output planar_intrinsics_result.json
For multi-stage workflows the calib_example_pipeline executable wires intrinsics, stereo, and hand-eye stages together on top of the unified dataset loader:
./build/apps/examples/calib_example_pipeline \
--config apps/examples/planar_intrinsics_config.json \
--features cam0=path/to/cam0_dataset.json \
--features cam1=path/to/cam1_dataset.json
The example prints a JSON summary highlighting the outcome of each pipeline stage.
For workflows that supply both planar intrinsics data and stereo pairing metadata in a single JSON file, calib_example_intrinsic_extrinsic consumes the combined format described in `doc/pipeline_input.md` and writes the full artifact bundle to disk:
./build/apps/examples/calib_example_intrinsic_extrinsic \
--input apps/examples/intrinsic_extrinsic_input.json \
--output calibration_artifacts.json
The resulting report lists accepted views, linear initialisation, refined statistics, and persists the outputs under a calibrations array to support multi-camera expansion.
End-to-end hand-eye plus bundle adjustment calibration is demonstrated by calib_example_bundle, which ingests intrinsics, robot poses, and stage configuration from a single JSON file (see apps/examples/bundle_pipeline_input.json):
./build/apps/examples/calib_example_bundle \
--input apps/examples/bundle_pipeline_input.json \
--output bundle_artifacts.json --verbose
The example records the pipeline summary alongside detailed artefacts from the hand-eye and bundle stages, including initial guesses, refined poses, and covariances for downstream analysis.
PlanarIntrinsicCalibrationFacade now returns a strongly typed PlanarIntrinsicsReport, so you can inspect the structured data directly or round-trip through JSON when you need a serialised payload:
PlanarIntrinsicCalibrationFacade facade;
auto run = facade.calibrate(cfg, cam_cfg,
detections, features_path);
const auto& report = run.report;
nlohmann::json json = report;
auto restored = json.get<PlanarIntrinsicsReport>();
PlanarDetections detections
Quality Gates
- Static analysis – clang-tidy / cppcheck via CI (
make lint locally)
- Unit tests – GoogleTest suites (
ctest with CALIB_BUILD_TESTS=ON)
- Formatting – clang-format helpers (
make format)
- Coverage –
make coverage when CALIB_ENABLE_COVERAGE=ON
Documentation
Doxygen powers the API reference. Generate and serve docs with:
./generate_docs.sh # plain generation
./generate_docs.sh --open # open in a browser
./serve_docs.py --port 8080 # lightweight HTTP server
cmake --build build --target doc
The generated manual groups content by functional modules (calibration, distortion, optimisation, pipelines) and cross-links tutorial executables with the relevant headers.
License
Distributed under the MIT License. See [LICENCE](LICENCE) for details.
Contributing
Bug reports, feature proposals, and pull requests are welcome. Open an issue for larger changes so the design can be discussed before implementation starts.