FAQ & troubleshooting
Install
Section titled “Install”Segfault when constructing gtsam.Pose3
Section titled “Segfault when constructing gtsam.Pose3”GTSAM 4.2 from pip is built against the NumPy 1.x ABI. With NumPy 2 you get a crash, not an exception:
pip install "numpy<2"aprilgrid or ArUco not found
Section titled “aprilgrid or ArUco not found”Detector backends are optional extras:
pip install -e ".[apriltag]" # AprilGridpip install -e ".[aruco]" # ArUcoCannot read a ROS bag
Section titled “Cannot read a ROS bag”pip install rosbagsPure Python — you do not need ROS installed.
Something else
Section titled “Something else”bash scripts/setup_env.sh builds the cam_calib environment and runs the test
suite, which separates an install problem from a data problem.
Running
Section titled “Running”Few or no detections
Section titled “Few or no detections”Check tag_family, rows, cols, and tag_spacing against the board you
actually printed — rows/cols are inner corners for a chessboard but tag
counts for an AprilGrid. Multi-scale detection handles far and near boards; it
cannot fix a wrong family.
Quality gating is dropping my frames
Section titled “Quality gating is dropping my frames”By design: pooled-pose filter (≥20% of tags across cameras), per-corner ≥5 views, per-camera ≥3 views, minimum 6 tags per frame. If most frames are dropped the recording is too sparse — get closer, or move more slowly.
Stage 1 initialisation fails
Section titled “Stage 1 initialisation fails”The sanity check caught a degenerate init. Common on wide fisheye with the wrong
model — try equidistant. max_init_frames caps how many frames the OpenCV
init uses.
It is slow
Section titled “It is slow”corner_subsample: top_left is already the default (3–5× faster). Also:
factor_hz to subsample frames, --parallel on the regression runner, and
cache_dir, which makes re-runs skip detection entirely.
A wide-FoV stereo fit diverged
Section titled “A wide-FoV stereo fit diverged”Known: double_sphere and eucm stereo fits can slide into an fx–xi / alpha
basin on TUM-VI while single-camera fits stay stable. Fit each camera alone,
then pin those intrinsics for the joint solve — the recipe is in
examples/configs/tumvi_cam_imu/. See Camera model.
Results that look wrong
Section titled “Results that look wrong”Reprojection error is low but the extrinsics look off
Section titled “Reprojection error is low but the extrinsics look off”A low residual means the solution explains its own observations. A parameter the
motion never constrained settles near its initial value without raising the
error. Read the motion-excitation grade in the HTML report, and for
camera–IMU run camcalib roundtrip.
Round-trip FAILs
Section titled “Round-trip FAILs”That is a real finding. Usual causes: wrong camera model, wrong IMU convention,
an interpolated accelerometer corrupting td (try gyro_only or
estimate_t_ga), or insufficient excitation. See
Round-trip validation.
td or the lever arm look wrong on a dynamic rig
Section titled “td or the lever arm look wrong on a dynamic rig”Check state_hz. It defaults to 30 Hz; below that, reprojection, lever, and
td alias on dynamic-motion rigs. Gentle sequences are insensitive to it.
The T265’s time offset is unstable
Section titled “The T265’s time offset is unstable”Its Bosch BMI055 publishes a 62.5 Hz accelerometer interpolated to 200 Hz, which
injects a gyro-accel timing offset. Either set gyro_only: true on that IMU or
turn on solve.estimate_t_ga. See IMU model.
IMU intrinsics come back at their initial values
Section titled “IMU intrinsics come back at their initial values”They were not observed. Scale and misalignment need excitation on every axis;
Tg needs simultaneous rotation and strong linear acceleration. See
Degeneracy.
Results differ from Kalibr’s
Section titled “Results differ from Kalibr’s”Check the IMU convention first — kalibr, rpng, and calyx produce different
matrices for the same device — then sensor numbering, then transform direction.
camcalib.io.kalibr reads Kalibr camchains directly, which is the reliable way
to compare.
Every translation is off by the same factor
Section titled “Every translation is off by the same factor”tag_size does not match the printed board. Measure a tag with calipers.
Results differ between sequences of the same rig
Section titled “Results differ between sequences of the same rig”Those parameters were not constrained by the motion in them. Run a batch sweep — spread across sequences is the most honest accuracy signal available without ground truth.
Still stuck
Section titled “Still stuck”Open an issue on the repository with your config, the console output, and what the rig is.