Skip to content

Commit

Permalink
✨ Add function geocentric_to_ecef
Browse files Browse the repository at this point in the history
  • Loading branch information
ronisbr committed Jul 6, 2023
1 parent 1761aa7 commit bdf4191
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 3 deletions.
33 changes: 30 additions & 3 deletions src/reference_frames/geodetic_geocentric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

export ecef_to_geocentric
export ecef_to_geocentric, geocentric_to_ecef
export ecef_to_geodetic, geodetic_to_ecef
export geocentric_to_geodetic, geodetic_to_geocentric

Expand All @@ -37,8 +37,8 @@ center).
# Returns
- `float(T)`: Geocentric latitude [rad].
- `float(T)`: Longitude [rad].
- `float(T)`: Geocentric latitude [rad] ∈ [-π / 2, π / 2].
- `float(T)`: Longitude [rad] ∈ [-π , π].
- `float(T)`: Distance from Earth's center [m].
"""
function ecef_to_geocentric(r_e::AbstractVector)
Expand All @@ -50,6 +50,7 @@ function ecef_to_geocentric(r_e::AbstractVector)
z = T(r_e[3])
= x^2
= y^2
= z^2

lat = atan(z, (x² + y²))
lon = atan(y, x)
Expand All @@ -58,6 +59,32 @@ function ecef_to_geocentric(r_e::AbstractVector)
return lat, lon, r
end

"""
geocentric_to_ecef(lat::T1, lon::T2, r::T3) where {T1<:Number, T2<:Number, T3<:Number} -> SVector{3, T}
Convert the geocentric coordinates (latitude `lat` [rad], longitude `lon` [rad], and
distance from Earth's center `r` [m]) into a Earth-Centered, Earth-Fixed vector [m].
!!! note
The output type `T` is obtained by promoting the input types `T1`, `T2`, and `T3` to
float.
"""
function geocentric_to_ecef(lat::T1, lon::T2, r::T3) where {T1<:Number, T2<:Number, T3<:Number}
T = promote_type(T1, T2, T3) |> float

# Compute the vector at Earth's center that points to the desired geocentric point.
sin_lon, cos_lon = sincos(lon)
sin_lat, cos_lat = sincos(lat)

r_ecef = SVector{3, T}(
r * cos_lat * cos_lon,
r * cos_lat * sin_lon,
r * sin_lat
)

return r_ecef
end

"""
ecef_to_geodetic(r_e::AbstractVector; ellipsoid::Ellipsoid{T} = WGS84_ELLIPSOID) where T<:Number -> NTuple{3, T}
Expand Down
154 changes: 154 additions & 0 deletions test/reference_frames/geodetic_geocentric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,160 @@
# File: ./src/reference_frames/geodetic_geocentric.jl
# ==========================================================================================

# Function: ecef_to_geocentric
# ------------------------------------------------------------------------------------------

@testset "Function ecef_to_geocentric" begin
for T in (Float64, Float32)
R₀ = T(7000e3)

lat, lon, r = ecef_to_geocentric([R₀, 0, R₀])
@test lat deg2rad(45)
@test lon deg2rad(0)
@test r 2 * R₀
@test typeof(lat) === T
@test typeof(lon) === T
@test typeof(r) === T

lat, lon, r = ecef_to_geocentric([R₀, 0, -R₀])
@test lat deg2rad(-45)
@test lon deg2rad(0)
@test r 2 * R₀
@test typeof(lat) === T
@test typeof(lon) === T
@test typeof(r) === T

lat, lon, r = ecef_to_geocentric([-R₀, 0, R₀])
@test lat deg2rad(45)
@test lon deg2rad(180)
@test r 2 * R₀
@test typeof(lat) === T
@test typeof(lon) === T
@test typeof(r) === T

lat, lon, r = ecef_to_geocentric([-R₀, 0, -R₀])
@test lat deg2rad(-45)
@test lon deg2rad(180)
@test r 2 * R₀
@test typeof(lat) === T
@test typeof(lon) === T
@test typeof(r) === T

lat, lon, r = ecef_to_geocentric([R₀, R₀, 0])
@test lat deg2rad(0)
@test lon deg2rad(45)
@test r 2 * R₀
@test typeof(lat) === T
@test typeof(lon) === T
@test typeof(r) === T

lat, lon, r = ecef_to_geocentric([-R₀, R₀, 0])
@test lat deg2rad(0)
@test lon deg2rad(135)
@test r 2 * R₀
@test typeof(lat) === T
@test typeof(lon) === T
@test typeof(r) === T

lat, lon, r = ecef_to_geocentric([-R₀, -R₀, 0])
@test lat deg2rad(0)
@test lon deg2rad(-135)
@test r 2 * R₀
@test typeof(lat) === T
@test typeof(lon) === T
@test typeof(r) === T

lat, lon, r = ecef_to_geocentric([R₀, -R₀, 0])
@test lat deg2rad(0)
@test lon deg2rad(-45)
@test r 2 * R₀
@test typeof(lat) === T
@test typeof(lon) === T
@test typeof(r) === T
end
end

# Function: geocentric_to_ecef
# ------------------------------------------------------------------------------------------

@testset "Function ecef_to_geocentric" begin
for T in (Float64, Float32)
R₀ = T(7000e3)

lat = deg2rad(T(45))
lon = deg2rad(T(0))
r = T(R₀ * 2)
R = geocentric_to_ecef(lat, lon, r)
@test R[1] R₀
@test R[2] 0
@test R[3] R₀
@test eltype(R) === T

lat = deg2rad(T(-45))
lon = deg2rad(T(0))
r = T(R₀ * 2)
R = geocentric_to_ecef(lat, lon, r)
@test R[1] R₀
@test R[2] 0
@test R[3] -R₀
@test eltype(R) === T

lat = deg2rad(T(45))
lon = deg2rad(T(180))
r = T(R₀ * 2)
R = geocentric_to_ecef(lat, lon, r)
@test R[1] -R₀
@test R[2] 0 atol = (T == Float64 ? 1e-9 : 1)
@test R[3] R₀
@test eltype(R) === T

lat = deg2rad(T(-45))
lon = deg2rad(T(180))
r = T(R₀ * 2)
R = geocentric_to_ecef(lat, lon, r)
@test R[1] -R₀
@test R[2] 0 atol = (T == Float64 ? 1e-9 : 1)
@test R[3] -R₀
@test eltype(R) === T

lat = deg2rad(T(0))
lon = deg2rad(T(45))
r = T(R₀ * 2)
R = geocentric_to_ecef(lat, lon, r)
@test R[1] R₀
@test R[2] R₀
@test R[3] 0
@test eltype(R) === T

lat = deg2rad(T(0))
lon = deg2rad(T(135))
r = T(R₀ * 2)
R = geocentric_to_ecef(lat, lon, r)
@test R[1] -R₀
@test R[2] R₀
@test R[3] 0
@test eltype(R) === T

lat = deg2rad(T(0))
lon = deg2rad(T(-135))
r = T(R₀ * 2)
R = geocentric_to_ecef(lat, lon, r)
@test R[1] -R₀
@test R[2] -R₀
@test R[3] 0
@test eltype(R) === T

lat = deg2rad(T(0))
lon = deg2rad(T(-45))
r = T(R₀ * 2)
R = geocentric_to_ecef(lat, lon, r)
@test R[1] R₀
@test R[2] -R₀
@test R[3] 0
@test eltype(R) === T
end
end

# Function: ecef_to_geodetic
# ------------------------------------------------------------------------------------------

Expand Down

0 comments on commit bdf4191

Please sign in to comment.