1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.frames;
18
19 import java.io.Serializable;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.hipparchus.Field;
24 import org.hipparchus.CalculusFieldElement;
25 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
26 import org.hipparchus.geometry.euclidean.threed.Rotation;
27 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
28 import org.hipparchus.geometry.euclidean.threed.RotationOrder;
29 import org.hipparchus.geometry.euclidean.threed.Vector3D;
30 import org.orekit.annotation.DefaultDataContext;
31 import org.orekit.data.DataContext;
32 import org.orekit.errors.OrekitException;
33 import org.orekit.errors.OrekitInternalError;
34 import org.orekit.time.AbsoluteDate;
35 import org.orekit.time.FieldAbsoluteDate;
36 import org.orekit.time.TimeScalarFunction;
37 import org.orekit.time.TimeScales;
38 import org.orekit.time.TimeVectorFunction;
39 import org.orekit.utils.IERSConventions;
40
41
42
43
44
45
46
47 class MODProvider implements TransformProvider {
48
49
50 private static final long serialVersionUID = 20130920L;
51
52
53 private final IERSConventions conventions;
54
55
56 private final transient TimeVectorFunction precessionFunction;
57
58
59 private final Rotation r4;
60
61
62 private final transient Map<Field<? extends CalculusFieldElement<?>>, FieldRotation<? extends CalculusFieldElement<?>>> fieldR4;
63
64
65
66
67
68 MODProvider(final IERSConventions conventions, final TimeScales timeScales) {
69 this.conventions = conventions;
70 this.precessionFunction = conventions.getPrecessionFunction(timeScales);
71 final TimeScalarFunction epsilonAFunction =
72 conventions.getMeanObliquityFunction(timeScales);
73 final AbsoluteDate date0 = conventions.getNutationReferenceEpoch(timeScales);
74 final double epsilon0 = epsilonAFunction.value(date0);
75 r4 = new Rotation(Vector3D.PLUS_I, epsilon0, RotationConvention.FRAME_TRANSFORM);
76 fieldR4 = new HashMap<>();
77 }
78
79
80 @Override
81 public Transform getTransform(final AbsoluteDate date) {
82
83
84 final double[] angles = precessionFunction.value(date);
85
86
87 final Rotation precession = r4.compose(new Rotation(RotationOrder.ZXZ, RotationConvention.FRAME_TRANSFORM,
88 -angles[0], -angles[1], angles[2]),
89 RotationConvention.FRAME_TRANSFORM);
90
91
92 return new Transform(date, precession);
93
94 }
95
96
97 @Override
98 public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
99
100
101 final T[] angles = precessionFunction.value(date);
102
103 @SuppressWarnings("unchecked")
104 final FieldRotation<T> fR4 =
105 (FieldRotation<T>) fieldR4.computeIfAbsent(date.getField(),
106 f -> new FieldRotation<>((Field<T>) f, r4));
107
108
109 final FieldRotation<T> precession = fR4.compose(new FieldRotation<>(RotationOrder.ZXZ, RotationConvention.FRAME_TRANSFORM,
110 angles[0].negate(),
111 angles[1].negate(),
112 angles[2]),
113 RotationConvention.FRAME_TRANSFORM);
114
115
116 return new FieldTransform<>(date, precession);
117
118 }
119
120
121
122
123
124
125
126 @DefaultDataContext
127 private Object writeReplace() {
128 return new DataTransferObject(conventions);
129 }
130
131
132 @DefaultDataContext
133 private static class DataTransferObject implements Serializable {
134
135
136 private static final long serialVersionUID = 20131209L;
137
138
139 private final IERSConventions conventions;
140
141
142
143
144 DataTransferObject(final IERSConventions conventions) {
145 this.conventions = conventions;
146 }
147
148
149
150
151 private Object readResolve() {
152 try {
153
154 return new MODProvider(conventions,
155 DataContext.getDefault().getTimeScales());
156 } catch (OrekitException oe) {
157 throw new OrekitInternalError(oe);
158 }
159 }
160
161 }
162
163 }