将[经度、纬度、海拔]格式的数据转换为[x,y,z]格式

问题描述 投票:0回答:1

我有一个航班数据集。飞机与地面站通信,通过 GPS,我可以获得当前飞机位置和地面站位置之间的距离,以及各自的经度、纬度和高度。 我现在需要做的是将 long、lat、alt 位置数据转换为 x、y、z 坐标系。

由于地面站处于静态位置,我希望它位于坐标系的原点(0,0,0)。 我正在寻找一个可以处理这种转换的 python 模块。

作为示例,我提供了来自地面站的实际数据以及需要转换的飞机的 1 个位置:

地面站 [应该是 (0, 0, 0)] 纬度:41.947.694
经度:3.209.083 海拔高度(米):379.41

飞机位置: 纬度:419.763.015.750 长:34.890.851.772 海拔[米]: 971.32

将地面站移动到原点,如果我理解正确的话,我必须从飞机位置中减去它的位置,这意味着:

地面站: 纬度: 0 经度: 0 海拔高度(米):0

飞机位置: 纬度:419.721.068.056
长:34.887.642.689 海拔[米]: 591.91

由于我是处理此类数据的新手,并尝试了一些简单的解决方案,但没有找到任何转换此数据的内容,我希望您能帮助我找到解决方案。

我需要转换后的数据来模拟 3D 椭球体以找到可能的交点。 这也可以使用与 python 不同的方法来完成。所以如果我从来没有使用过的话,matlab 也很好。

提前致谢!

python matlab gps simulation
1个回答
0
投票

转换纬度、经度和高度 GPS 坐标, 这是大地坐标(垂直方向是 垂直于椭球体而不是地球中心的方向) 基于 WGS84 参考椭球体,以“xyz”坐标,地心, 在所谓的地心地球固定框架中是一个函数 在多个库中以多种语言实现。自从Matlab 提到过,它的实现为

geodetic2ecef

一些文本和网站也对此进行了描述,甚至在 维基百科, 这样我们就可以安全地从头开始实施它。

如果将站点坐标和平面坐标都变换为这个 ECEF x,y,z 坐标,你可以计算它们的差值,然后你 已经有一个 XYZ 坐标系统,即 (0, 0, 0) 车站。

请注意,确实,正如评论中提到的,您不能执行 纬度或经度本身与任何位置的差异 有意义的解释。找出两个之间的距离 点我们只能减去大小,如向量或笛卡尔坐标; 纬度和经度与这些不线性相关。

现在,按照前面描述计算的 xyz 差异并不是很大 本身很重要,因为它们的参考方向 是全局的 - z 轴平行于旋转轴 地球和 xz 平面平行于本初子午线。

为此,我建议通过添加(双)来“本地化”这些差异 旋转这些全局方向以使它们指向 与参考站相关的方向:新的 z 轴 为大地垂直线(朝向天顶), 新的 x 轴从车站向北,y 轴向东。

同样,这些计算在文献中有详细记录,并且 在线,在这里从头开始实现它们是安全的。

这是一个例子,可能是用python实现的,效率不是很高 因为它重复计算三角函数 基础,但我的目的是尽可能清楚地表达,而不是 高效。

import math

a = 6378137  # semi major axis, WGS84
# f = 1 / 298.257223563 # WGS84
e2 = 6.69437999014e-3  # eccentricity, WGS84 e2 = 1 - (1-f)*(1-f)


def gps_to_geocentric_ecef(lat, lon, alt):
    # converts geodetic latitude, longitude, altitude based on WGS84 (GPS coordinates)
    # to geocentric x, y, z in meters (ECEF), sqrt(x^2+y^2+z^2) = geocentric radius
    # |z| distance to equatorial plane, |x| distance to the plane of the prime meridian
    # https://en.wikipedia.org/wiki/Geodetic_coordinates#Conversion
    # https://github.com/proj4js/proj4js/blob/master/lib/datumUtils.js#L68C5-L70C44
    # verify: https://tool-online.com/en/coordinate-converter.php (right select WORLD and XYZ (geocentric))
    # or: https://www.oc.nps.edu/oc2902w/coord/llhxyz.htm - paste lat, lon, height, then press "LLH to ECEF"

    lat = math.radians(lat)
    lon = math.radians(lon)
    sin_lat = math.sin(lat)
    cos_lat = math.cos(lat)
    cos_lon = math.cos(lon)
    sin_lon = math.sin(lon)

    rn = a / (math.sqrt(1 - e2 * sin_lat * sin_lat))
    x = (rn + alt) * cos_lat * cos_lon
    y = (rn + alt) * cos_lat * sin_lon
    z = ((rn * (1 - e2)) + alt) * sin_lat

    return [x, y, z]


def rotate_ecef_to_local_xyz(dx, dy, dz, lat, lon):
    # rotates the coordinate differences dx, dy, dz fromm the global frame (ECEF) to
    # a local frame that has the geodetic normal to (lat, lon) as z-axis, while
    # the new x-axis is towards North and the y-axis towards East

    lat = math.radians(lat)
    lon = math.radians(lon)

    cos_lon = math.cos(lon)
    sin_lon = math.sin(lon)
    cos_lat = math.cos(lat)
    sin_lat = math.sin(lat)
    dx, dy, dz = (- dx * cos_lon * sin_lat - dy * sin_lon * sin_lat + dz * cos_lat,
                  - dx * sin_lon + dy * cos_lon,
                  dx * cos_lon * cos_lat + dy * sin_lon * cos_lat + dz * sin_lat)

    return [dx, dy, dz]


def main():
    bgr_lat, bgr_lon, bgr_alt = [41.947694, 3.209083, 379.41]
    airplane_gps = [
        [41.9763015750,  3.4890851772, 971.32]
    ]

    # ecef coordinates for the station:
    bgr_xyz = gps_to_geocentric_ecef(bgr_lat, bgr_lon, bgr_alt)

    # ecef coordinates for the (first) airplane:
    plane_xyz = gps_to_geocentric_ecef(*airplane_gps[0])

    # xyz position of the airplane relative to the station, ecef orientation:
    diff_xyz = [plane_xyz[i] - bgr_xyz[i] for i in range(3)]

    # xyz position of the airplane relative to the station, station-local orientation
    local_xyz = rotate_ecef_to_local_xyz(*diff_xyz, bgr_lat, bgr_lon)

    print(local_xyz)  # final result, in meters (x-towards North, y-towards East, z-towards Zenith)


if __name__ == '__main__':
    main()

由于海拔高度以米为单位,因此我使用了 WGS84 半长轴也以米为单位,结果以米为单位: 该平面向北 3215m,向东 23210m, 高 549m(从地球切线平面测量) 经过参考站 BGR)

虽然我通过多种方式彻底验证了这段代码,但我仍然希望 没有人会基于它来驾驶飞机:)

© www.soinside.com 2019 - 2024. All rights reserved.