Class RoomCalibrationManager#

Nested Relationships#

Nested Types#

Class Documentation#

class RoomCalibrationManager#

Multi-camera extrinsic (“room”) calibration via a shared ChArUco board.

Companion to CalibrationManager, which only handles single-camera intrinsics. A camera must already have a valid intrinsic CalibrationData (set_camera_intrinsics()) before its views can contribute to a solve — cv::solvePnP() needs real, non-identity intrinsics to produce a meaningful board pose.

Requires MOSAIC_HAVE_OPENCV — is_available() returns false otherwise.

Workflow
RoomCalibrationManager mgr;
mgr.set_board({7, 5, 40.0, 30.0});
for (int i = 0; i < cameraCount; ++i) mgr.set_camera_intrinsics(i,
settings.cameras[i].calibration);

// Repeat, moving the board through overlapping pairs of camera views:
mgr.feed_shot(simultaneousFrames);

const auto result = mgr.solve(cameraCount, /*referenceCameraIndex=*/0);
if (mgr.is_resolved(2)) { auto rt = mgr.extrinsic_for(2); ... }

std::array<double,3> planePoint, planeNormal;
mgr.use_shot_as_plane(lastShotIndex, 0, planePoint, planeNormal);

Public Functions

RoomCalibrationManager()#
~RoomCalibrationManager()#
void set_board(const BoardSpec &spec)#

Call before the first feed_shot(). Changing the spec after capturing shots requires clear_shots() to discard incompatible data.

void set_camera_intrinsics(int cameraIndex, const CalibrationData &data)#

Registers a camera’s already-computed intrinsic calibration (from CalibrationManager). Must be called once per camera before that camera’s frames in feed_shot() can be used — a camera with !data.calibrated is skipped by feed_shot() with a warning.

QVector<CameraShotResult> feed_shot(const QVector<VideoFrame> &frames)#

Runs ChArUco detection + per-camera cv::solvePnP() on one simultaneous multi-camera shot. A camera missing from frames (the UI’s per-shot capture timed out waiting for it) or lacking prior intrinsics is simply absent from the accepted shot data, reported as found = false here. Returns one result per input frame, in order.

int shot_count() const#
void clear_shots()#
SolveResult solve(int cameraCount, int referenceCameraIndex)#

Resolves every camera’s extrinsicRt (pose relative to referenceCameraIndex, which always resolves to identity) by BFS over the shared-shot graph accumulated so far (room_frame::bfs_resolve()). Also computes each directly-observed camera’s own reprojection RMS (its solvePnP fit quality, independent of any BFS chain length).

bool is_resolved(int cameraIndex) const#
std::array<double, 16> extrinsic_for(int cameraIndex) const#
double reprojection_rms_for(int cameraIndex) const#
bool use_shot_as_plane(int shotIndex, int cameraIndex, std::array<double, 3> &outPoint, std::array<double, 3> &outNormal) const#

Uses the board’s own pose from a specific (shot, camera) pair — where the board was presumably lying flat on the target surface — as the room’s reference plane. Both the shot’s camera detection and that camera’s own extrinsic resolution (solve() already called) must exist. outNormal is the board’s printed-face normal (its local Z axis) in room coordinates. Returns false if no matching detection exists or the camera is unresolved.

Public Static Functions

static bool is_available()#
struct BoardSpec#

ChArUco board geometry.

Public Members

int cols = 7#

Number of squares, horizontally.

int rows = 5#

Number of squares, vertically.

double squareLengthMm = 40.0#

Physical side length of one square, in mm.

double markerLengthMm = 30.0#

Physical side length of one ArUco marker, in mm.

struct CameraShotResult#

Outcome of one camera’s board detection within a single shot.

Public Members

int cameraIndex = -1#
bool found = false#

true if enough ChArUco corners were found to solve a pose.

int cornerCount = 0#
struct SolveResult#

Outcome of a solve() call.

Public Members

std::vector<bool> resolved#

index = cameraIndex

std::vector<double> reprojectionRmsPx#

index = cameraIndex; -1 = never directly seen