#!/usr/bin/env python3 """Recompute hand-eye calibration from an observations .npz file.""" import argparse from typing import List import cv2 import numpy as np def _method_from_name(name: str) -> int: name = name.upper() methods = { "TSAI": cv2.CALIB_HAND_EYE_TSAI, "PARK": cv2.CALIB_HAND_EYE_PARK, "HORAUD": cv2.CALIB_HAND_EYE_HORAUD, "ANDREFF": cv2.CALIB_HAND_EYE_ANDREFF, "DANIILIDIS": cv2.CALIB_HAND_EYE_DANIILIDIS, } return methods.get(name, cv2.CALIB_HAND_EYE_TSAI) def main() -> None: parser = argparse.ArgumentParser(description="Recompute hand-eye from observations npz.") parser.add_argument("observations", help="*_observations.npz path") parser.add_argument("--method", default="TSAI") args = parser.parse_args() data = np.load(args.observations, allow_pickle=True) R_gripper2base: List[np.ndarray] = list(data["R_gripper2base"]) t_gripper2base: List[np.ndarray] = list(data["t_gripper2base"]) R_target2cam: List[np.ndarray] = list(data["R_target2cam"]) t_target2cam: List[np.ndarray] = list(data["t_target2cam"]) method = _method_from_name(args.method) R_cam2gripper, t_cam2gripper = cv2.calibrateHandEye( R_gripper2base, t_gripper2base, R_target2cam, t_target2cam, method=method ) T_cam2gripper = np.eye(4) T_cam2gripper[:3, :3] = R_cam2gripper T_cam2gripper[:3, 3] = t_cam2gripper.reshape(3) base_targets = [] for i in range(len(R_gripper2base)): base_T_gripper = np.eye(4) base_T_gripper[:3, :3] = R_gripper2base[i] base_T_gripper[:3, 3] = np.array(t_gripper2base[i]).reshape(3) cam_T_target = np.eye(4) cam_T_target[:3, :3] = R_target2cam[i] cam_T_target[:3, 3] = np.array(t_target2cam[i]).reshape(3) base_T_target = base_T_gripper @ T_cam2gripper @ cam_T_target base_targets.append(base_T_target[:3, 3]) base_targets = np.array(base_targets) mean_target = base_targets.mean(axis=0) errors = np.linalg.norm(base_targets - mean_target[None, :], axis=1) print("T_cam2gripper:") print(T_cam2gripper) print(f"Mean translation error: {errors.mean()*1000:.2f} mm") print(f"Max translation error: {errors.max()*1000:.2f} mm") if __name__ == "__main__": main()