#!/usr/bin/env python3 """Compare two homogeneous-extrinsic JSON files in parameter space and on SE(3).""" import argparse import json from pathlib import Path import numpy as np from scipy.spatial.transform import Rotation def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--reference", type=Path, required=True) parser.add_argument("--candidate", type=Path, required=True) parser.add_argument("--output", type=Path, required=True) args = parser.parse_args() reference = json.loads(args.reference.read_text(encoding="utf-8-sig")) candidate = json.loads(args.candidate.read_text(encoding="utf-8-sig")) a = np.asarray(reference["matrix_4x4"], dtype=float) b = np.asarray(candidate["matrix_4x4"], dtype=float) delta = np.linalg.inv(a) @ b result = { "convention": "delta = inverse(reference) @ candidate", "reference": str(args.reference.resolve()), "candidate": str(args.candidate.resolve()), "candidate_minus_reference_translation_xyz_m": (b[:3, 3] - a[:3, 3]).tolist(), "candidate_minus_reference_rpy_xyz_deg": ( np.asarray(candidate["rotation_rpy_deg_xyz"], float) - np.asarray(reference["rotation_rpy_deg_xyz"], float) ).tolist(), "relative_translation_norm_m": float(np.linalg.norm(delta[:3, 3])), "relative_rotation_deg": float(np.degrees(Rotation.from_matrix(delta[:3, :3]).magnitude())), "relative_matrix_4x4": delta.tolist(), } args.output.parent.mkdir(parents=True, exist_ok=True) args.output.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8") print(json.dumps(result, ensure_ascii=False, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())