Skip to content

Commit 2222686

Browse files
ephemeris axes
1 parent 1eb0cd9 commit 2222686

File tree

5 files changed

+409
-18
lines changed

5 files changed

+409
-18
lines changed

ext/EphemeridesExt.jl

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,63 @@
1-
module EphemeridesExt
1+
module EphemeridesExt
22

3-
import FrameTransformations: add_point_ephemeris!
3+
import FrameTransformations: add_point_ephemeris!, add_axes_ephemeris!
44

5-
using FrameTransformations: FrameSystem,
6-
FramePointFunctions, Translation, add_point!,
7-
check_point_ephemeris
5+
using FrameTransformations: FrameSystem,
6+
FramePointFunctions, Translation, add_point!,
7+
FrameAxesFunctions, Rotation, add_axes!,
8+
check_point_ephemeris, check_axes_ephemeris,
9+
angles_to_rot3, angles_to_rot6, angles_to_rot9, angles_to_rot12
810

9-
using Ephemerides: EphemerisProvider,
10-
ephem_vector3, ephem_vector6, ephem_vector9, ephem_vector12
11+
using Ephemerides: EphemerisProvider,
12+
ephem_vector3, ephem_vector6, ephem_vector9, ephem_vector12,
13+
ephem_rotation3, ephem_rotation6, ephem_rotation9, ephem_rotation12
1114

1215

1316
"""
14-
add_point_ephemeris!(fr::FrameSystem{O, N}, eph::EphemerisProvider,
15-
name::Symbol, id::Int) where {O, N}
17+
add_point_ephemeris!(fr::FrameSystem{O, T}, eph::EphemerisProvider,
18+
name::Symbol, id::Int) where {O, T}
1619
1720
Add a point from `Ephemerides.jl` provider.
1821
"""
1922
function add_point_ephemeris!(
20-
fr::FrameSystem{O, N}, eph::EphemerisProvider, name::Symbol, id::Int
21-
) where {O, N}
23+
fr::FrameSystem{O,T}, eph::EphemerisProvider, name::Symbol, id::Int
24+
) where {O,T}
2225

2326
pid, axid = check_point_ephemeris(fr, eph, id)
2427

25-
funs = FramePointFunctions{O, N}(
26-
t -> Translation{O}( ephem_vector3(eph, pid, id, t) ),
27-
t -> Translation{O}( ephem_vector6(eph, pid, id, t) ),
28-
t -> Translation{O}( ephem_vector9(eph, pid, id, t) ),
29-
t -> Translation{O}( ephem_vector12(eph, pid, id, t) )
28+
funs = FramePointFunctions{O,T}(
29+
t -> Translation{O}(ephem_vector3(eph, pid, id, t)),
30+
t -> Translation{O}(ephem_vector6(eph, pid, id, t)),
31+
t -> Translation{O}(ephem_vector9(eph, pid, id, t)),
32+
t -> Translation{O}(ephem_vector12(eph, pid, id, t))
3033
)
31-
return add_point!(fr, name, id, axid, funs, pid)
34+
return add_point!(fr, name, id, axid, funs, pid)
35+
end
36+
37+
"""
38+
add_point_ephemeris!(fr::FrameSystem{O, T}, eph::EphemerisProvider,
39+
name::Symbol, id::Int) where {O, T}
40+
41+
Add a point from `Ephemerides.jl` provider.
42+
"""
43+
function add_point_ephemeris!(
44+
fr::FrameSystem{O,T}, eph::EphemerisProvider, name::Symbol, id::Int, rot_seq::Symbol
45+
) where {O,T}
46+
47+
# Check and retrieve the parent ID for the given axes
48+
pid = check_axes_ephemeris(frames, eph, id)
49+
50+
if rot_seq in (:ZYX, :XYX, :XYZ, :XZX, :XZY, :YXY, :YXZ, :YZX, :YZY, :ZXY, :ZXZ, :ZYZ)
51+
funs = FrameAxesFunctions{O,T}(
52+
t -> Rotation{O}(angles_to_rot3(ephem_rotation3(eph, pid, id, t), rot_seq)),
53+
t -> Rotation{O}(angles_to_rot6(ephem_rotation6(eph, pid, id, t), rot_seq)),
54+
t -> Rotation{O}(angles_to_rot9(ephem_rotation9(eph, pid, id, t), rot_seq)),
55+
t -> Rotation{O}(angles_to_rot12(ephem_rotation12(eph, pid, id, t), rot_seq))
56+
)
57+
else
58+
throw(ArgumentError("The rotation sequence :$rot_seq is not valid."))
59+
end
60+
return add_axes!(fr, name, id, axid, funs, pid)
3261
end
3362

3463
end

src/Definitions/ephemeris.jl

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@ The point is identifies by the `id` and a have a user defined `name`.
1414
::FrameSystem{O,T}, ::AbstractEphemerisProvider, ::Symbol, ::Int
1515
) where {O,T} end
1616

17+
"""
18+
add_axes_ephemeris!(frames::FrameSystem{O, T}, eph::AbstractEphemerisProvider,
19+
name::Symbol, id::Int, seq::Symbol, class::Int) where {O, T}
20+
21+
Add axes coming from an `AbstractEphemerisProvider` subtype to `frames`.
22+
The axes are identifies by the `id` and a have a user defined `name`. The rotation matrix
23+
is build using the rotation sequence specified in `seq`. The axes type is specified by `class`.
24+
25+
!!! warning
26+
This is an interface only, concrete subtypes of `AbstractEphemerisProvider` requires
27+
an proper implementation.
28+
"""
29+
@interface function add_axes_ephemeris!(
30+
::FrameSystem{O,T}, ::AbstractEphemerisProvider, ::Symbol, ::Int, ::Symbol, ::Int
31+
) where {O,T} end
32+
1733
"""
1834
add_point_ephemeris!(fr, eph::AbstractEphemerisProvider, book::Dict{Int, Symbol})
1935
@@ -125,3 +141,79 @@ function check_point_ephemeris(
125141

126142
return parentid, axesid
127143
end
144+
145+
function check_axes_ephemeris(
146+
frames::FrameSystem{O,N}, eph::AbstractEphemerisProvider, id::Int
147+
) where {O,N}
148+
149+
# Check that the kernels contain orientation data for the given axes ID
150+
if !(id in ephem_available_axes(eph))
151+
throw(
152+
ArgumentError(
153+
"Orientation data for AXESID $id is not available " *
154+
"in the kernels loaded in the given FrameSystem.",
155+
),
156+
)
157+
end
158+
159+
# Retrieve the parent from the ephemeris data
160+
orient_records = ephem_orient_records(eph)
161+
parentid = nothing
162+
163+
for or in orient_records
164+
if or.target == id
165+
if isnothing(parentid)
166+
parentid = or.axes
167+
elseif parentid != or.axes
168+
throw(
169+
ErrorException(
170+
"UnambiguityError: at least two set of orientation data " *
171+
"with different centers are available for axes with ID $id.",
172+
),
173+
)
174+
end
175+
end
176+
end
177+
178+
# Check that the default parent is available in the FrameSystem!
179+
if !has_axes(frames, parentid)
180+
throw(
181+
ArgumentError(
182+
"Orientation data for axes with ID $id is available " *
183+
"with respect to axes with ID $parentid, which has not yet been defined " *
184+
"in the given FrameSystem.",
185+
),
186+
)
187+
end
188+
189+
return parentid
190+
end
191+
192+
# Functions for an easier definition\handling of ephemeris axes
193+
@inline function angles_to_rot3(θ, seq::Symbol)
194+
@inbounds angle_to_dcm(θ[1], θ[2], θ[3], seq)
195+
end
196+
197+
@inline function angles_to_rot6(θ, seq::Symbol)
198+
return (
199+
angle_to_dcm(θ[1], θ[2], θ[3], seq),
200+
angle_to_δdcm(θ[1], θ[2], θ[3], seq)
201+
)
202+
end
203+
204+
@inline function angles_to_rot9(θ, seq::Symbol)
205+
return (
206+
angle_to_dcm(θ[1], θ[2], θ[3], seq),
207+
angle_to_δdcm(θ[1], θ[2], θ[3], seq),
208+
angle_to_δ²dcm(θ[1], θ[2], θ[3], seq)
209+
)
210+
end
211+
212+
@inline function angles_to_rot12(θ, seq::Symbol)
213+
return (
214+
angle_to_dcm(θ[1], θ[2], θ[3], seq),
215+
angle_to_δdcm(θ[1], θ[2], θ[3], seq),
216+
angle_to_δ²dcm(θ[1], θ[2], θ[3], seq),
217+
angle_to_δ³dcm(θ[1], θ[2], θ[3], seq)
218+
)
219+
end

src/Definitions/lunar.jl

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
"""
2+
DCM_MOON_PA440_TO_ME421
3+
4+
DCM for the rotation from the Moon Principal Axis 440 (PA440) to the Moon Mean
5+
Earth/Mean Rotation DE421 (ME421) axes.
6+
7+
### References
8+
- Park, S. R. et al. (2021), _The JPL Planetary and Lunar Ephemerides DE440 and DE441_,
9+
[DOI: 10.3847/1538-3881/abd414](https://doi.org/10.3847/1538-3881/abd414)
10+
11+
"""
12+
const DCM_MOON_PA440_TO_ME421 = angle_to_dcm(
13+
arcsec2rad(-67.8526), arcsec2rad(-78.6944), arcsec2rad(-0.2785), :ZYX
14+
)
15+
16+
"""
17+
DCM_MOON_PA430_TO_ME430
18+
19+
DCM for the rotation from the Moon Principal Axis 430 (PA430) to the Moon Mean
20+
Earth/Mean Rotation DE430 (ME430) axes.
21+
22+
### References
23+
- Folkner M. William et al. (2014), _The Planetary and Lunar EphemeridesDE430 and DE431_
24+
25+
- J. G. Williams et al. (2013), _DE430 Lunar Orbit, Physical Librations, and Surface Coordinates_,
26+
[DE430 Lunar Ephemeris and Orientation](https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de430_moon_coord.pdf)
27+
28+
"""
29+
const DCM_MOON_PA430_TO_ME430 = angle_to_dcm(
30+
arcsec2rad(-67.573), arcsec2rad(-78.58), arcsec2rad(-0.285), :ZYX
31+
)
32+
33+
"""
34+
DCM_MOON_PA430_TO_ME421
35+
36+
DCM for the rotation from the Moon Principal Axis 430 (PA430) to the Moon Mean
37+
Earth/Mean Rotation DE421 (ME421) axes.
38+
39+
### References
40+
- Folkner M. William et al. (2014), _The Planetary and Lunar EphemeridesDE430 and DE431_
41+
42+
- J. G. Williams et al. (2013), _DE430 Lunar Orbit, Physical Librations, and Surface Coordinates_,
43+
[DE430 Lunar Ephemeris and Orientation](https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de430_moon_coord.pdf)
44+
45+
"""
46+
const DCM_MOON_PA430_TO_ME421 = angle_to_dcm(
47+
arcsec2rad(-67.737), arcsec2rad(-78.627), arcsec2rad(-0.295), :ZYX
48+
)
49+
50+
"""
51+
DCM_MOON_PA421_TO_ME421
52+
53+
DCM for the rotation from the Moon Principal Axis 421 (PA421) to the Moon Mean
54+
Earth/Mean Rotation DE421 (ME421) axes.
55+
56+
### References
57+
- J. G. Williams et al. (2008), _DE421 Lunar Orbit, Physical Librations, and Surface Coordinates_,
58+
[DE421 Lunar Ephemeris and Orientation](https://naif.jpl.nasa.gov/pub/naif/generic_kernels/fk/satellites/de421_lunar_ephemeris_and_orientation.pdf)
59+
60+
"""
61+
const DCM_MOON_PA421_TO_ME421 = angle_to_dcm(
62+
arcsec2rad(-67.92), arcsec2rad(-78.56), arcsec2rad(-0.3), :ZYX
63+
)
64+
65+
"""
66+
add_axes_pa440!(frames, eph::AbstractEphemerisProvider, name::Symbol,
67+
id::Int=AXESID_MOONPA_DE440)
68+
69+
Add DE440 Moon's Principal Axes (PA) axes to `frames`. The libration angles are extracted
70+
from the `eph` ephemeris kernels, an error is thrown if such orientation data is not available.
71+
72+
!!! warning
73+
The parent axes are automatically set to the ICRF (ID = $(AXESID_ICRF)). If such
74+
axes are not registered in the frame system, an error is thrown.
75+
76+
!!! warning
77+
To properly read the ephemeris kernels, the ID associated to the input `axes` must match
78+
NAIF's FRAME ID for the Moon PA DE440 axes ($(AXESID_MOONPA_DE440)).
79+
"""
80+
function add_axes_pa440!(
81+
frames::FrameSystem, eph::AbstractEphemerisProvider, name::Symbol,
82+
id::Int=AXESID_MOONPA_DE440
83+
)
84+
if !(has_axes(frames, AXESID_ICRF))
85+
throw(
86+
ErrorException(
87+
"The DE440 Moon Principal Axes (PA) can only be defined w.r.t. the" *
88+
" ICRF (ID = $(AXESID_ICRF)), which is not defined" *
89+
" in the current frames graph."
90+
)
91+
)
92+
end
93+
94+
# Throw a warning if the ID does not match the standard one.
95+
if id != AXESID_MOONPA_DE440
96+
throw(
97+
ArgumentError(
98+
"$name is aliasing an ID that is not the standard PA440" *
99+
" ID ($(AXESID_MOONPA_DE440))."
100+
)
101+
)
102+
end
103+
104+
return add_axes_ephemeris!(frames, eph, name, id, :ZXZ)
105+
end
106+
107+
"""
108+
add_axes_pa421!(frames, eph::AbstractEphemerisProvider, name::Symbol,
109+
id::Int=AXESID_MOONPA_DE421)
110+
111+
Add DE421 Moon's Principal Axes (PA) axes to `frames`. The libration angles are extracted
112+
from the `eph` ephemeris kernels, an error is thrown if such orientation data is not available.
113+
114+
!!! warning
115+
The parent axes are automatically set to the ICRF (ID = $(AXESID_ICRF)). If such
116+
axes are not registered in the frame system, an error is thrown.
117+
118+
!!! warning
119+
To properly read the ephemeris kernels, the ID associated to the input `axes` must match
120+
NAIF's FRAME ID for the Moon PA DE421 axes ($(AXESID_MOONPA_DE421)).
121+
"""
122+
function add_axes_pa421!(
123+
frames::FrameSystem, eph::AbstractEphemerisProvider, name::Symbol,
124+
id::Int=AXESID_MOONPA_DE421
125+
)
126+
if !(has_axes(frames, AXESID_ICRF))
127+
throw(
128+
ErrorException(
129+
"The DE421 Moon Principal Axes (PA) can only be defined w.r.t. the" *
130+
" ICRF (ID = $(AXESID_ICRF)), which is not defined" *
131+
" in the current frames graph."
132+
)
133+
)
134+
end
135+
136+
# Throw a warning if the ID does not match the standard one.
137+
if id != AXESID_MOONPA_DE421
138+
throw(
139+
ArgumentError(
140+
"$name is aliasing an ID that is not the standard PA421" *
141+
" ID ($(AXESID_MOONPA_DE421))."
142+
)
143+
)
144+
end
145+
146+
return add_axes_ephemeris!(frames, eph, name, id, :ZXZ)
147+
end
148+
149+
"""
150+
add_axes_me421!(frames, name::Symbol, parentid::Int, axesid::Int=AXESID_MOONME_DE421)
151+
152+
Add DE421 Moon's Mean Earth/Mean Rotation (ME) axes to `frames`.
153+
154+
!!! warning
155+
The `parent` set of axes must either the DE440 Principal Axes (PA440, ID =
156+
$(AXESID_MOONPA_DE440)) or the DE421 Principal Axes (PA421, ID =
157+
$(AXESID_MOONPA_DE421)), otherwise an error is thrown. Depending on that, the
158+
relative axes orientation will be automatically selected by this function.
159+
"""
160+
function add_axes_me421!(
161+
frames::FrameSystem, name::Symbol, parent, id::Int=AXESID_MOONME_DE421
162+
)
163+
pid = axes_id(frames, parent)
164+
if pid == AXESID_MOONPA_DE421
165+
dcm = DCM_MOON_PA421_TO_ME421
166+
167+
elseif pid == AXESID_MOONPA_DE440
168+
dcm = DCM_MOON_PA440_TO_ME421
169+
170+
else
171+
172+
throw(
173+
ArgumentError(
174+
"The DE421 Mean Earth/Mean Rotation (ME) axes cannot be defined w.r.t." *
175+
" axes with ID $pid. Only the DE440 (ID = $(AXESID_MOONPA_DE440))" *
176+
" or DE421 (ID = $(AXESID_MOONPA_DE421)) Moon Principal Axes are" *
177+
" accepted as parent axes.",
178+
),
179+
)
180+
end
181+
182+
if id != AXESID_MOONME_DE421
183+
@warn "$(name) is aliasing an ID that is not the standard ME421" *
184+
"ID ($(AXESID_MOONME_DE421))."
185+
end
186+
187+
return add_axes_fixedoffset!(frames, name, id, pid, dcm)
188+
end

0 commit comments

Comments
 (0)