• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
MKT-porter
博客园    首页    新随笔    联系   管理    订阅  订阅
坐标系转换- 大地坐标系到GPS坐标系

 

世界大地测量系统(World Geodetic System, WGS),比如WGS84,是一种地理坐标系统,用于全球定位系统(GPS)。 

 ENU(东、北、天)坐标系就是分别以原点正东方、正北方和垂直地表正上方作为XYZ三轴正方向的坐标系,ENU坐标系又称为站心坐标系或站点坐标系;

 NED(北、东、地)坐标系就是分别以原点正北方、正东方和正下方作为XYZ三轴正方向的坐标系,NED坐标系ENU坐标系本质上是一体两面的。

 

 

1.1 ECEF坐标系

 

  也叫地心地固直角坐标系。其原点为地球的质心,x轴延伸通过本初子午线(0度经度)和赤道(0deglatitude)的交点。 z轴延伸通过的北极(即,与地球旋转轴重合)。 y轴完成右手坐标系,穿过赤道和90度经度。

 

 ENU坐标系和NED坐标系如图1所示: 

 

 

1.2 WGS-84坐标
  也就是也叫经纬高坐标系(经度(longitude),纬度(latitude)和高度(altitude)LLA坐标系)。,全球地理坐标系、大地坐标系。可以说是最为广泛应用的一个地球坐标系,它给出一点的大地纬度、大地经度和大地高程而更加直观地告诉我们该点在地球中的位置,故又被称作纬经高坐标系。WGS-84坐标系的X轴指向BIH(国际时间服务机构)1984.0定义的零子午面(Greenwich)和协议地球极(CTP)赤道的交点。Z轴指向CTP方向。Y轴与X、Z轴构成右手坐标系。

  一句话解释就是:把前面提到的ECEF坐标系用在GPS中,就是WGS-84坐标系。
其中:
(1):大地纬度是过用户点P的基准椭球面法线与赤道面的夹角。纬度值在-90°到+90°之间。北半球为正,南半球为负。

(2):大地经度是过用户点P的子午面与本初子午线之间的夹角。经度值在-180°到+180°之间。

(3):大地高度h是过用户点P到基准椭球面的法线距离,基准椭球面以内为负,以外为正。

 

 

 

 

1.3 东北天坐标系(ENU)
  也叫站心坐标系以用户所在位置P为坐标原点。

  坐标系定义为: X轴:指向东边 Y轴:指向北边 Z轴:指向天顶

  ENU局部坐标系采用三维直角坐标系来描述地球表面,实际应用较为困难,因此一般使用简化后的二维投影坐标系来描述。在众多二维投影坐标系中,统一横轴墨卡托(The Universal Transverse Mercator ,UTM)坐标系是一种应用较为广泛的一种。UTM 坐标系统使用基于网格的方法表示坐标,它将地球分为 60 个经度区,每个区包含6度的经度范围,每个区内的坐标均基于横轴墨卡托投影,如下图所示:



 

#!/usr/bin/python
# -*- coding: UTF-8 -*-



'''


// 北东天->gps
void world2GPS(double r_lat, double r_lon, double x_in_NED, double y_in_NED, double& t_lon, double& t_lat) {
    double y_rad = x_in_NED / C_EARTH;
    t_lat = (r_lat + RAD2DEG(y_rad));
    double x_rad = y_in_NED / C_EARTH / cos(DEG2RAD(t_lat));
    t_lon = r_lon + RAD2DEG(x_rad);
}

void trans_NED2GPS(std::map<std::string, cv::Point3d>& all_gps_data) {
    std::map<std::string, cv::Point3d>::iterator it;
    double init_lat = 25.44993764;  // 纬度
    double init_lon = 112.71335009; // 经度
    // std::ofstream out("../data/gps_ccctrans.txt", std::ios::app);
    for (it = all_gps_data.begin(); it != all_gps_data.end(); it++) {
        double lat, lon;
        // std::cout<<"x:"<<(it->second).x<<std::endl;
        // std::cout<<"y:"<<(it->second).y<<std::endl;
        world2GPS(init_lat, init_lon, (it->second).x, (it->second).y, lon, lat);
        it->second.x = lat;
        it->second.y = lon;
        // std::cout<<"lat:"<<lat<<std::endl;
        // std::cout<<"lon:"<<lon<<std::endl<<std::endl;
        // out<<it->first<<" "<<std::setprecision(12)<<lat<<" "<<lon<<" "<<(it->second).z<<std::endl;
    }
    // out.close();
}


'''

import pyproj

#初始化GPS位置
#111.492682  24.413449  351
gps_int=[111.492682,24.413449,351]


def ecef2lla(x,y,z):
    '''

    x = 652954.1006

    y = 0

    z = -4167647.7937

    '''

    #ecef转化为经纬高

    ecef = pyproj.Proj(proj='geocent', ellps='WGS84', datum='WGS84')

    lla = pyproj.Proj(proj='latlong', ellps='WGS84', datum='WGS84')

    lon, lat, alt = pyproj.transform(ecef, lla, x, y, z, radians=False)#radians否用弧度返回值

    print ('纬度:',lat)

    print ('经度:',lon)

    print ('高度:',alt)

    return lat,lon,alt



import math as mt
'''以下为WGS84椭球参数'''
a = 6378137.0         # 参考椭球的长半轴, 单位 m
b = 6356752.31414     # 参考椭球的短半轴, 单位 m
 
'''以下为三角函数调用'''
a = 6378137.0         # 参考椭球的长半轴, 单位 m
f=1 / 298.257223563     # 参考椭球的扁率
b = 6356752.31414     # 参考椭球的短半轴, 单位 m
'''以下为三角函数调用'''
sqrt = mt.sqrt
sin = mt.sin
cos = mt.cos
atan = mt.atan
atan2=mt.atan2
fabs=math.fabs
'''弧度转角度'''
def rad2angle(r):
    """
    该函数可以实现弧度到角度的转换.
    :param r:  弧度
    :return:  a, 对应的角度
    """
    a = r*180.0/mt.pi
    return a
 
'''角度转换弧度函数'''
def angle2rad(a):
    """
    该函数可以实现角度到弧度的转换.
    :param a:  角度
    :return:  r, 对应的弧度
    """
    r = a*mt.pi/180.0
    return r
 
def XYZ2BLH(X, Y, Z):
    """
    该函数实现把某点在参心空间直角坐标系下的坐标(X, Y, Z)转为大地坐标(B, L, H).
    :param X:  X方向坐标,单位 m
    :param Y:  Y方向坐标, 单位 m
    :param Z:  Z方向坐标, 单位 m
    :param a: 地球长半轴,即赤道半径,单位 m
    :param b: 地球短半轴,即大地坐标系原点到两级的距离, 单位 m
    :return:  B, L, H, 大地纬度、经度、海拔高度 (m)
    """
    R = sqrt(X * X + Y * Y)
    B0 = atan2(Z, R)
 
    while 1:
        N = a/ sqrt(1.0 - f * (2 - f) * sin(B0) * sin(B0))
        B_ = atan2(Z + N * f* (2 - f) * sin(B0), R)
        if (fabs(B_ - B0) < 1.0e-7):
            break
        B0 = B_
    L_ = atan2(Y, X)
    H= R / cos(B_) - N
    B=rad2angle(B_)
    L=rad2angle(L_)
    return B,L,H
 
 
 
'''该函数把某点的大地坐标(B, L, H)转换为空间直角坐标(X, Y, Z)'''
def BLH2XYZ(B, L, H):
    """
     该函数把某点的大地坐标(B, L, H)转换为空间直角坐标(X, Y, Z).
    :param B:  大地纬度, 角度制, 规定南纬为负,范围为[-90, 90]
    :param L:  大地经度, 角度制, 规定西经为负, 范围为[-180, 180]
    :param H:  海拔,大地高, 单位 m
    :param a:  地球长半轴,即赤道半径,单位 m
    :param b:  地球短半轴,即大地坐标系原点到两级的距离, 单位 m
    :return:   X, Y, Z, 空间直角坐标, 单位 m
    """
 
    B = angle2rad(B)    # 角度转为弧度
    L = angle2rad(L)    # 角度转为弧度
 
    e = sqrt((a**2-b**2)/(a**2))     # 参考椭球的第一偏心率
    N = a/sqrt(1-e*e*sin(B)*sin(B))  # 卯酉圈半径, 单位 m
 
    X =(N+H)*cos(B)*cos(L)
    Y = (N+H)*cos(B)*sin(L)
    Z = (N*(1-e*e)+H)*sin(B)
    return X, Y, Z    # 返回空间直角坐标(X, Y, Z)
 
'''以下函数为大地坐标转站心地平坐标'''
def XYZ2NEU(X,Y,Z,X1,Y1,Z1):
    """
    该函数实现把某点在参心空间直角坐标系下的坐标(X, Y, Z)转为站心地平坐标(E,N,U).
     X,Y,Z 定位结果的XYZ值
     X1,Y1,Z1 参考坐标的XYZ值
    :return:  N, E ,U, 东方向,北方向,天顶方向(m)
    """
    dx=X-X1
    dy=Y-Y1
    dz=Z-Z1
    B,L,H=XYZ2BLH(X1,Y1,Z1)
    B=angle2rad(B)
    L=angle2rad(L)
    N = -sin(B)*cos(L)*dx-sin(B)*sin(L)*dy+cos(B)*dz
    E = -sin(L)*dx+cos(L)*dy
    U = cos(B)*cos(L)*dx+cos(B)*sin(L)*dy+sin(B)*dz
    H=sqrt(pow(N,2)+pow(E,2))#平面方向高程
    error=sqrt(pow(dx,2)+pow(dy,2)+pow(dz,2))
    return H,U,error

  

 

posted on 2022-06-13 20:31  MKT-porter  阅读(5474)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3