{"record":{"id":"54031829f5a7408a","repo":"ruvnet/RuView","slug":"solvepnp-failed-for-all-corner-ordering-combinatio","errorCode":null,"errorMessage":"solvePnP failed for all corner-ordering combinations","messagePattern":"solvePnP failed for all corner-ordering combinations","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"scripts/calibration_lib.py","lineNumber":268,"sourceCode":"            room = np.concatenate([wall_room, floor_room], axis=0)\n            img = np.concatenate([wi, fi], axis=0)\n            ext = _solve_pnp(room, img, camera_matrix, dist_coeffs)\n            if ext is None:\n                continue\n            if best is None or ext[\"rmse_px\"] < best[0][\"rmse_px\"]:\n                ext[\"wall_flipped\"] = wall_flipped\n                ext[\"floor_flipped\"] = floor_flipped\n                rvec, _ = cv2.Rodrigues(np.asarray(ext[\"rotation\"]).T)\n                tvec = -np.asarray(ext[\"rotation\"]).T @ np.asarray(ext[\"translation_m\"])\n                ext[\"per_board\"] = {\n                    \"wall\": {\"rmse_px\": reprojection_rmse(\n                        wall_room, wi, rvec, tvec, camera_matrix, dist_coeffs)},\n                    \"floor\": {\"rmse_px\": reprojection_rmse(\n                        floor_room, fi, rvec, tvec, camera_matrix, dist_coeffs)},\n                }\n                best = (ext,)\n    if best is None:\n        raise RuntimeError(\"solvePnP failed for all corner-ordering combinations\")\n    return best[0]\n\n\ndef extrinsics_consistency(ext_a: dict, ext_b: dict) -> dict:\n    \"\"\"Angular + translational disagreement between two extrinsic solutions\n    (the two single-board solves). Large values mean a mis-entered board\n    placement or a bad corner detection.\n    \"\"\"\n    ra = np.asarray(ext_a[\"rotation\"])\n    rb = np.asarray(ext_b[\"rotation\"])\n    r_delta = ra.T @ rb\n    angle = float(np.degrees(np.arccos(np.clip((np.trace(r_delta) - 1.0) / 2.0, -1.0, 1.0))))\n    t_delta = float(\n        np.linalg.norm(np.asarray(ext_a[\"translation_m\"]) - np.asarray(ext_b[\"translation_m\"]))\n    )\n    return {\"rotation_deg\": angle, \"translation_m\": t_delta}\n\n","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/scripts/calibration_lib.py#L250-L286","documentation":"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.","triggerScenarios":"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.","commonSituations":"Handheld capture breaking the fixed-camera requirement; wall and floor image arguments swapped; stale intrinsics after a lens or resolution change.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"ok_wall = len(wall_room) == len(wall_image) and len(wall_image) > 0\nok_floor = len(floor_room) == len(floor_image) and len(floor_image) > 0\nif not (ok_wall and ok_floor):\n    raise SystemExit(\"corner detection failed on a board; recapture/re-detect first\")","typeGuard":null,"tryCatchPattern":"try:\n    ext = solve_two_board_extrinsics(wall_room, wall_image, floor_room, floor_image, K, D)\nexcept RuntimeError as e:\n    log.error(\"two-board solve failed: %s\", e)\n    log.info(\"consistency: %r\", extrinsics_consistency(wall_ext, floor_ext))\n    raise SystemExit(\n        \"recapture wall/floor with a fixed camera and verify board placements\"\n    ) from e","preventionTips":["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"],"tags":["opencv","calibration","pnp","geometry","computer-vision","capture-procedure"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}