/******************************************************************************* * 文件名称 : geo_utils.c * 文件说明 : LLA/ECEF/ENU 坐标转换辅助函数 * 创建日期 : 2025-11-22 *******************************************************************************/ #include "geo_utils.h" #include #define DEG2RAD (0.017453292519943295769236907684886f) #define WGS84_A (6378137.0) #define WGS84_E2 (6.69437999014e-3) static void geo_lla_to_ecef(double lat_rad, double lon_rad, double alt_m, double ecef[3]) { double sin_lat = sin(lat_rad); double cos_lat = cos(lat_rad); double sin_lon = sin(lon_rad); double cos_lon = cos(lon_rad); double N = WGS84_A / sqrt(1.0 - WGS84_E2 * sin_lat * sin_lat); ecef[0] = (N + alt_m) * cos_lat * cos_lon; ecef[1] = (N + alt_m) * cos_lat * sin_lon; ecef[2] = (N * (1.0 - WGS84_E2) + alt_m) * sin_lat; } static void geo_ecef_to_enu(const ST_GeoOrigin *origin, const double ecef[3], float enu[3]) { double dx = ecef[0] - origin->ecef[0]; double dy = ecef[1] - origin->ecef[1]; double dz = ecef[2] - origin->ecef[2]; float east = (float)(-origin->sin_lon * dx + origin->cos_lon * dy); float north = (float)(-origin->sin_lat * origin->cos_lon * dx - origin->sin_lat * origin->sin_lon * dy + origin->cos_lat * dz); float up = (float)(origin->cos_lat * origin->cos_lon * dx + origin->cos_lat * origin->sin_lon * dy + origin->sin_lat * dz); enu[0] = east; enu[1] = north; enu[2] = up; } /* 预先计算 ENU 原点,缓存经纬度 sin/cos 以及 ECEF 坐标 */ HIDO_VOID Geo_OriginInit(ST_GeoOrigin *_pstOrigin, double _latDeg, double _lonDeg, double _altM) { if (_pstOrigin == HIDO_NULL) { return; } _pstOrigin->lat_deg = _latDeg; _pstOrigin->lon_deg = _lonDeg; _pstOrigin->alt_m = _altM; _pstOrigin->lat_rad = _latDeg * DEG2RAD; _pstOrigin->lon_rad = _lonDeg * DEG2RAD; _pstOrigin->sin_lat = sin(_pstOrigin->lat_rad); _pstOrigin->cos_lat = cos(_pstOrigin->lat_rad); _pstOrigin->sin_lon = sin(_pstOrigin->lon_rad); _pstOrigin->cos_lon = cos(_pstOrigin->lon_rad); geo_lla_to_ecef(_pstOrigin->lat_rad, _pstOrigin->lon_rad, _pstOrigin->alt_m, _pstOrigin->ecef); _pstOrigin->initialized = HIDO_TRUE; } /* 将 GPRMI (经纬高) 转换为相对原点的 ENU 坐标 */ HIDO_VOID Geo_GprmiToENU(const ST_GPRMI *_pstGprmi, const ST_GeoOrigin *_pstOrigin, float _enu[3]) { if (_enu == HIDO_NULL) { return; } _enu[0] = 0.0f; _enu[1] = 0.0f; _enu[2] = 0.0f; if (_pstGprmi == HIDO_NULL || _pstOrigin == HIDO_NULL) { return; } if (_pstGprmi->m_bValid == HIDO_FALSE || _pstOrigin->initialized == HIDO_FALSE) { return; } double ecef[3]; geo_lla_to_ecef(_pstGprmi->m_dLatitude * DEG2RAD, _pstGprmi->m_dLongitude * DEG2RAD, (double)_pstGprmi->m_fAltitude, ecef); geo_ecef_to_enu(_pstOrigin, ecef, _enu); }