100 lines
3.6 KiB
Python
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 rtk_imu.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())
|