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