Android 将GPS转换为ENU

Android 将GPS转换为ENU,android,gps,coordinates,Android,Gps,Coordinates,我想创建android应用程序“兴趣点”。我读过很多不同的教程,我不明白为什么我需要将GPS坐标转换为ECEF,然后再转换为ENU。你能解释一下吗 谢谢 地理空间坐标系是一个很大的主题,但在ECEF和ENU等系统之间的主要选择是关于您是要描述地球表面的一个大区域还是一个小区域 当Android通过API提供时,它通常使用纬度/经度/高度来实现这一点,这是表示地球表面上任何点的理想方法,但它是一个“极坐标”或“大地坐标”坐标系,不适合绘制二维位置。标准允许将该坐标系转换为ECEF,ECEF是另一个

我想创建android应用程序“兴趣点”。我读过很多不同的教程,我不明白为什么我需要将GPS坐标转换为ECEF,然后再转换为ENU。你能解释一下吗


谢谢

地理空间坐标系是一个很大的主题,但在ECEF和ENU等系统之间的主要选择是关于您是要描述地球表面的一个大区域还是一个小区域

当Android通过API提供时,它通常使用纬度/经度/高度来实现这一点,这是表示地球表面上任何点的理想方法,但它是一个“极坐标”或“大地坐标”坐标系,不适合绘制二维位置。标准允许将该坐标系转换为ECEF,ECEF是另一个适用于整个地球的坐标系,但它是“笛卡尔坐标系”,因此可以使用比原始纬度/经度/高度坐标简单得多的数学运算进行旋转和缩放

以地球为中心的固定地球()使用原点位于地球中心的坐标系,因此地面上的任何点都将具有通常以百万米为单位的坐标值。这对于描述卫星轨道或跨越多个大陆的位置非常有用,但对于城镇或城市内感兴趣点的2D绘图来说却不太方便

如果您想绘制地球表面一个小区域的二维地图,那么“东-北-上”坐标系可能更方便。要使用它,您需要一个参考位置(例如特定城市的中心),可以在该位置上定义本地的东/北/向上方向。然后,它们提供一组x/y/z轴,其中x&y轴可以直接转换为二维屏幕坐标。显然,随着感兴趣区域变大(例如超过100公里),地球曲率的影响变得更加明显,而ENU坐标系将不再有用。有关更多信息,请参阅


从ECEF坐标系到ENU坐标系的移动可以通过一组简单的矩阵加法和乘法来完成,这些矩阵加法和乘法可以从地图中心的ECEF位置以及东/北/上方向的单位向量来计算。

您可以在Java上这样做

public List<Double> convertGpsToECEF(double lat, double longi, float alt) {

    double a=6378.1;
    double b=6356.8;
    double N;
    double e= 1-(Math.pow(b, 2)/Math.pow(a, 2));
    N= a/(Math.sqrt(1.0-(e*Math.pow(Math.sin(Math.toRadians(lat)), 2))));
    double cosLatRad=Math.cos(Math.toRadians(lat));
    double cosLongiRad=Math.cos(Math.toRadians(longi));
    double sinLatRad=Math.sin(Math.toRadians(lat));
    double sinLongiRad=Math.sin(Math.toRadians(longi));
    double x =(N+0.001*alt)*cosLatRad*cosLongiRad;
    double y =(N+0.001*alt)*cosLatRad*sinLongiRad;
    double z =((Math.pow(b, 2)/Math.pow(a, 2))*N+0.001*alt)*sinLatRad;

    List<Double> ecef= new ArrayList<>();
    ecef.add(x);
    ecef.add(y);
    ecef.add(z);

    return ecef;


}


public List<Double> convertECEFtoENU(List<Double> ecefUser, List<Double> ecefPOI, double lat, double longi){

    double cosLatRad=Math.cos(Math.toRadians(lat));
    double cosLongiRad=Math.cos(Math.toRadians(longi));
    double sinLatRad=Math.sin(Math.toRadians(lat));
    double sinLongiRad=Math.sin(Math.toRadians(longi));


    List<Double> vector = new ArrayList<>();

    vector.add(ecefUser.get(0)-ecefPOI.get(0));
    vector.add(ecefUser.get(1)-ecefPOI.get(1));
    vector.add(ecefUser.get(2)-ecefPOI.get(2));

    double e= vector.get(0)*(-sinLongiRad)+vector.get(0)*(cosLongiRad);
    double n= vector.get(0)*(-sinLatRad)*(cosLongiRad)+vector.get(1)*(-sinLatRad)*(sinLongiRad)+vector.get(2)*cosLatRad;
    double u= vector.get(0)*(cosLatRad)*(cosLongiRad)+vector.get(1)*(cosLatRad)*(sinLongiRad)+vector.get(2)*sinLatRad;


    List<Double> enu= new ArrayList<>();
    enu.add(e);
    enu.add(n);
    enu.add(u);

    return enu;
    }
public List convertGpsToECEF(双lat、双longi、float-alt){
双a=6378.1;
双b=6356.8;
双N;
双e=1-(数学功率(b,2)/数学功率(a,2));
N=a/(数学sqrt(1.0-(e*Math.pow(Math.sin(Math.toRadians,lat)),2));
double-cosLatRad=Math.cos(Math.toRadians(lat));
双余弦长=数学余弦(数学余弦长);
double sinLatRad=Math.sin(Math.toRadians(lat));
double sinLongiRad=Math.sin(Math.toRadians(longi));
双x=(N+0.001*alt)*余弦*余弦;
双y=(N+0.001*alt)*共轴*正弦;
双z=((数学功率(b,2)/数学功率(a,2))*N+0.001*alt)*sinLatRad;
List ecef=new ArrayList();
ecef.添加(x);
ecef.添加(y);
ecef.添加(z);
返回ecef;
}
公共列表转换器ECEFTOENU(列表ecefUser、列表ecefPOI、双lat、双longi){
double-cosLatRad=Math.cos(Math.toRadians(lat));
双余弦长=数学余弦(数学余弦长);
double sinLatRad=Math.sin(Math.toRadians(lat));
double sinLongiRad=Math.sin(Math.toRadians(longi));
列表向量=新的ArrayList();
add(ecefUser.get(0)-ecefPOI.get(0));
add(ecefUser.get(1)-ecefPOI.get(1));
add(ecefUser.get(2)-ecefPOI.get(2));
双e=向量get(0)*(-sinLongiRad)+向量get(0)*(coslongrad);
双n=向量get(0)*(-sinLatRad)*(coslongrad)+向量get(1)*(-sinLatRad)*(sinLongiRad)+向量get(2)*cosLatRad;
双u=vector.get(0)*(cosLatRad)*(coslongrad)+vector.get(1)*(cosLatRad)*(sinLongiRad)+vector.get(2)*sinLatRad;
列表enu=新的ArrayList();
enu.添加(e);
enu.添加(n);
enu.添加(u);
返回菜单;
}

您为什么认为需要这样做?我看不出任何理由。@VladyslavMatviienko GPS坐标是地理坐标系,但要在屏幕上显示它们,我需要笛卡尔坐标系。