如何将经/纬度坐标转换为地球表面上的NE米距离?

发布于 2024-10-11 23:55:26 字数 273 浏览 3 评论 0原文

在地球表面进行一些平移(以米为单位)后,如何从参考点(大地测量中)获得新的大地测量坐标(纬度/经度),并且我还需要使用真实的地球椭球体模型进行计算,例如WGS84。

例如:

  • 假设我的参考点为 10.32E,-4.31N
  • ,那么我会平移 (3000,-2000) 米(即将点向东移动 3000 米,向南移动 2000 米在地球表面
  • 我需要大地测量中的新点的坐标,

谢谢。

how do I get a new coordinate in geodetic (Lat/Lon) from a reference point (which is in geodetic) after some translation (in meters) on earth surface, and also I need to do the calculation using true earth ellipsoid model such as WGS84.

for example:

  • suppose I have reference point of 10.32E, -4.31N
  • then I do translation of (3000,-2000) meters ( which is move the point 3000 meters to east and 2000 meters to south on earth surface.
  • then I need the coordinate of new point in geodetic.

thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

生寂 2024-10-18 23:55:26

查看开源库 PROJ.4,您可以使用它来准确翻译地理坐标(纬度/经度)到投影坐标(米),然后再返回。在您的情况下,您可以投影到 WGS 84 / World Mercator (EPSG:3395),执行以米为单位进行翻译,然后取消投影回地理。

Have a look at the open-source library PROJ.4 which you can use to accurately translate geographic coordinates (lat/long) to projected coordinates (metres), and back again. In your case you can project into WGS 84 / World Mercator (EPSG:3395), perform the translation in metres, then un-project back to geographic.

七度光 2024-10-18 23:55:26

找到答案:

http://www.movable-type.co .uk/scripts/latlong-vincenty-direct.html

来自:
Vincenty 直接公式 - T Vincenty,“测地线的正解和逆解
应用嵌套方程的椭球”,调查评论,第 XXII 卷第 176 期,1975

http:// www.ngs.noaa.gov/PUBS_LIB/inverse.pdf

found the answer :

http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html

from:
Vincenty direct formula - T Vincenty, "Direct and Inverse Solutions of Geodesics on the
Ellipsoid with application of nested equations", Survey Review, vol XXII no 176, 1975

http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf

注定孤独终老 2024-10-18 23:55:26

此代码计算给定纬度/经度坐标的两点之间的距离(N 和 E)。您可以轻松地将其反转以达到您的目的。

看看

u8 GPS_CalculateDeviation()

http中的

函数: //svn.mikrokopter.de/filedetails.php?repname=NaviCtrl&path=/tags/V0.15c/GPS.c

This code calculates the distance (N and E) between two points given lat/lon coordinates. You can easily reverse it for your purposes.

Take a look at function

u8 GPS_CalculateDeviation()

in

http://svn.mikrokopter.de/filedetails.php?repname=NaviCtrl&path=/tags/V0.15c/GPS.c

思念绕指尖 2024-10-18 23:55:26

您要么找到一些地理图书馆,要么自己做三角学。

无论如何,你应该更准确地提出你的问题。特别是你说:

然后我平移(3000,-2000)米(即将地球表面的点向东移动3000米,向南移动2000米。

您应该注意,向东移动3公里,然后向南移动2公里不同< /strong> 从向南移动 2 公里,然后向东移动 3 公里,因此通过偏移 (3000, -2000) 来调用它是不正确的。

You either find some geo-library, or do the trigonometry yourself.

In any case you should formulate your question more exactly. In particular you say:

then I do translation of (3000,-2000) meters ( which is move the point 3000 meters to east and 2000 meters to south on earth surface.

You should note that moving by 3km to east and then 2km to south differs from moving 2km to south and then 3km to east. Those are not commutative actions. So that calling this by offsetting (3000, -2000) is incorrect.

软甜啾 2024-10-18 23:55:26

下面是从苏黎世联邦理工学院的 原始版本稍作修改的 C++ 代码。该文件仅依赖于 Eigen 库(如果需要,可以通过编写矩阵乘法来消除一些琐碎的工作)自己发挥作用)。您可以使用 geodetic2ned() 函数将纬度、经度、海拔高度转换为 NED 坐标系。

//GeodeticConverter.hpp
#ifndef air_GeodeticConverter_hpp
#define air_GeodeticConverter_hpp

#include <math>
#include <eigen3/Eigen/Dense>

class GeodeticConverter
{
 public:
  GeodeticConverter(double home_latitude = 0, double home_longitude = 0, double home_altitude = 0)
    : home_latitude_(home_latitude), home_longitude_(home_longitude)
  {
    // Save NED origin
    home_latitude_rad_ = deg2Rad(latitude);
    home_longitude_rad_ = deg2Rad(longitude);
    home_altitude_ = altitude;

    // Compute ECEF of NED origin
    geodetic2Ecef(latitude, longitude, altitude, &home_ecef_x_, &home_ecef_y_, &home_ecef_z_);

    // Compute ECEF to NED and NED to ECEF matrices
    double phiP = atan2(home_ecef_z_, sqrt(pow(home_ecef_x_, 2) + pow(home_ecef_y_, 2)));

    ecef_to_ned_matrix_ = nRe(phiP, home_longitude_rad_);
    ned_to_ecef_matrix_ = nRe(home_latitude_rad_, home_longitude_rad_).transpose();    
  }

  void getHome(double* latitude, double* longitude, double* altitude)
  {
    *latitude = home_latitude_;
    *longitude = home_longitude_;
    *altitude = home_altitude_;
  }

  void geodetic2Ecef(const double latitude, const double longitude, const double altitude, double* x,
                     double* y, double* z)
  {
    // Convert geodetic coordinates to ECEF.
    // http://code.google.com/p/pysatel/source/browse/trunk/coord.py?r=22
    double lat_rad = deg2Rad(latitude);
    double lon_rad = deg2Rad(longitude);
    double xi = sqrt(1 - kFirstEccentricitySquared * sin(lat_rad) * sin(lat_rad));
    *x = (kSemimajorAxis / xi + altitude) * cos(lat_rad) * cos(lon_rad);
    *y = (kSemimajorAxis / xi + altitude) * cos(lat_rad) * sin(lon_rad);
    *z = (kSemimajorAxis / xi * (1 - kFirstEccentricitySquared) + altitude) * sin(lat_rad);
  }

  void ecef2Geodetic(const double x, const double y, const double z, double* latitude,
                     double* longitude, double* altitude)
  {
    // Convert ECEF coordinates to geodetic coordinates.
    // J. Zhu, "Conversion of Earth-centered Earth-fixed coordinates
    // to geodetic coordinates," IEEE Transactions on Aerospace and
    // Electronic Systems, vol. 30, pp. 957-961, 1994.

    double r = sqrt(x * x + y * y);
    double Esq = kSemimajorAxis * kSemimajorAxis - kSemiminorAxis * kSemiminorAxis;
    double F = 54 * kSemiminorAxis * kSemiminorAxis * z * z;
    double G = r * r + (1 - kFirstEccentricitySquared) * z * z - kFirstEccentricitySquared * Esq;
    double C = (kFirstEccentricitySquared * kFirstEccentricitySquared * F * r * r) / pow(G, 3);
    double S = cbrt(1 + C + sqrt(C * C + 2 * C));
    double P = F / (3 * pow((S + 1 / S + 1), 2) * G * G);
    double Q = sqrt(1 + 2 * kFirstEccentricitySquared * kFirstEccentricitySquared * P);
    double r_0 = -(P * kFirstEccentricitySquared * r) / (1 + Q)
        + sqrt(
            0.5 * kSemimajorAxis * kSemimajorAxis * (1 + 1.0 / Q)
                - P * (1 - kFirstEccentricitySquared) * z * z / (Q * (1 + Q)) - 0.5 * P * r * r);
    double U = sqrt(pow((r - kFirstEccentricitySquared * r_0), 2) + z * z);
    double V = sqrt(
        pow((r - kFirstEccentricitySquared * r_0), 2) + (1 - kFirstEccentricitySquared) * z * z);
    double Z_0 = kSemiminorAxis * kSemiminorAxis * z / (kSemimajorAxis * V);
    *altitude = U * (1 - kSemiminorAxis * kSemiminorAxis / (kSemimajorAxis * V));
    *latitude = rad2Deg(atan((z + kSecondEccentricitySquared * Z_0) / r));
    *longitude = rad2Deg(atan2(y, x));
  }

  void ecef2Ned(const double x, const double y, const double z, double* north, double* east,
                double* down)
  {
    // Converts ECEF coordinate position into local-tangent-plane NED.
    // Coordinates relative to given ECEF coordinate frame.

    Vector3d vect, ret;
    vect(0) = x - home_ecef_x_;
    vect(1) = y - home_ecef_y_;
    vect(2) = z - home_ecef_z_;
    ret = ecef_to_ned_matrix_ * vect;
    *north = ret(0);
    *east = ret(1);
    *down = -ret(2);
  }

  void ned2Ecef(const double north, const double east, const double down, double* x, double* y,
                double* z)
  {
    // NED (north/east/down) to ECEF coordinates
    Vector3d ned, ret;
    ned(0) = north;
    ned(1) = east;
    ned(2) = -down;
    ret = ned_to_ecef_matrix_ * ned;
    *x = ret(0) + home_ecef_x_;
    *y = ret(1) + home_ecef_y_;
    *z = ret(2) + home_ecef_z_;
  }

  void geodetic2Ned(const double latitude, const double longitude, const double altitude,
                    double* north, double* east, double* down)
  {
    // Geodetic position to local NED frame
    double x, y, z;
    geodetic2Ecef(latitude, longitude, altitude, &x, &y, &z);
    ecef2Ned(x, y, z, north, east, down);
  }

  void ned2Geodetic(const double north, const double east, const double down, double* latitude,
                    double* longitude, double* altitude)
  {
    // Local NED position to geodetic coordinates
    double x, y, z;
    ned2Ecef(north, east, down, &x, &y, &z);
    ecef2Geodetic(x, y, z, latitude, longitude, altitude);
  }

  void geodetic2Enu(const double latitude, const double longitude, const double altitude,
                    double* east, double* north, double* up)
  {
    // Geodetic position to local ENU frame
    double x, y, z;
    geodetic2Ecef(latitude, longitude, altitude, &x, &y, &z);

    double aux_north, aux_east, aux_down;
    ecef2Ned(x, y, z, &aux_north, &aux_east, &aux_down);

    *east = aux_east;
    *north = aux_north;
    *up = -aux_down;
  }

  void enu2Geodetic(const double east, const double north, const double up, double* latitude,
                    double* longitude, double* altitude)
  {
    // Local ENU position to geodetic coordinates

    const double aux_north = north;
    const double aux_east = east;
    const double aux_down = -up;
    double x, y, z;
    ned2Ecef(aux_north, aux_east, aux_down, &x, &y, &z);
    ecef2Geodetic(x, y, z, latitude, longitude, altitude);
  }

private:
  // Geodetic system parameters
  static double kSemimajorAxis = 6378137;
  static double kSemiminorAxis = 6356752.3142;
  static double kFirstEccentricitySquared = 6.69437999014 * 0.001;
  static double kSecondEccentricitySquared = 6.73949674228 * 0.001;
  static double kFlattening = 1 / 298.257223563;

  typedef Eigen::Vector3d Vector3d;
  typedef Eigen::Matrix<double, 3, 3> Matrix3x3d;

  inline Matrix3x3d nRe(const double lat_radians, const double lon_radians)
  {
    const double sLat = sin(lat_radians);
    const double sLon = sin(lon_radians);
    const double cLat = cos(lat_radians);
    const double cLon = cos(lon_radians);

    Matrix3x3d ret;
    ret(0, 0) = -sLat * cLon;
    ret(0, 1) = -sLat * sLon;
    ret(0, 2) = cLat;
    ret(1, 0) = -sLon;
    ret(1, 1) = cLon;
    ret(1, 2) = 0.0;
    ret(2, 0) = cLat * cLon;
    ret(2, 1) = cLat * sLon;
    ret(2, 2) = sLat;

    return ret;
  }

  inline double rad2Deg(const double radians)
  {
    return (radians / M_PI) * 180.0;
  }

  inline double deg2Rad(const double degrees)
  {
    return (degrees / 180.0) * M_PI;
  }

  double home_latitude_rad_, home_latitude_;
  double home_longitude_rad_, home_longitude_;
  double home_altitude_;

  double home_ecef_x_;
  double home_ecef_y_;
  double home_ecef_z_;

  Matrix3x3d ecef_to_ned_matrix_;
  Matrix3x3d ned_to_ecef_matrix_;

}; // class GeodeticConverter

#endif

Below is C++ code slighly modified from original version from ETH Zurich. The file only has dependency on Eigen library (which can be eliminated with some trivial work if required by writing matrix multiplication function yourself). You can use geodetic2ned() function to convert latitude, longitude, altitude to NED frame.

//GeodeticConverter.hpp
#ifndef air_GeodeticConverter_hpp
#define air_GeodeticConverter_hpp

#include <math>
#include <eigen3/Eigen/Dense>

class GeodeticConverter
{
 public:
  GeodeticConverter(double home_latitude = 0, double home_longitude = 0, double home_altitude = 0)
    : home_latitude_(home_latitude), home_longitude_(home_longitude)
  {
    // Save NED origin
    home_latitude_rad_ = deg2Rad(latitude);
    home_longitude_rad_ = deg2Rad(longitude);
    home_altitude_ = altitude;

    // Compute ECEF of NED origin
    geodetic2Ecef(latitude, longitude, altitude, &home_ecef_x_, &home_ecef_y_, &home_ecef_z_);

    // Compute ECEF to NED and NED to ECEF matrices
    double phiP = atan2(home_ecef_z_, sqrt(pow(home_ecef_x_, 2) + pow(home_ecef_y_, 2)));

    ecef_to_ned_matrix_ = nRe(phiP, home_longitude_rad_);
    ned_to_ecef_matrix_ = nRe(home_latitude_rad_, home_longitude_rad_).transpose();    
  }

  void getHome(double* latitude, double* longitude, double* altitude)
  {
    *latitude = home_latitude_;
    *longitude = home_longitude_;
    *altitude = home_altitude_;
  }

  void geodetic2Ecef(const double latitude, const double longitude, const double altitude, double* x,
                     double* y, double* z)
  {
    // Convert geodetic coordinates to ECEF.
    // http://code.google.com/p/pysatel/source/browse/trunk/coord.py?r=22
    double lat_rad = deg2Rad(latitude);
    double lon_rad = deg2Rad(longitude);
    double xi = sqrt(1 - kFirstEccentricitySquared * sin(lat_rad) * sin(lat_rad));
    *x = (kSemimajorAxis / xi + altitude) * cos(lat_rad) * cos(lon_rad);
    *y = (kSemimajorAxis / xi + altitude) * cos(lat_rad) * sin(lon_rad);
    *z = (kSemimajorAxis / xi * (1 - kFirstEccentricitySquared) + altitude) * sin(lat_rad);
  }

  void ecef2Geodetic(const double x, const double y, const double z, double* latitude,
                     double* longitude, double* altitude)
  {
    // Convert ECEF coordinates to geodetic coordinates.
    // J. Zhu, "Conversion of Earth-centered Earth-fixed coordinates
    // to geodetic coordinates," IEEE Transactions on Aerospace and
    // Electronic Systems, vol. 30, pp. 957-961, 1994.

    double r = sqrt(x * x + y * y);
    double Esq = kSemimajorAxis * kSemimajorAxis - kSemiminorAxis * kSemiminorAxis;
    double F = 54 * kSemiminorAxis * kSemiminorAxis * z * z;
    double G = r * r + (1 - kFirstEccentricitySquared) * z * z - kFirstEccentricitySquared * Esq;
    double C = (kFirstEccentricitySquared * kFirstEccentricitySquared * F * r * r) / pow(G, 3);
    double S = cbrt(1 + C + sqrt(C * C + 2 * C));
    double P = F / (3 * pow((S + 1 / S + 1), 2) * G * G);
    double Q = sqrt(1 + 2 * kFirstEccentricitySquared * kFirstEccentricitySquared * P);
    double r_0 = -(P * kFirstEccentricitySquared * r) / (1 + Q)
        + sqrt(
            0.5 * kSemimajorAxis * kSemimajorAxis * (1 + 1.0 / Q)
                - P * (1 - kFirstEccentricitySquared) * z * z / (Q * (1 + Q)) - 0.5 * P * r * r);
    double U = sqrt(pow((r - kFirstEccentricitySquared * r_0), 2) + z * z);
    double V = sqrt(
        pow((r - kFirstEccentricitySquared * r_0), 2) + (1 - kFirstEccentricitySquared) * z * z);
    double Z_0 = kSemiminorAxis * kSemiminorAxis * z / (kSemimajorAxis * V);
    *altitude = U * (1 - kSemiminorAxis * kSemiminorAxis / (kSemimajorAxis * V));
    *latitude = rad2Deg(atan((z + kSecondEccentricitySquared * Z_0) / r));
    *longitude = rad2Deg(atan2(y, x));
  }

  void ecef2Ned(const double x, const double y, const double z, double* north, double* east,
                double* down)
  {
    // Converts ECEF coordinate position into local-tangent-plane NED.
    // Coordinates relative to given ECEF coordinate frame.

    Vector3d vect, ret;
    vect(0) = x - home_ecef_x_;
    vect(1) = y - home_ecef_y_;
    vect(2) = z - home_ecef_z_;
    ret = ecef_to_ned_matrix_ * vect;
    *north = ret(0);
    *east = ret(1);
    *down = -ret(2);
  }

  void ned2Ecef(const double north, const double east, const double down, double* x, double* y,
                double* z)
  {
    // NED (north/east/down) to ECEF coordinates
    Vector3d ned, ret;
    ned(0) = north;
    ned(1) = east;
    ned(2) = -down;
    ret = ned_to_ecef_matrix_ * ned;
    *x = ret(0) + home_ecef_x_;
    *y = ret(1) + home_ecef_y_;
    *z = ret(2) + home_ecef_z_;
  }

  void geodetic2Ned(const double latitude, const double longitude, const double altitude,
                    double* north, double* east, double* down)
  {
    // Geodetic position to local NED frame
    double x, y, z;
    geodetic2Ecef(latitude, longitude, altitude, &x, &y, &z);
    ecef2Ned(x, y, z, north, east, down);
  }

  void ned2Geodetic(const double north, const double east, const double down, double* latitude,
                    double* longitude, double* altitude)
  {
    // Local NED position to geodetic coordinates
    double x, y, z;
    ned2Ecef(north, east, down, &x, &y, &z);
    ecef2Geodetic(x, y, z, latitude, longitude, altitude);
  }

  void geodetic2Enu(const double latitude, const double longitude, const double altitude,
                    double* east, double* north, double* up)
  {
    // Geodetic position to local ENU frame
    double x, y, z;
    geodetic2Ecef(latitude, longitude, altitude, &x, &y, &z);

    double aux_north, aux_east, aux_down;
    ecef2Ned(x, y, z, &aux_north, &aux_east, &aux_down);

    *east = aux_east;
    *north = aux_north;
    *up = -aux_down;
  }

  void enu2Geodetic(const double east, const double north, const double up, double* latitude,
                    double* longitude, double* altitude)
  {
    // Local ENU position to geodetic coordinates

    const double aux_north = north;
    const double aux_east = east;
    const double aux_down = -up;
    double x, y, z;
    ned2Ecef(aux_north, aux_east, aux_down, &x, &y, &z);
    ecef2Geodetic(x, y, z, latitude, longitude, altitude);
  }

private:
  // Geodetic system parameters
  static double kSemimajorAxis = 6378137;
  static double kSemiminorAxis = 6356752.3142;
  static double kFirstEccentricitySquared = 6.69437999014 * 0.001;
  static double kSecondEccentricitySquared = 6.73949674228 * 0.001;
  static double kFlattening = 1 / 298.257223563;

  typedef Eigen::Vector3d Vector3d;
  typedef Eigen::Matrix<double, 3, 3> Matrix3x3d;

  inline Matrix3x3d nRe(const double lat_radians, const double lon_radians)
  {
    const double sLat = sin(lat_radians);
    const double sLon = sin(lon_radians);
    const double cLat = cos(lat_radians);
    const double cLon = cos(lon_radians);

    Matrix3x3d ret;
    ret(0, 0) = -sLat * cLon;
    ret(0, 1) = -sLat * sLon;
    ret(0, 2) = cLat;
    ret(1, 0) = -sLon;
    ret(1, 1) = cLon;
    ret(1, 2) = 0.0;
    ret(2, 0) = cLat * cLon;
    ret(2, 1) = cLat * sLon;
    ret(2, 2) = sLat;

    return ret;
  }

  inline double rad2Deg(const double radians)
  {
    return (radians / M_PI) * 180.0;
  }

  inline double deg2Rad(const double degrees)
  {
    return (degrees / 180.0) * M_PI;
  }

  double home_latitude_rad_, home_latitude_;
  double home_longitude_rad_, home_longitude_;
  double home_altitude_;

  double home_ecef_x_;
  double home_ecef_y_;
  double home_ecef_z_;

  Matrix3x3d ecef_to_ned_matrix_;
  Matrix3x3d ned_to_ecef_matrix_;

}; // class GeodeticConverter

#endif
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文