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.CalculusFieldElement;
24 import org.hipparchus.Field;
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 @SuppressWarnings("unchecked")
98 @Override
99 public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
100
101
102 final T[] angles = precessionFunction.value(date);
103
104 final FieldRotation<T> fR4;
105 synchronized (fieldR4) {
106 fR4 = (FieldRotation<T>) fieldR4.computeIfAbsent(date.getField(),
107 f -> new FieldRotation<>((Field<T>) f, r4));
108 }
109
110
111 final FieldRotation<T> precession = fR4.compose(new FieldRotation<>(RotationOrder.ZXZ, RotationConvention.FRAME_TRANSFORM,
112 angles[0].negate(),
113 angles[1].negate(),
114 angles[2]),
115 RotationConvention.FRAME_TRANSFORM);
116
117
118 return new FieldTransform<>(date, precession);
119
120 }
121
122
123
124
125
126
127
128 @DefaultDataContext
129 private Object writeReplace() {
130 return new DataTransferObject(conventions);
131 }
132
133
134 @DefaultDataContext
135 private static class DataTransferObject implements Serializable {
136
137
138 private static final long serialVersionUID = 20131209L;
139
140
141 private final IERSConventions conventions;
142
143
144
145
146 DataTransferObject(final IERSConventions conventions) {
147 this.conventions = conventions;
148 }
149
150
151
152
153 private Object readResolve() {
154 try {
155
156 return new MODProvider(conventions,
157 DataContext.getDefault().getTimeScales());
158 } catch (OrekitException oe) {
159 throw new OrekitInternalError(oe);
160 }
161 }
162
163 }
164
165 }