"""LiDAR keyframe selection.""" from __future__ import annotations from dataclasses import dataclass import numpy as np from .contracts import LidarFrame from .registration import register_lidar_pair @dataclass(frozen=True) class KeyframeSet: indices: tuple[int, ...] frames: tuple[LidarFrame, ...] def build_keyframes( frames: list[LidarFrame], *, min_translation_m: float = 0.3, min_rotation_deg: float = 3.0, min_registration_fitness: float = 0.5, max_frame_gap: int = 8, ) -> KeyframeSet: """Select keyframes with enough relative motion for hand-eye pairs.""" if not frames: return KeyframeSet((), ()) selected = [0] last = 0 for index in range(1, len(frames)): if index - last > max_frame_gap: selected.append(index) last = index continue result = register_lidar_pair(frames[index].points_xyz, frames[last].points_xyz) if not result.ok or result.fitness < min_registration_fitness: continue if result.translation_m >= min_translation_m or result.rotation_deg >= min_rotation_deg: selected.append(index) last = index if selected[-1] != len(frames) - 1 and len(frames) > 1: selected.append(len(frames) - 1) unique = tuple(dict.fromkeys(selected)) return KeyframeSet(indices=unique, frames=tuple(frames[i] for i in unique))