mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-22 09:06:37 +00:00
30 lines
1.5 KiB
Python
30 lines
1.5 KiB
Python
import math
|
|
from abc import ABC, abstractmethod
|
|
from f02_1_flight_lifecycle_manager import CameraParameters
|
|
|
|
class IGSDCalculator(ABC):
|
|
@abstractmethod
|
|
def compute_gsd(self, altitude: float, camera_params: CameraParameters) -> float: pass
|
|
@abstractmethod
|
|
def altitude_to_scale(self, altitude: float, focal_length: float) -> float: pass
|
|
@abstractmethod
|
|
def meters_per_pixel(self, lat: float, zoom: int) -> float: pass
|
|
@abstractmethod
|
|
def gsd_from_camera(self, altitude: float, focal_length: float, sensor_width: float, image_width: int) -> float: pass
|
|
|
|
class GSDCalculator(IGSDCalculator):
|
|
"""H02: Ground Sampling Distance computations for altitude and coordinate systems."""
|
|
def compute_gsd(self, altitude: float, camera_params: CameraParameters) -> float:
|
|
w = camera_params.resolution.get("width", 1920)
|
|
return self.gsd_from_camera(altitude, camera_params.focal_length_mm, camera_params.sensor_width_mm, w)
|
|
|
|
def altitude_to_scale(self, altitude: float, focal_length: float) -> float:
|
|
if focal_length <= 0: return 1.0
|
|
return altitude / focal_length
|
|
|
|
def meters_per_pixel(self, lat: float, zoom: int) -> float:
|
|
return 156543.03392 * math.cos(math.radians(lat)) / (2 ** zoom)
|
|
|
|
def gsd_from_camera(self, altitude: float, focal_length: float, sensor_width: float, image_width: int) -> float:
|
|
if focal_length <= 0 or image_width <= 0: return 0.0
|
|
return (altitude * sensor_width) / (focal_length * image_width) |