Files
calibration/tools/run_rtk_imu_calibration.py
T

100 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""Run the independent RTK--IMU calibration against the project inventory."""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from imu_lidar.rtk_imu_replay import (
DEFAULT_RTK_FRAME_DEFINITION,
DEFAULT_RTK_REFERENCE_POINT,
load_inventory,
load_sessions,
run_calibration,
)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--inventory",
type=Path,
default=ROOT / "artifacts" / "rtk_imu_inventory_v1" / "rtk_session_inventory.csv",
)
parser.add_argument(
"--output-dir",
type=Path,
default=ROOT / "artifacts" / "rtk_imu_calibration_v1",
)
parser.add_argument("--session", action="append", help="session id to include; repeatable")
parser.add_argument("--batch", action="append", help="batch id to include; repeatable")
parser.add_argument("--rotation-only", action="store_true")
parser.add_argument("--no-loo", action="store_true")
parser.add_argument("--knot-step-s", type=float, default=2.0)
parser.add_argument("--per-batch", action="store_true")
parser.add_argument("--rtk-frame-definition", default=DEFAULT_RTK_FRAME_DEFINITION)
parser.add_argument("--rtk-reference-point", default=DEFAULT_RTK_REFERENCE_POINT)
args = parser.parse_args(argv)
entries = load_inventory(args.inventory)
if args.session:
selected = set(args.session)
entries = [entry for entry in entries if entry.session_id in selected]
if args.batch:
selected_batches = set(args.batch)
entries = [entry for entry in entries if entry.batch_id in selected_batches]
if not entries:
raise SystemExit("no inventory rows match the requested selection")
sessions = load_sessions(entries)
rotation, translation = run_calibration(
sessions,
args.output_dir,
rotation_only=args.rotation_only,
compute_loo=not args.no_loo,
knot_step_s=args.knot_step_s,
rtk_frame_definition=args.rtk_frame_definition,
rtk_reference_point=args.rtk_reference_point,
)
print(
json.dumps(
{
"output": str(args.output_dir.resolve()),
"sessions": [session.session_id for session in sessions],
"rotation_ok": rotation.ok,
"rotation_rpy_deg": rotation.rpy_deg.tolist(),
"rotation_rms_deg": rotation.residual_rms_deg,
"translation_ok": None if translation is None else translation.ok,
"translation_m": None if translation is None else translation.t_RTK_IMU_m.tolist(),
},
ensure_ascii=False,
indent=2,
)
)
if args.per_batch:
for batch in sorted({entry.batch_id for entry in entries}):
batch_entries = [entry for entry in entries if entry.batch_id == batch]
if len(batch_entries) < 2:
continue
run_calibration(
load_sessions(batch_entries),
args.output_dir / "per_batch" / batch,
rotation_only=args.rotation_only,
compute_loo=False,
knot_step_s=args.knot_step_s,
rtk_frame_definition=args.rtk_frame_definition,
rtk_reference_point=args.rtk_reference_point,
)
return 0
if __name__ == "__main__":
raise SystemExit(main())