ruvnet/RuView · error · RuntimeError
solvePnP failed for all corner-ordering combinations
Error message
solvePnP failed for all corner-ordering combinations
What it means
solve_two_board_extrinsics jointly solves the camera→room transform over the wall and floor checkerboards, enumerating corner-ordering (flip) combinations to break the single-board centrosymmetric ambiguity. If cv2.solvePnP fails for every combination, `best` stays None and RuntimeError is raised — indicating the inputs themselves are bad, not mere ordering ambiguity.
Source
Thrown at scripts/calibration_lib.py:268
room = np.concatenate([wall_room, floor_room], axis=0)
img = np.concatenate([wi, fi], axis=0)
ext = _solve_pnp(room, img, camera_matrix, dist_coeffs)
if ext is None:
continue
if best is None or ext["rmse_px"] < best[0]["rmse_px"]:
ext["wall_flipped"] = wall_flipped
ext["floor_flipped"] = floor_flipped
rvec, _ = cv2.Rodrigues(np.asarray(ext["rotation"]).T)
tvec = -np.asarray(ext["rotation"]).T @ np.asarray(ext["translation_m"])
ext["per_board"] = {
"wall": {"rmse_px": reprojection_rmse(
wall_room, wi, rvec, tvec, camera_matrix, dist_coeffs)},
"floor": {"rmse_px": reprojection_rmse(
floor_room, fi, rvec, tvec, camera_matrix, dist_coeffs)},
}
best = (ext,)
if best is None:
raise RuntimeError("solvePnP failed for all corner-ordering combinations")
return best[0]
def extrinsics_consistency(ext_a: dict, ext_b: dict) -> dict:
"""Angular + translational disagreement between two extrinsic solutions
(the two single-board solves). Large values mean a mis-entered board
placement or a bad corner detection.
"""
ra = np.asarray(ext_a["rotation"])
rb = np.asarray(ext_b["rotation"])
r_delta = ra.T @ rb
angle = float(np.degrees(np.arccos(np.clip((np.trace(r_delta) - 1.0) / 2.0, -1.0, 1.0))))
t_delta = float(
np.linalg.norm(np.asarray(ext_a["translation_m"]) - np.asarray(ext_b["translation_m"]))
)
return {"rotation_deg": angle, "translation_m": t_delta}
View on GitHub (pinned to 4685618388)
Solutions
- Recapture with the camera NOT moved between the wall and floor shots (ADR-152 requirement)
- Re-check each board's cols, rows, square_size and the entered wall/floor placement values
- Improve corner detection (focus, lighting, flat boards) and confirm findChessboardCorners succeeds on both images
- Run the two single-board solves and compare via extrinsics_consistency — large angle/translation flags a mis-entered placement
Defensive patterns
Strategy: validation
Validate before calling
ok_wall = len(wall_room) == len(wall_image) and len(wall_image) > 0
ok_floor = len(floor_room) == len(floor_image) and len(floor_image) > 0
if not (ok_wall and ok_floor):
raise SystemExit("corner detection failed on a board; recapture/re-detect first") Try / catch
try:
ext = solve_two_board_extrinsics(wall_room, wall_image, floor_room, floor_image, K, D)
except RuntimeError as e:
log.error("two-board solve failed: %s", e)
log.info("consistency: %r", extrinsics_consistency(wall_ext, floor_ext))
raise SystemExit(
"recapture wall/floor with a fixed camera and verify board placements"
) from e Prevention
- Mount the camera on a tripod; it must not move between wall and floor shots
- Confirm findChessboardCorners succeeds on both images before the joint solve
- Keep per-board cols/rows/square_size in one config to avoid swaps
When it happens
Trigger: The camera moved between the wall and floor captures; wrong wall/floor placement entries; per-board cols/rows/square_size mismatched; corner detection failing on one board; intrinsics from a different camera or resolution.
Common situations: Handheld capture breaking the fixed-camera requirement; wall and floor image arguments swapped; stale intrinsics after a lens or resolution change.
Related errors
- solvePnP failed
- Intrinsics file {path} missing key {key!r}
- Calibration already in progress
- {path}: expected {{'nodes': [...]}} or a top-level list
- {path}: each node needs 'id' and 'position_m' [x,y,z]
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/54031829f5a7408a.
Report an issue: GitHub.