【问题标题】:ECEF to lla (lat,lon,alt) in javaJava中的ECEF到lla(lat,lon,alt)
【发布时间】:2013-08-15 13:20:26
【问题描述】:

我浏览了网站上的帖子并没有发现我的问题... 正如标题所说,我正在尝试从 ecef 转换为 lla 。

我正在使用此文档:Conversion article 在直接公式中,而不是在迭代公式中 和这个网站进行结果比较:ECEF2LLA

我是用java开发的,所以我的代码如下:

public static final double a = 6378137;
public static final double f = 1/298.257223563;
public static final double b = a*(1-f);
public static final double e = Math.sqrt((Math.pow(a, 2)-Math.pow(b, 2))/Math.pow(a, 2));
public static final double e2 = Math.sqrt((Math.pow(a, 2)-Math.pow(b, 2))/Math.pow(b, 2));
public static double[] ecef2lla(double x , double y , double z){
    double[] lla = {0,0,0};
    double lon,lat,height,N;
    double p = Math.sqrt(Math.pow(x, 2)+Math.pow(y, 2));
    double theta = Math.atan((z*a)/(p*b));
    lon = Math.atan(y/x);
    lon = lon*180/Math.PI;

    lat = Math.atan(((z+Math.pow(e2, 2)*b*Math.pow(Math.sin(theta), 3))/((p-Math.pow(e,2)*a*Math.pow(Math.cos(theta), 3)))));
    lat = (lat*180)/Math.PI;

    N= a/(Math.sqrt(1-Math.pow(e*Math.sin(lat), 2)));
    height = (p/Math.cos(theta)) - N;
    lla[0] = lon;
    lla[1] = lat;
    lla[2] = height;
    return lla;

}

我得到了错误的身高数据。 我试图移动到弧度和度数,什么不是。

提前谢谢你!

【问题讨论】:

    标签: java math gps latitude-longitude coordinate-systems


    【解决方案1】:

    我找到了这篇文章,并准备在我的部分应用程序中使用“接受的答案”,但我决定先运行几个测试来验证算法。我使用了在线转换计算器 (http://www.sysense.com/products/ecef_lla_converter/index.html) 生成的样本数据。我得到的结果并不理想,如下面的输出所示。

    -----Test 1---------
    Inputs:   -576793.17, -5376363.47, 3372298.51
    Expected: 32.12345, -96.12345, 500.0
    Actuals:  32.12306332822881, 83.87654999786477, 486.5472474489361
    -----Test 2---------
    Inputs:   2297292.91, 1016894.94, -5843939.62
    Expected: -66.87654, 23.87654, 1000.0
    Actuals:  -66.876230479461, 23.87653991401422, 959.6879360172898
    

    然后我使用以下帖子 (https://gist.github.com/klucar/1536194) 中的代码重新运行相同的测试,并获得了更好的结果,如下面的输出所示。

    -----Test 1---------
    Inputs:   -576793.17, -5376363.47, 3372298.51
    Expected: 32.12345, -96.12345, 500.0
    Actuals:  32.12345004807767, -96.12345000213524, 499.997958839871
    -----Test 2---------
    Inputs:   2297292.91, 1016894.94, -5843939.62
    Expected: -66.87654, 23.87654, 1000.0
    Actuals:  -66.87654001741278, 23.87653991401422, 999.9983866894618
    

    我没有花时间在“已接受的答案”中提供的解决方案中找到错误,但我建议的答案是:使用此代码...

    /*
    *
    *  ECEF - Earth Centered Earth Fixed
    *   
    *  LLA - Lat Lon Alt
    *
    *  ported from matlab code at
    *  https://gist.github.com/1536054
    *     and
    *  https://gist.github.com/1536056
    */
    
    // WGS84 ellipsoid constants
    private final double a = 6378137; // radius
    private final double e = 8.1819190842622e-2;  // eccentricity
    
    private final double asq = Math.pow(a,2);
    private final double esq = Math.pow(e,2);
    
    private double[] ecef2lla(double[] ecef){
      double x = ecef[0];
      double y = ecef[1];
      double z = ecef[2];
    
      double b = Math.sqrt( asq * (1-esq) );
      double bsq = Math.pow(b,2);
      double ep = Math.sqrt( (asq - bsq)/bsq);
      double p = Math.sqrt( Math.pow(x,2) + Math.pow(y,2) );
      double th = Math.atan2(a*z, b*p);
    
      double lon = Math.atan2(y,x);
      double lat = Math.atan2( (z + Math.pow(ep,2)*b*Math.pow(Math.sin(th),3) ), (p - esq*a*Math.pow(Math.cos(th),3)) );
      double N = a/( Math.sqrt(1-esq*Math.pow(Math.sin(lat),2)) );
      double alt = p / Math.cos(lat) - N;
    
      // mod lat to 0-2pi
      lon = lon % (2*Math.PI);
    
      // correction for altitude near poles left out.
    
      double[] ret = {lat, lon, alt};
    
      return ret;
    }
    

    【讨论】:

      【解决方案2】:

      好的,所以我得到了这个工作。

      问题是一个放错位置的变量,所以为了我们的未来,这里是有效的 JAVA 实现:

      public static final double a = 6378137;
      public static final double f = 0.0034;
      public static final double b = 6.3568e6;
      public static final double e = Math.sqrt((Math.pow(a, 2) - Math.pow(b, 2)) / Math.pow(a, 2));
      public static final double e2 = Math.sqrt((Math.pow(a, 2) - Math.pow(b, 2)) / Math.pow(b, 2));
      
      public static double[] ecef2lla(double x, double y, double z) {
      
          double[] lla = { 0, 0, 0 };
          double lan, lon, height, N , theta, p;
      
          p = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
      
          theta = Math.atan((z * a) / (p * b));
      
          lon = Math.atan(y / x);
      
          lat = Math.atan(((z + Math.pow(e2, 2) * b * Math.pow(Math.sin(theta), 3)) / ((p - Math.pow(e, 2) * a * Math.pow(Math.cos(theta), 3)))));
          N = a / (Math.sqrt(1 - (Math.pow(e, 2) * Math.pow(Math.sin(lat), 2))));
      
          double m = (p / Math.cos(lat));
          height = m - N;
      
      
          lon = lon * 180 / Math.PI;
          lat = lat * 180 / Math.PI; 
          lla[0] = lat;
          lla[1] = lon;
          lla[2] = height;
          return lla;
      }
      

      注意ECEF X Y Z的单位是

      【讨论】:

      • 我认为您需要使用 atan2 才能获得所有可能经度的正确结果。
      • 这里的 f 是什么?没用过
      【解决方案3】:

      如果您有兴趣使用已发布的 java 库在笛卡尔坐标系和大地坐标系之间进行转换,可以使用 java 轨道传播库orekit

      虽然 Orekit 提供了一些高级功能,但要深入了解它并不容易。为了帮助您入门,我编写了一个示例代码进行了一些转换。我的代码在 Scala 中,但它使用 java 库,所以它应该仍然有用。参见示例代码here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-05
        • 1970-01-01
        • 1970-01-01
        • 2012-01-08
        • 1970-01-01
        • 1970-01-01
        • 2018-01-08
        • 2016-07-16
        相关资源
        最近更新 更多