1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.orbits;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.exception.MathIllegalStateException;
22 import org.hipparchus.util.FastMath;
23 import org.hipparchus.util.FieldSinCos;
24 import org.hipparchus.util.MathUtils;
25 import org.hipparchus.util.Precision;
26 import org.orekit.errors.OrekitMessages;
27
28
29
30
31
32
33
34 public class FieldKeplerianAnomalyUtility {
35
36
37 private static final double A;
38
39
40 private static final double B;
41
42 static {
43 final double k1 = 3 * FastMath.PI + 2;
44 final double k2 = FastMath.PI - 1;
45 final double k3 = 6 * FastMath.PI - 1;
46 A = 3 * k2 * k2 / k1;
47 B = k3 * k3 / (6 * k1);
48 }
49
50
51 private FieldKeplerianAnomalyUtility() {
52
53 }
54
55
56
57
58
59
60
61
62 public static <T extends CalculusFieldElement<T>> T ellipticMeanToTrue(final T e, final T M) {
63 final T E = ellipticMeanToEccentric(e, M);
64 final T v = ellipticEccentricToTrue(e, E);
65 return v;
66 }
67
68
69
70
71
72
73
74
75 public static <T extends CalculusFieldElement<T>> T ellipticTrueToMean(final T e, final T v) {
76 final T E = ellipticTrueToEccentric(e, v);
77 final T M = ellipticEccentricToMean(e, E);
78 return M;
79 }
80
81
82
83
84
85
86
87
88 public static <T extends CalculusFieldElement<T>> T ellipticEccentricToTrue(final T e, final T E) {
89 final T beta = e.divide(e.multiply(e).negate().add(1).sqrt().add(1));
90 final FieldSinCos<T> scE = FastMath.sinCos(E);
91 return E.add(beta.multiply(scE.sin()).divide(beta.multiply(scE.cos()).subtract(1).negate()).atan().multiply(2));
92 }
93
94
95
96
97
98
99
100
101 public static <T extends CalculusFieldElement<T>> T ellipticTrueToEccentric(final T e, final T v) {
102 final T beta = e.divide(e.multiply(e).negate().add(1).sqrt().add(1));
103 final FieldSinCos<T> scv = FastMath.sinCos(v);
104 return v.subtract((beta.multiply(scv.sin()).divide(beta.multiply(scv.cos()).add(1))).atan().multiply(2));
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public static <T extends CalculusFieldElement<T>> T ellipticMeanToEccentric(final T e, final T M) {
120
121 final T reducedM = MathUtils.normalizeAngle(M, M.getField().getZero());
122
123
124 T E;
125 if (reducedM.abs().getReal() < 1.0 / 6.0) {
126 if (FastMath.abs(reducedM.getReal()) < Precision.SAFE_MIN) {
127
128
129
130
131 E = reducedM;
132 } else {
133
134 E = reducedM.add(e.multiply((reducedM.multiply(6).cbrt()).subtract(reducedM)));
135 }
136 } else {
137 final T pi = e.getPi();
138 if (reducedM.getReal() < 0) {
139 final T w = reducedM.add(pi);
140 E = reducedM.add(e.multiply(w.multiply(A).divide(w.negate().add(B)).subtract(pi).subtract(reducedM)));
141 } else {
142 final T w = reducedM.negate().add(pi);
143 E = reducedM
144 .add(e.multiply(w.multiply(A).divide(w.negate().add(B)).negate().subtract(reducedM).add(pi)));
145 }
146 }
147
148 final T e1 = e.negate().add(1);
149 final boolean noCancellationRisk = (e1.getReal() + E.getReal() * E.getReal() / 6) >= 0.1;
150
151
152
153 for (int j = 0; j < 2; ++j) {
154
155 final T f;
156 T fd;
157 final FieldSinCos<T> scE = FastMath.sinCos(E);
158 final T fdd = e.multiply(scE.sin());
159 final T fddd = e.multiply(scE.cos());
160
161 if (noCancellationRisk) {
162
163 f = (E.subtract(fdd)).subtract(reducedM);
164 fd = fddd.negate().add(1);
165 } else {
166
167 f = eMeSinE(e, E).subtract(reducedM);
168 final T s = E.multiply(0.5).sin();
169 fd = e1.add(e.multiply(s).multiply(s).multiply(2));
170 }
171 final T dee = f.multiply(fd).divide(f.multiply(fdd).multiply(0.5).subtract(fd.multiply(fd)));
172
173
174 final T w = fd.add(dee.multiply(fdd.add(dee.multiply(fddd.divide(3)))).multiply(0.5));
175 fd = fd.add(dee.multiply(fdd.add(dee.multiply(fddd).multiply(0.5))));
176 E = E.subtract(f.subtract(dee.multiply(fd.subtract(w))).divide(fd));
177
178 }
179
180
181 E = E.add(M).subtract(reducedM);
182 return E;
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196 private static <T extends CalculusFieldElement<T>> T eMeSinE(final T e, final T E) {
197 T x = (e.negate().add(1)).multiply(E.sin());
198 final T mE2 = E.negate().multiply(E);
199 T term = E;
200 double d = 0;
201
202
203 for (T x0 = E.getField().getZero().add(Double.NaN); !Double.valueOf(x.getReal())
204 .equals(Double.valueOf(x0.getReal()));) {
205 d += 2;
206 term = term.multiply(mE2.divide(d * (d + 1)));
207 x0 = x;
208 x = x.subtract(term);
209 }
210 return x;
211 }
212
213
214
215
216
217
218
219
220 public static <T extends CalculusFieldElement<T>> T ellipticEccentricToMean(final T e, final T E) {
221 return E.subtract(e.multiply(E.sin()));
222 }
223
224
225
226
227
228
229
230
231 public static <T extends CalculusFieldElement<T>> T hyperbolicMeanToTrue(final T e, final T M) {
232 final T H = hyperbolicMeanToEccentric(e, M);
233 final T v = hyperbolicEccentricToTrue(e, H);
234 return v;
235 }
236
237
238
239
240
241
242
243
244 public static <T extends CalculusFieldElement<T>> T hyperbolicTrueToMean(final T e, final T v) {
245 final T H = hyperbolicTrueToEccentric(e, v);
246 final T M = hyperbolicEccentricToMean(e, H);
247 return M;
248 }
249
250
251
252
253
254
255
256
257 public static <T extends CalculusFieldElement<T>> T hyperbolicEccentricToTrue(final T e, final T H) {
258 final T s = e.add(1).divide(e.subtract(1)).sqrt();
259 final T tanH = H.multiply(0.5).tanh();
260 return s.multiply(tanH).atan().multiply(2);
261 }
262
263
264
265
266
267
268
269
270 public static <T extends CalculusFieldElement<T>> T hyperbolicTrueToEccentric(final T e, final T v) {
271 final FieldSinCos<T> scv = FastMath.sinCos(v);
272 final T sinhH = e.multiply(e).subtract(1).sqrt().multiply(scv.sin()).divide(e.multiply(scv.cos()).add(1));
273 return sinhH.asinh();
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 public static <T extends CalculusFieldElement<T>> T hyperbolicMeanToEccentric(final T e, final T M) {
290 final Field<T> field = e.getField();
291 final T zero = field.getZero();
292 final T one = field.getOne();
293 final T two = zero.add(2.0);
294 final T three = zero.add(3.0);
295 final T half = zero.add(0.5);
296 final T onePointFive = zero.add(1.5);
297 final T fourThirds = zero.add(4.0).divide(zero.add(3.0));
298
299
300 final T L = M.divide(e);
301 final T g = e.reciprocal();
302 final T g1 = one.subtract(g);
303
304
305 T S = L;
306 if (L.isZero()) {
307 return M.getField().getZero();
308 }
309 final T cl = L.multiply(L).add(one).sqrt();
310 final T al = L.asinh();
311 final T w = g.multiply(g).multiply(al).divide(cl.multiply(cl).multiply(cl));
312 S = one.subtract(g.divide(cl));
313 S = L.add(g.multiply(al).divide(S.multiply(S).multiply(S)
314 .add(w.multiply(L).multiply(onePointFive.subtract(fourThirds.multiply(g)))).cbrt()));
315
316
317 for (int i = 0; i < 2; ++i) {
318 final T s0 = S.multiply(S);
319 final T s1 = s0.add(one);
320 final T s2 = s1.sqrt();
321 final T s3 = s1.multiply(s2);
322 final T fdd = g.multiply(S).divide(s3);
323 final T fddd = g.multiply(one.subtract(two.multiply(s0))).divide(s1.multiply(s3));
324
325 T f;
326 T fd;
327 if (s0.divide(zero.add(6.0)).add(g1).getReal() >= 0.5) {
328 f = S.subtract(g.multiply(S.asinh())).subtract(L);
329 fd = one.subtract(g.divide(s2));
330 } else {
331
332
333 final T t = S.divide(one.add(one.add(S.multiply(S)).sqrt()));
334 final T tsq = t.multiply(t);
335 T x = S.multiply(g1.add(g.multiply(tsq)));
336 T term = two.multiply(g).multiply(t);
337 T twoI1 = one;
338 T x0;
339 int j = 0;
340 do {
341 if (++j == 1000000) {
342
343 throw new MathIllegalStateException(
344 OrekitMessages.UNABLE_TO_COMPUTE_HYPERBOLIC_ECCENTRIC_ANOMALY, j);
345 }
346 twoI1 = twoI1.add(2.0);
347 term = term.multiply(tsq);
348 x0 = x;
349 x = x.subtract(term.divide(twoI1));
350 } while (x.getReal() != x0.getReal());
351 f = x.subtract(L);
352 fd = s0.divide(s2.add(one)).add(g1).divide(s2);
353 }
354 final T ds = f.multiply(fd).divide(half.multiply(f).multiply(fdd).subtract(fd.multiply(fd)));
355 final T stemp = S.add(ds);
356 if (S.getReal() == stemp.getReal()) {
357 break;
358 }
359 f = f.add(ds.multiply(fd.add(half.multiply(ds.multiply(fdd.add(ds.divide(three).multiply(fddd)))))));
360 fd = fd.add(ds.multiply(fdd.add(half.multiply(ds).multiply(fddd))));
361 S = stemp.subtract(f.divide(fd));
362 }
363
364 final T H = S.asinh();
365 return H;
366 }
367
368
369
370
371
372
373
374
375 public static <T extends CalculusFieldElement<T>> T hyperbolicEccentricToMean(final T e, final T H) {
376 return e.multiply(H.sinh()).subtract(H);
377 }
378
379 }