Skip to content

Commit 890bf20

Browse files
Merge pull request #63 from JuliaSpaceMissionDesign/dev
v2.1.1
2 parents 1c263d3 + 79e009f commit 890bf20

File tree

8 files changed

+255
-6
lines changed

8 files changed

+255
-6
lines changed

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "FrameTransformations"
22
uuid = "5be70612-1674-42c4-a038-c376b6dc81ed"
33
authors = ["JSMD Team"]
4-
version = "2.1.0"
4+
version = "2.1.1"
55

66
[deps]
77
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
@@ -32,7 +32,7 @@ ForwardDiff = "0.10"
3232
FunctionWrappers = "1"
3333
FunctionWrappersWrappers = "0.1"
3434
IERSConventions = "1"
35-
JSMDInterfaces = "1.5"
35+
JSMDInterfaces = "1.6"
3636
JSMDUtils = "1"
3737
PrecompileTools = "1"
3838
ReferenceFrameRotations = "3"
@@ -45,4 +45,4 @@ julia = "1.9"
4545
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
4646

4747
[targets]
48-
test = ["Test"]
48+
test = ["Test"]

docs/src/API/axes_api.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ add_axes_inertial!
1010
add_axes_rotating!
1111
add_axes_fixedoffset!
1212
add_axes_alias!
13+
add_axes_frozen!
14+
add_axes_ephemeris!
1315
```
1416

1517
## Celestial
@@ -39,6 +41,13 @@ add_axes_gtod!
3941
add_axes_pef!
4042
```
4143

44+
## Planetary
45+
46+
```@docs
47+
add_axes_bci2000!
48+
add_axes_bcrtod!
49+
```
50+
4251
## Lunar
4352

4453
```@docs
@@ -57,7 +66,6 @@ add_axes_topocentric!
5766

5867
```@docs
5968
add_axes_twovectors!
60-
add_axes_ephemeris!
6169
```
6270

6371
## Utils

src/Definitions/frozen.jl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
"""
3+
add_axes_frozen!(frames, name, id, frozen, e)
4+
5+
Create a frozen axes version of `frozen` at epoch `e`, with `name` and `id` and add
6+
it to `frames`.
7+
8+
!!! warning
9+
The parent axes are automatically assigned to the `frozen` parent.
10+
"""
11+
function add_axes_frozen!(
12+
frames::FrameSystem{O, N, S}, name::Symbol, id::Int, frozen, epoch::Epoch{S2}
13+
) where {O, N, S, S2}
14+
15+
eS = convert(S(), epoch)
16+
fixid = axes_id(frames, frozen)
17+
18+
if !(has_axes(frames, fixid))
19+
throw(
20+
ErrorException(
21+
"no axes with ID $frozen is registered in the given frame system"
22+
)
23+
)
24+
end
25+
26+
mid = get_mappedid(axes_graph(frames), fixid)
27+
@show node = get_mappednode(axes_graph(frames), mid)
28+
parid = node.parentid
29+
30+
# Compute rotation
31+
dcm = rotation3(frames, parid, fixid, j2000s(eS))[1]
32+
33+
# Create new axes
34+
return add_axes_fixedoffset!(frames, name, id, parid, dcm)
35+
end

src/Definitions/planetary.jl

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
2+
"""
3+
add_axes_bcrtod!(frames, name, id, center; deriv=true)
4+
5+
Add Body-Centered Rotating (BCR), True-of-Date (TOD) axes with `name` and `id` to `frames`.
6+
The center point (i.e., the reference body) is `center`.
7+
8+
These axes are the equivalent of SPICE's `IAU_<BODY_NAME>` frames.
9+
10+
!!! warning
11+
The parent axes are automatically set to the ICRF (ID = $(AXESID_ICRF)). If the
12+
ICRF is not defined in `frames`, an error is thrown.
13+
14+
### See also
15+
See also [`add_axes_rotating!`](@ref), [`add_axes_bci2000!`](@ref).
16+
"""
17+
function add_axes_bcrtod!(
18+
frames::FrameSystem, name::Symbol, id::Int, center; deriv::Bool=false
19+
)
20+
# create val dispatch
21+
cid = point_id(frames, center)
22+
vid = Val(cid)
23+
24+
if length( methods(body_rotational_elements, [Number, Val{cid}]) ) != 1
25+
throw(
26+
MethodError(
27+
body_rotational_elements,
28+
"there must be a unique method defined for $cid"
29+
)
30+
)
31+
end
32+
33+
if !(has_axes(frames, AXESID_ICRF))
34+
throw(
35+
ErrorException(
36+
"Body-Centered Inertial (BCI) at J2000 axes can only be defined" *
37+
" w.r.t. the ICRF (ID = $(AXESID_ICRF)), which is not defined in" *
38+
" the current frames graph."
39+
)
40+
)
41+
end
42+
43+
if !deriv
44+
add_axes_rotating!(frames, name, id, AXESID_ICRF, t->_bcrtod(t, vid))
45+
else
46+
add_axes_rotating!(
47+
frames, name, id, AXESID_ICRF,
48+
t->_bcrtod(t, vid), t->_∂bcrtod(t, vid), t->_∂²bcrtod(t, vid), t->_∂³bcrtod(t, vid)
49+
)
50+
end
51+
end
52+
53+
"""
54+
add_axes_bci2000!(frames, axes::AbstractFrameAxes, center, data)
55+
56+
Add Body-Centered Inertial (BCI) axes at J2000 with `name` and `id` to `frames`.
57+
The center point (i.e., the reference body) is `center`.
58+
59+
!!! warning
60+
The parent axes are automatically set to the ICRF (ID = $(AXESID_ICRF)). If the
61+
ICRF is not defined in `frames`, an error is thrown.
62+
63+
### See also
64+
See also [`add_axes_fixedoffset!`](@ref), [`add_axes_bcrtod!`](@ref).
65+
"""
66+
function add_axes_bci2000!(frames::FrameSystem, name::Symbol, id::Int, center)
67+
68+
# create val dispatch
69+
cid = point_id(frames, center)
70+
vid = Val(cid)
71+
72+
if length( methods(body_rotational_elements, [Number, Val{cid}]) ) != 1
73+
throw(
74+
ErrorException(
75+
"there must be a unique method defined for $cid"
76+
)
77+
)
78+
end
79+
80+
if !(has_axes(frames, AXESID_ICRF))
81+
throw(
82+
ErrorException(
83+
"Body-Centered Inertial (BCI) at J2000 axes can only be defined" *
84+
" w.r.t. the ICRF (ID = $(AXESID_ICRF)), which is not defined in" *
85+
" the current frames graph."
86+
)
87+
)
88+
end
89+
90+
# evaluate rotational elements and build the DCM
91+
α2000, δ2000, _ = body_rotational_elements(0, vid)
92+
dcm = angle_to_dcm/2 + α2000, π/2 - δ2000, :ZX)
93+
94+
# insert the new axes
95+
return add_axes_fixedoffset!(frames, name, id, AXESID_ICRF, dcm)
96+
97+
end
98+
99+
function _bcrtod(seconds, val)
100+
α, δ, w = body_rotational_elements(seconds / CENTURY2SEC, val)
101+
return angle_to_dcm/2 + α, π/2 - δ, w, :ZXZ)
102+
end
103+
104+
function _∂bcrtod(seconds, val)
105+
T = seconds / CENTURY2SEC
106+
α, δ, w = body_rotational_elements(T, val)
107+
dα, dδ, dw = ∂body_rotational_elements(T, val)
108+
109+
R = angle_to_dcm/2 + α, π/2 - δ, w, :ZXZ)
110+
dR = angle_to_δdcm( (π/2 + α, dα), (π/2 - δ, -dδ), (w, dw), :ZXZ)
111+
return R, dR
112+
end
113+
114+
function _∂²bcrtod(seconds, val)
115+
T = seconds / CENTURY2SEC
116+
α, δ, w = body_rotational_elements(T, val)
117+
dα, dδ, dw = ∂body_rotational_elements(T, val)
118+
d²α, d²δ, d²w = ∂²body_rotational_elements(T, val)
119+
120+
R = angle_to_dcm( π/2 + α, π/2 - δ, w, :ZXZ )
121+
dR = angle_to_δdcm( (π/2 + α, dα), (π/2 - δ, -dδ), (w, dw), :ZXZ )
122+
d²R = angle_to_δ²dcm( (π/2 + α, dα, d²α), (π/2 - δ, -dδ, -d²δ), (w, dw, d²w), :ZXZ)
123+
return R, dR, d²R
124+
end
125+
126+
function _∂³bcrtod(seconds, val)
127+
T = seconds / CENTURY2SEC
128+
α, δ, w = body_rotational_elements(T, val)
129+
dα, dδ, dw = ∂body_rotational_elements(T, val)
130+
d²α, d²δ, d²w = ∂²body_rotational_elements(T, val)
131+
d³α, d³δ, d³w = ∂³body_rotational_elements(T, val)
132+
133+
R = angle_to_dcm( π/2 + α, π/2 - δ, w, :ZXZ )
134+
dR = angle_to_δdcm( (π/2 + α, dα), (π/2 - δ, -dδ), (w, dw), :ZXZ )
135+
d²R = angle_to_δ²dcm( (π/2 + α, dα, d²α), (π/2 - δ, -dδ, -d²δ), (w, dw, d²w), :ZXZ)
136+
d³R = angle_to_δ³dcm( (π/2 + α, dα, d²α, d³α), (π/2 - δ, -dδ, -d²δ, -d³δ), (w, dw, d²w, d³w), :ZXZ)
137+
return R, dR, d²R, d³R
138+
end

src/FrameTransformations.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,20 @@ using JSMDUtils.Math: D¹, D², D³,
1515
arcsec2rad,
1616
unitvec, δunitvec, δ²unitvec, δ³unitvec,
1717
cross3, cross6, cross9, cross12,
18-
_3angles_to_δdcm, _3angles_to_δ²dcm, _3angles_to_δ³dcm
18+
_3angles_to_δdcm, _3angles_to_δ²dcm, _3angles_to_δ³dcm,
19+
angle_to_δdcm, angle_to_δ²dcm, angle_to_δ³dcm
1920

2021
using JSMDInterfaces.Graph: AbstractJSMDGraphNode, add_edge!, add_vertex!, get_path, has_vertex
2122

2223
using JSMDInterfaces.Ephemeris: AbstractEphemerisProvider,
2324
ephem_position_records, ephem_available_points,
2425
ephem_orient_records, ephem_available_axes
26+
2527
using JSMDInterfaces.Interface: @interface
2628

29+
using JSMDInterfaces.Bodies: body_rotational_elements, ∂body_rotational_elements,
30+
∂²body_rotational_elements, ∂³body_rotational_elements
31+
2732
using IERSConventions: iers_bias, iers_obliquity,
2833
iers_rot3_gcrf_to_itrf, iers_rot6_gcrf_to_itrf,
2934
iers_rot9_gcrf_to_itrf, iers_rot12_gcrf_to_itrf,
@@ -36,7 +41,7 @@ using SMDGraphs: MappedNodeGraph, SimpleGraph, MappedGraph,
3641

3742
import SMDGraphs: get_node_id
3843

39-
using Tempo: AbstractTimeScale, Epoch, j2000s, BarycentricDynamicalTime
44+
using Tempo: AbstractTimeScale, Epoch, j2000s, BarycentricDynamicalTime, CENTURY2SEC
4045

4146
# Core Routines
4247
# ==============================================
@@ -81,6 +86,10 @@ export AXESID_ICRF, AXESID_GCRF,
8186

8287
include("Definitions/index.jl")
8388

89+
export add_axes_frozen!
90+
91+
include("Definitions/frozen.jl")
92+
8493
export add_point_ephemeris!, add_axes_ephemeris!
8594

8695
include("Definitions/ephemeris.jl")
@@ -95,6 +104,10 @@ export add_axes_itrf!, add_axes_cirf!, add_axes_tirf!,
95104

96105
include("Definitions/terrestrial.jl")
97106

107+
export add_axes_bci2000!, add_axes_bcrtod!
108+
109+
include("Definitions/planetary.jl")
110+
98111
export add_axes_pa440!, add_axes_pa421!, add_axes_me421!
99112

100113
include("Definitions/lunar.jl")

test/Definitions/Definitions.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ end;
2323
download(KERNELS; verbose=true, force=false)
2424

2525
@testset "Definitions" verbose=true begin
26+
@safetestset "Frozen" begin include("frozen.jl") end
2627
@safetestset "Ephemeris" begin include("ephemeris.jl") end
2728
@safetestset "Celestial" begin include("celestial.jl") end
2829
@safetestset "Ecliptic" begin include("ecliptic.jl") end
30+
@safetestset "Planetary" begin include("planetary.jl") end
2931
end;

test/Definitions/frozen.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using FrameTransformations
2+
using ReferenceFrameRotations
3+
using LinearAlgebra
4+
using Tempo
5+
using Test
6+
7+
frames = FrameSystem{4, Float64}()
8+
add_axes_icrf!(frames)
9+
add_axes_mod!(frames, :MOD, 399)
10+
11+
e = Epoch("2022-01-01T12:00:00.0000 UTC")
12+
@test_nowarn add_axes_frozen!(frames, :FROZEN, -399, 399, e)
13+
14+
eTDB = convert(TDB, e)
15+
R0 = rotation3(frames, :ICRF, :MOD, eTDB)
16+
R = rotation3(frames, :ICRF, :FROZEN, eTDB)
17+
18+
@test R == R0
19+
20+
R = rotation12(frames, :ICRF, :FROZEN, eTDB)
21+
22+
@test R[2] DCM(0.0I)
23+
@test R[3] DCM(0.0I)
24+
@test R[4] DCM(0.0I)

test/Definitions/planetary.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using FrameTransformations
2+
using ReferenceFrameRotations
3+
using LinearAlgebra
4+
using JSMDInterfaces.Bodies
5+
using Test
6+
7+
function Bodies.body_rotational_elements(::Number, ::Val{-1})
8+
return -pi/2, pi/2, 0.0
9+
end
10+
11+
frames = FrameSystem{4, Float64}()
12+
add_axes_icrf!(frames)
13+
@test_nowarn add_axes_bci2000!(frames, :BCI, -1, -1)
14+
15+
R = rotation12(frames, :ICRF, :BCI, 12.345)
16+
17+
@test R[1] DCM(1.0I)
18+
@test R[2] DCM(0.0I)
19+
@test R[3] DCM(0.0I)
20+
@test R[4] DCM(0.0I)
21+
22+
@test_nowarn add_axes_bcrtod!(frames, :BCR, -2, -1; deriv=false)
23+
24+
R = rotation12(frames, :ICRF, :BCR, 12.345)
25+
26+
@test R[1] DCM(1.0I)
27+
@test R[2] DCM(0.0I)
28+
@test R[3] DCM(0.0I)
29+
@test R[4] DCM(0.0I)

0 commit comments

Comments
 (0)