1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.analytical.gnss;
18
19 import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
20 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.hipparchus.util.FastMath;
23 import org.hipparchus.util.MathUtils;
24 import org.hipparchus.util.Precision;
25 import org.orekit.attitudes.AttitudeProvider;
26 import org.orekit.errors.OrekitException;
27 import org.orekit.errors.OrekitMessages;
28 import org.orekit.frames.Frame;
29 import org.orekit.orbits.CartesianOrbit;
30 import org.orekit.orbits.Orbit;
31 import org.orekit.propagation.SpacecraftState;
32 import org.orekit.propagation.analytical.AbstractAnalyticalPropagator;
33 import org.orekit.propagation.analytical.gnss.data.GNSSOrbitalElements;
34 import org.orekit.time.AbsoluteDate;
35 import org.orekit.utils.PVCoordinates;
36
37
38
39
40
41
42
43
44 public class GNSSPropagator extends AbstractAnalyticalPropagator {
45
46
47
48 private static final double A;
49
50
51 private static final double B;
52
53 static {
54 final double k1 = 3 * FastMath.PI + 2;
55 final double k2 = FastMath.PI - 1;
56 final double k3 = 6 * FastMath.PI - 1;
57 A = 3 * k2 * k2 / k1;
58 B = k3 * k3 / (6 * k1);
59 }
60
61
62 private final GNSSOrbitalElements gnssOrbit;
63
64
65 private final double mass;
66
67
68 private final Frame eci;
69
70
71 private final Frame ecef;
72
73
74
75
76
77
78
79
80
81 GNSSPropagator(final GNSSOrbitalElements gnssOrbit, final Frame eci,
82 final Frame ecef, final AttitudeProvider provider,
83 final double mass) {
84 super(provider);
85
86 this.gnssOrbit = gnssOrbit;
87
88 setStartDate(gnssOrbit.getDate());
89
90 this.mass = mass;
91
92 this.eci = eci;
93
94 this.ecef = ecef;
95 }
96
97
98
99
100
101
102 public Frame getECI() {
103 return eci;
104 }
105
106
107
108
109
110
111
112 public Frame getECEF() {
113 return ecef;
114 }
115
116
117
118
119
120
121 public double getMU() {
122 return gnssOrbit.getMu();
123 }
124
125
126
127
128
129
130 public GNSSOrbitalElements getOrbitalElements() {
131 return gnssOrbit;
132 }
133
134
135 @Override
136 protected Orbit propagateOrbit(final AbsoluteDate date) {
137
138 final PVCoordinates pvaInECEF = propagateInEcef(date);
139
140 final PVCoordinates pvaInECI = ecef.getTransformTo(eci, date).transformPVCoordinates(pvaInECEF);
141
142 return new CartesianOrbit(pvaInECI, eci, date, getMU());
143 }
144
145
146
147
148
149
150
151
152
153
154 public PVCoordinates propagateInEcef(final AbsoluteDate date) {
155
156 final UnivariateDerivative2 tk = new UnivariateDerivative2(getTk(date), 1.0, 0.0);
157
158 final UnivariateDerivative2 mk = tk.multiply(gnssOrbit.getMeanMotion()).add(gnssOrbit.getM0());
159
160 final UnivariateDerivative2 ek = getEccentricAnomaly(mk);
161
162 final UnivariateDerivative2 vk = getTrueAnomaly(ek);
163
164 final UnivariateDerivative2 phik = vk.add(gnssOrbit.getPa());
165 final UnivariateDerivative2 twoPhik = phik.multiply(2);
166 final UnivariateDerivative2 c2phi = twoPhik.cos();
167 final UnivariateDerivative2 s2phi = twoPhik.sin();
168
169 final UnivariateDerivative2 dphik = c2phi.multiply(gnssOrbit.getCuc()).add(s2phi.multiply(gnssOrbit.getCus()));
170
171 final UnivariateDerivative2 drk = c2phi.multiply(gnssOrbit.getCrc()).add(s2phi.multiply(gnssOrbit.getCrs()));
172
173 final UnivariateDerivative2 dik = c2phi.multiply(gnssOrbit.getCic()).add(s2phi.multiply(gnssOrbit.getCis()));
174
175 final UnivariateDerivative2 uk = phik.add(dphik);
176
177 final UnivariateDerivative2 rk = ek.cos().multiply(-gnssOrbit.getE()).add(1).multiply(gnssOrbit.getSma()).add(drk);
178
179 final UnivariateDerivative2 ik = tk.multiply(gnssOrbit.getIDot()).add(gnssOrbit.getI0()).add(dik);
180 final UnivariateDerivative2 cik = ik.cos();
181
182 final UnivariateDerivative2 xk = uk.cos().multiply(rk);
183 final UnivariateDerivative2 yk = uk.sin().multiply(rk);
184
185 final UnivariateDerivative2 omk = tk.multiply(gnssOrbit.getOmegaDot() - gnssOrbit.getAngularVelocity()).
186 add(gnssOrbit.getOmega0() - gnssOrbit.getAngularVelocity() * gnssOrbit.getTime());
187 final UnivariateDerivative2 comk = omk.cos();
188 final UnivariateDerivative2 somk = omk.sin();
189
190 final FieldVector3D<UnivariateDerivative2> positionwithDerivatives =
191 new FieldVector3D<>(xk.multiply(comk).subtract(yk.multiply(somk).multiply(cik)),
192 xk.multiply(somk).add(yk.multiply(comk).multiply(cik)),
193 yk.multiply(ik.sin()));
194 return new PVCoordinates(new Vector3D(positionwithDerivatives.getX().getValue(),
195 positionwithDerivatives.getY().getValue(),
196 positionwithDerivatives.getZ().getValue()),
197 new Vector3D(positionwithDerivatives.getX().getFirstDerivative(),
198 positionwithDerivatives.getY().getFirstDerivative(),
199 positionwithDerivatives.getZ().getFirstDerivative()),
200 new Vector3D(positionwithDerivatives.getX().getSecondDerivative(),
201 positionwithDerivatives.getY().getSecondDerivative(),
202 positionwithDerivatives.getZ().getSecondDerivative()));
203 }
204
205
206
207
208
209
210
211 private double getTk(final AbsoluteDate date) {
212 final double cycleDuration = gnssOrbit.getCycleDuration();
213
214 double tk = date.durationFrom(gnssOrbit.getDate());
215
216 while (tk > 0.5 * cycleDuration) {
217 tk -= cycleDuration;
218 }
219 while (tk < -0.5 * cycleDuration) {
220 tk += cycleDuration;
221 }
222
223 return tk;
224 }
225
226
227
228
229
230
231
232
233
234
235
236 private UnivariateDerivative2 getEccentricAnomaly(final UnivariateDerivative2 mk) {
237
238
239 final UnivariateDerivative2 reducedM = new UnivariateDerivative2(MathUtils.normalizeAngle(mk.getValue(), 0.0),
240 mk.getFirstDerivative(),
241 mk.getSecondDerivative());
242
243
244 UnivariateDerivative2 ek;
245 if (FastMath.abs(reducedM.getValue()) < 1.0 / 6.0) {
246 if (FastMath.abs(reducedM.getValue()) < Precision.SAFE_MIN) {
247
248
249
250 ek = reducedM;
251 } else {
252
253 ek = reducedM.add(reducedM.multiply(6).cbrt().subtract(reducedM).multiply(gnssOrbit.getE()));
254 }
255 } else {
256 if (reducedM.getValue() < 0) {
257 final UnivariateDerivative2 w = reducedM.add(FastMath.PI);
258 ek = reducedM.add(w.multiply(-A).divide(w.subtract(B)).subtract(FastMath.PI).subtract(reducedM).multiply(gnssOrbit.getE()));
259 } else {
260 final UnivariateDerivative2 minusW = reducedM.subtract(FastMath.PI);
261 ek = reducedM.add(minusW.multiply(A).divide(minusW.add(B)).add(FastMath.PI).subtract(reducedM).multiply(gnssOrbit.getE()));
262 }
263 }
264
265 final double e1 = 1 - gnssOrbit.getE();
266 final boolean noCancellationRisk = (e1 + ek.getValue() * ek.getValue() / 6) >= 0.1;
267
268
269 for (int j = 0; j < 2; ++j) {
270 final UnivariateDerivative2 f;
271 UnivariateDerivative2 fd;
272 final UnivariateDerivative2 fdd = ek.sin().multiply(gnssOrbit.getE());
273 final UnivariateDerivative2 fddd = ek.cos().multiply(gnssOrbit.getE());
274 if (noCancellationRisk) {
275 f = ek.subtract(fdd).subtract(reducedM);
276 fd = fddd.subtract(1).negate();
277 } else {
278 f = eMeSinE(ek).subtract(reducedM);
279 final UnivariateDerivative2 s = ek.multiply(0.5).sin();
280 fd = s.multiply(s).multiply(2 * gnssOrbit.getE()).add(e1);
281 }
282 final UnivariateDerivative2 dee = f.multiply(fd).divide(f.multiply(0.5).multiply(fdd).subtract(fd.multiply(fd)));
283
284
285 final UnivariateDerivative2 w = fd.add(dee.multiply(0.5).multiply(fdd.add(dee.multiply(fdd).divide(3))));
286 fd = fd.add(dee.multiply(fdd.add(dee.multiply(0.5).multiply(fdd))));
287 ek = ek.subtract(f.subtract(dee.multiply(fd.subtract(w))).divide(fd));
288 }
289
290
291 ek = ek.add(mk.getValue() - reducedM.getValue());
292
293
294 return ek;
295 }
296
297
298
299
300
301
302
303 private UnivariateDerivative2 eMeSinE(final UnivariateDerivative2 E) {
304 UnivariateDerivative2 x = E.sin().multiply(1 - gnssOrbit.getE());
305 final UnivariateDerivative2 mE2 = E.negate().multiply(E);
306 UnivariateDerivative2 term = E;
307 UnivariateDerivative2 d = E.getField().getZero();
308
309 for (UnivariateDerivative2 x0 = d.add(Double.NaN); !Double.valueOf(x.getValue()).equals(Double.valueOf(x0.getValue()));) {
310 d = d.add(2);
311 term = term.multiply(mE2.divide(d.multiply(d.add(1))));
312 x0 = x;
313 x = x.subtract(term);
314 }
315 return x;
316 }
317
318
319
320
321
322
323 private UnivariateDerivative2 getTrueAnomaly(final UnivariateDerivative2 ek) {
324 final UnivariateDerivative2 svk = ek.sin().multiply(FastMath.sqrt(1. - gnssOrbit.getE() * gnssOrbit.getE()));
325 final UnivariateDerivative2 cvk = ek.cos().subtract(gnssOrbit.getE());
326 return svk.atan2(cvk);
327 }
328
329
330 @Override
331 public Frame getFrame() {
332 return eci;
333 }
334
335
336 @Override
337 protected double getMass(final AbsoluteDate date) {
338 return mass;
339 }
340
341
342 @Override
343 public void resetInitialState(final SpacecraftState state) {
344 throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
345 }
346
347
348 @Override
349 protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
350 throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
351 }
352
353 }