ecef2geodetic#

ahrs.common.frames.ecef2geodetic(x: float, y: float, z: float, a: float = 6378137.0, b: float = 6356752.3142) ndarray#

Transform cartesian coordinates in ECEF-frame to Geodetic Coordinates [ZHP11].

Given the Cartesian coordinates \(\begin{pmatrix}x & y & z\end{pmatrix}\) in the Earth-Centered Earth-Fixed (ECEF) frame, we can start by computing the geodetic longitude \(\lambda\):

\[\lambda = \mathrm{arctan2}\left(x, \,y\right)\]

Then, we iteratively compute the geodetic latitude \(\phi\) using the initial estimation:

\[\phi_0 = \mathrm{arctan2}\big(z, \,(1-e^2)p \big)\]

with \(p = \sqrt{x^2 + y^2}\).

Now we iterate until the difference between two consecutive latitudes (\(\phi_i\) and \(\phi_{i-1}\)) is smaller than a given threshold \(\delta\). Each iteration updates the values as follows:

\[\begin{split}\begin{array}{rcl} N & \leftarrow & \frac{a}{\sqrt{1 - e^2 \sin^2(\phi_{i-1})}} \\ \phi_i & \leftarrow & \mathrm{arctan2}\big(z+e^2N\sin(\phi_{i-1}), \,p\big) \end{array}\end{split}\]

where \(N\) is the radius of curvature in the vertical prime, and \(e^2\) is the square of the first eccentricity of the ellipsoid.

\[e^2 = \frac{a^2-b^2}{a^2}\]

The value of \(\delta\) is empirically found to perform well when set to \(10^{-8}\) in this implementation.

The altitude (height) \(h\) is computed as:

\[h = \frac{p}{\cos\phi} - N\]

Note

The altitude \(h\) has an accuracy up to 0.1 m (10 cm), which is enough for most applications.

The latitude and longitude are returned in degrees. The altitude is returned in meters.

Parameters:
  • x (float) – ECEF x-coordinate, in meters.

  • y (float) – ECEF y-coordinate, in meters.

  • z (float) – ECEF z-coordinate, in meters.

  • a (float, default: 6378137.0) – Ellipsoid’s equatorial radius, in meters. Defaults to Earth’s.

  • b (float, default: 6356752.3142) – Ellipsoid’s polar radius, in meters. Defaults to Earth’s.

Returns:

lla – Geodetic coordinates [latitude, longitude, altitude].

Return type:

numpy.ndarray

Examples

>>> from ahrs.common.frames import ecef2geodetic
>>> x = 4_201_000
>>> y = 172_460
>>> z = 4_780_100
>>> ecef2geodetic(x, y, z)
array([48.85616162,  2.35079383, 67.37006803])