# Common Helper — `WgsConverter` ## Purpose WGS84 ↔ local tangent-plane (ENU/NED) ↔ tile pixel-coordinate conversions. Required by every component that interacts with geographic positions — from C4's pose estimation, through C5's state graph, through C6's tile-bounding-box queries, through C8's per-FC encoding, through C10's bbox provisioning, through C12's operator UX. ## Used By - C4 — Pose Estimation. - C5 — State Estimator. - C6 — Tile Cache + Spatial Index (bbox queries). - C8 — FC Adapter (per-FC encoding of LatLonAlt → MAVLink/MSP2). - C10 — Pre-flight Cache Provisioning (bbox → tile-id list). - C12 — Operator Pre-flight Tooling (operator-entered bbox). ## Interface (sketch) ``` class WgsConverter: @staticmethod def latlonalt_to_ecef(p: LatLonAlt) -> Vector3 @staticmethod def ecef_to_latlonalt(p: Vector3) -> LatLonAlt @staticmethod def latlonalt_to_local_enu(origin: LatLonAlt, p: LatLonAlt) -> Vector3 @staticmethod def local_enu_to_latlonalt(origin: LatLonAlt, p_enu: Vector3) -> LatLonAlt @staticmethod def latlon_to_tile_xy(zoom: int, lat: float, lon: float) -> tuple[int, int] @staticmethod def tile_xy_to_latlon_bounds(zoom: int, x: int, y: int) -> BoundingBox ``` ## Implementation Notes - Stateless; pure functions. - Backed by `pyproj` for the geodesy primitives; tile_xy math uses the standard slippy-map convention (matches `satellite-provider`'s on-disk layout). - All conversions use WGS84 ellipsoid; no datum-shift complexity. ## Caveats - The static-only design satisfies the coderule.mdc constraint ("only use static methods for pure self-contained computations"). If a future deployment needs alternative datum support, switch to an instance-based factory then. - Tile-coordinate math is zoom-level-sensitive; callers MUST pass the right zoom level for the tile in question (typically zoomLevel from `TileMetadata`).