# Configuration Manager ## Interface Definition **Interface Name**: `IConfigurationManager` ### Interface Methods ```python class IConfigurationManager(ABC): @abstractmethod def load_config(self, config_path: str) -> SystemConfig: pass @abstractmethod def get_camera_params(self, camera_id: Optional[str] = None) -> CameraParameters: pass @abstractmethod def validate_config(self, config: SystemConfig) -> ValidationResult: pass @abstractmethod def get_flight_config(self, flight_id: str) -> FlightConfig: pass @abstractmethod def update_config(self, section: str, key: str, value: Any) -> bool: pass @abstractmethod def get_operational_altitude(self, flight_id: str) -> float: """Returns predefined operational altitude for the flight (NOT from EXIF).""" pass @abstractmethod def get_frame_spacing(self, flight_id: str) -> float: """Returns expected distance between consecutive frames in meters.""" pass @abstractmethod def save_flight_config(self, flight_id: str, config: FlightConfig) -> bool: """Persists flight-specific configuration.""" pass ``` ## Component Description ### Responsibilities - Load system configuration from files/environment - Provide camera parameters (focal length, sensor size, resolution) - Manage flight-specific configurations - Validate configuration integrity - Support configuration updates at runtime ### Scope - System-wide configuration - Camera parameter management - Operational area bounds - Model paths and settings - Database connections - API endpoints ## API Methods ### `load_config(config_path: str) -> SystemConfig` **Description**: Loads system configuration. **Called By**: System startup **Input**: `config_path: str` - Path to config file (YAML/JSON) **Output**: `SystemConfig` - Complete configuration **Test Cases**: 1. Load valid config → succeeds 2. Missing file → uses defaults 3. Invalid config → raises error --- ### `get_camera_params(camera_id: Optional[str] = None) -> CameraParameters` **Description**: Gets camera parameters. **Called By**: All processing components **Output**: ```python CameraParameters: focal_length: float sensor_width: float sensor_height: float resolution_width: int resolution_height: int principal_point: Tuple[float, float] distortion_coefficients: List[float] ``` **Test Cases**: 1. Get default camera → returns params 2. Get specific camera → returns params --- ### `validate_config(config: SystemConfig) -> ValidationResult` **Description**: Validates configuration. **Called By**: After load_config **Validation Rules**: - Camera parameters sensible - Paths exist - Operational area valid - Database connection string valid **Test Cases**: 1. Valid config → passes 2. Invalid focal length → fails --- ### `get_flight_config(flight_id: str) -> FlightConfig` **Description**: Gets flight-specific configuration. **Called By**: F02.1 Flight Lifecycle Manager **Output**: ```python FlightConfig: camera_params: CameraParameters altitude: float operational_area: OperationalArea ``` **Test Cases**: 1. Get flight config → returns params --- ### `update_config(section: str, key: str, value: Any) -> bool` **Description**: Updates config at runtime. **Called By**: Admin tools **Test Cases**: 1. Update value → succeeds 2. Invalid key → fails --- ### `get_operational_altitude(flight_id: str) -> float` **Description**: Returns predefined operational altitude for the flight in meters. This is the altitude provided during flight creation, NOT extracted from EXIF metadata (images don't have GPS/altitude metadata per problem constraints). **Called By**: - F10 Factor Graph Optimizer (for scale resolution) - H02 GSD Calculator (for GSD computation) - F09 Metric Refinement (for alignment) **Input**: `flight_id: str` **Output**: `float` - Altitude in meters (typically 100-500m) **Test Cases**: 1. Get existing flight altitude → returns value 2. Non-existent flight → raises error --- ### `get_frame_spacing(flight_id: str) -> float` **Description**: Returns expected distance between consecutive frames in meters. Used for scale estimation in visual odometry. **Called By**: - F10 Factor Graph Optimizer (for expected displacement calculation) **Input**: `flight_id: str` **Output**: `float` - Expected frame spacing in meters (typically ~100m) **Test Cases**: 1. Get frame spacing → returns expected distance --- ### `save_flight_config(flight_id: str, config: FlightConfig) -> bool` **Description**: Persists flight-specific configuration when a flight is created. **Called By**: - F02.1 Flight Lifecycle Manager (during flight creation) **Input**: ```python flight_id: str config: FlightConfig ``` **Output**: `bool` - True if saved successfully **Test Cases**: 1. Save valid config → succeeds 2. Invalid flight_id → fails ## Data Models ### SystemConfig ```python class SystemConfig(BaseModel): camera: CameraParameters operational_area: OperationalArea models: ModelPaths database: DatabaseConfig api: APIConfig ``` ### CameraParameters ```python class CameraParameters(BaseModel): focal_length: float # mm sensor_width: float # mm sensor_height: float # mm resolution_width: int resolution_height: int principal_point: Tuple[float, float] distortion_coefficients: List[float] ``` ### OperationalArea ```python class OperationalArea(BaseModel): name: str = "Eastern Ukraine" min_lat: float = 45.0 max_lat: float = 52.0 min_lon: float = 22.0 max_lon: float = 40.0 ``` ### RecoveryConfig ```python class RecoveryConfig(BaseModel): """Configuration for failure recovery and progressive search.""" search_grid_sizes: List[int] = [1, 4, 9, 16, 25] # Progressive tile search grid min_chunk_frames_for_matching: int = 5 # Minimum frames before chunk matching max_chunk_frames_for_matching: int = 20 # Maximum frames per chunk user_input_threshold_tiles: int = 25 # Request user input after this many tiles chunk_matching_interval_seconds: float = 5.0 # Background matching interval confidence_threshold_good: float = 0.7 # Confidence for good tracking confidence_threshold_degraded: float = 0.5 # Confidence for degraded tracking min_inlier_count_good: int = 50 # Inliers for good tracking min_inlier_count_tracking: int = 20 # Minimum inliers before tracking loss ``` ### RotationConfig ```python class RotationConfig(BaseModel): """Configuration for image rotation and heading tracking.""" rotation_step_degrees: float = 30.0 # Degrees per rotation step litesam_max_rotation_tolerance: float = 45.0 # Max rotation LiteSAM handles sharp_turn_threshold_degrees: float = 45.0 # Threshold for sharp turn detection heading_history_size: int = 10 # Number of headings to track confidence_threshold: float = 0.7 # For accepting rotation match @property def rotation_iterations(self) -> int: """Number of rotation steps (360 / step_degrees).""" return int(360 / self.rotation_step_degrees) ``` ## Dependencies ### Internal Components - **F03 Flight Database**: For flight-specific configuration persistence (save_flight_config stores to F03) ### External Dependencies - **pydantic**: Data model validation - **PyYAML**: Configuration file parsing