1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.conversion.osc2mean;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.util.FastMath;
22 import org.hipparchus.util.MathUtils;
23 import org.orekit.errors.OrekitException;
24 import org.orekit.errors.OrekitMessages;
25 import org.orekit.orbits.EquinoctialOrbit;
26 import org.orekit.orbits.FieldEquinoctialOrbit;
27 import org.orekit.orbits.FieldOrbit;
28 import org.orekit.orbits.Orbit;
29 import org.orekit.orbits.PositionAngleType;
30 import org.orekit.time.FieldAbsoluteDate;
31
32
33
34
35
36
37
38
39 public class FixedPointConverter implements OsculatingToMeanConverter {
40
41
42 public static final double DEFAULT_THRESHOLD = 1e-12;
43
44
45 public static final int DEFAULT_MAX_ITERATIONS = 100;
46
47
48 public static final double DEFAULT_DAMPING = 1.;
49
50
51 private MeanTheory theory;
52
53
54 private double threshold;
55
56
57 private int maxIterations;
58
59
60 private double damping;
61
62
63 private int iterationsNb;
64
65
66
67
68
69
70 public FixedPointConverter() {
71 this(null, DEFAULT_THRESHOLD, DEFAULT_MAX_ITERATIONS, DEFAULT_DAMPING);
72 }
73
74
75
76
77
78 public FixedPointConverter(final MeanTheory theory) {
79 this(theory, DEFAULT_THRESHOLD, DEFAULT_MAX_ITERATIONS, DEFAULT_DAMPING);
80 }
81
82
83
84
85
86
87
88
89
90
91 public FixedPointConverter(final double threshold,
92 final int maxIterations,
93 final double damping) {
94 this(null, threshold, maxIterations, damping);
95 }
96
97
98
99
100
101
102
103
104 public FixedPointConverter(final MeanTheory theory,
105 final double threshold,
106 final int maxIterations,
107 final double damping) {
108 setMeanTheory(theory);
109 setThreshold(threshold);
110 setMaxIterations(maxIterations);
111 setDamping(damping);
112 }
113
114
115 @Override
116 public MeanTheory getMeanTheory() {
117 return theory;
118 }
119
120
121 @Override
122 public void setMeanTheory(final MeanTheory meanTheory) {
123 this.theory = meanTheory;
124 }
125
126
127
128
129
130 public double getThreshold() {
131 return threshold;
132 }
133
134
135
136
137
138 public void setThreshold(final double threshold) {
139 this.threshold = threshold;
140 }
141
142
143
144
145
146 public int getMaxIterations() {
147 return maxIterations;
148 }
149
150
151
152
153
154 public void setMaxIterations(final int maxIterations) {
155 this.maxIterations = maxIterations;
156 }
157
158
159
160
161
162 public double getDamping() {
163 return damping;
164 }
165
166
167
168
169
170 public void setDamping(final double damping) {
171 this.damping = damping;
172 }
173
174
175
176
177
178 public int getIterationsNb() {
179 return iterationsNb;
180 }
181
182
183
184
185 @Override
186 public Orbit convertToMean(final Orbit osculating) {
187
188
189 if (osculating.getA() < theory.getReferenceRadius()) {
190 throw new OrekitException(OrekitMessages.TRAJECTORY_INSIDE_BRILLOUIN_SPHERE,
191 osculating.getA());
192 }
193
194
195 final Orbit equinoctial = theory.preprocessing(osculating);
196 double sma = equinoctial.getA();
197 double ex = equinoctial.getEquinoctialEx();
198 double ey = equinoctial.getEquinoctialEy();
199 double hx = equinoctial.getHx();
200 double hy = equinoctial.getHy();
201 double lv = equinoctial.getLv();
202
203
204 final double thresholdA = threshold * FastMath.abs(sma);
205 final double thresholdE = threshold * (1 + FastMath.hypot(ex, ey));
206 final double thresholdH = threshold * (1 + FastMath.hypot(hx, hy));
207 final double thresholdLv = threshold * FastMath.PI;
208
209
210 Orbit mean = theory.initialize(equinoctial);
211
212 int i = 0;
213 while (i++ < maxIterations) {
214
215
216 final Orbit updated = theory.meanToOsculating(mean);
217
218
219 final double deltaA = equinoctial.getA() - updated.getA();
220 final double deltaEx = equinoctial.getEquinoctialEx() - updated.getEquinoctialEx();
221 final double deltaEy = equinoctial.getEquinoctialEy() - updated.getEquinoctialEy();
222 final double deltaHx = equinoctial.getHx() - updated.getHx();
223 final double deltaHy = equinoctial.getHy() - updated.getHy();
224 final double deltaLv = MathUtils.normalizeAngle(equinoctial.getLv() - updated.getLv(), 0.0);
225
226
227 if (FastMath.abs(deltaA) < thresholdA &&
228 FastMath.abs(deltaEx) < thresholdE &&
229 FastMath.abs(deltaEy) < thresholdE &&
230 FastMath.abs(deltaHx) < thresholdH &&
231 FastMath.abs(deltaHy) < thresholdH &&
232 FastMath.abs(deltaLv) < thresholdLv) {
233
234 iterationsNb = i;
235
236 return theory.postprocessing(osculating, mean);
237 }
238
239
240 sma += damping * deltaA;
241 ex += damping * deltaEx;
242 ey += damping * deltaEy;
243 hx += damping * deltaHx;
244 hy += damping * deltaHy;
245 lv += damping * deltaLv;
246
247
248 mean = new EquinoctialOrbit(sma, ex, ey, hx, hy, lv,
249 PositionAngleType.TRUE,
250 equinoctial.getFrame(),
251 equinoctial.getDate(),
252 equinoctial.getMu());
253 }
254 throw new OrekitException(OrekitMessages.UNABLE_TO_COMPUTE_MEAN_PARAMETERS, theory.getTheoryName(), i);
255 }
256
257
258
259
260 @Override
261 public <T extends CalculusFieldElement<T>> FieldOrbit<T> convertToMean(final FieldOrbit<T> osculating) {
262
263
264 if (osculating.getA().getReal() < theory.getReferenceRadius()) {
265 throw new OrekitException(OrekitMessages.TRAJECTORY_INSIDE_BRILLOUIN_SPHERE,
266 osculating.getA());
267 }
268
269
270 final FieldAbsoluteDate<T> date = osculating.getDate();
271 final Field<T> field = date.getField();
272 final T zero = field.getZero();
273 final T pi = zero.getPi();
274
275
276 final FieldOrbit<T> equinoctial = theory.preprocessing(osculating);
277 T sma = equinoctial.getA();
278 T ex = equinoctial.getEquinoctialEx();
279 T ey = equinoctial.getEquinoctialEy();
280 T hx = equinoctial.getHx();
281 T hy = equinoctial.getHy();
282 T lv = equinoctial.getLv();
283
284
285 final T thresholdA = sma.abs().multiply(threshold);
286 final T thresholdE = FastMath.hypot(ex, ey).add(1).multiply(threshold);
287 final T thresholdH = FastMath.hypot(hx, hy).add(1).multiply(threshold);
288 final T thresholdLv = pi.multiply(threshold);
289
290
291 FieldOrbit<T> mean = theory.initialize(equinoctial);
292
293 int i = 0;
294 while (i++ < maxIterations) {
295
296
297 final FieldOrbit<T> updated = theory.meanToOsculating(mean);
298
299
300 final T deltaA = equinoctial.getA().subtract(updated.getA());
301 final T deltaEx = equinoctial.getEquinoctialEx().subtract(updated.getEquinoctialEx());
302 final T deltaEy = equinoctial.getEquinoctialEy().subtract(updated.getEquinoctialEy());
303 final T deltaHx = equinoctial.getHx().subtract(updated.getHx());
304 final T deltaHy = equinoctial.getHy().subtract(updated.getHy());
305 final T deltaLv = MathUtils.normalizeAngle(equinoctial.getLv().subtract(updated.getLv()), zero);
306
307
308 if (FastMath.abs(deltaA.getReal()) < thresholdA.getReal() &&
309 FastMath.abs(deltaEx.getReal()) < thresholdE.getReal() &&
310 FastMath.abs(deltaEy.getReal()) < thresholdE.getReal() &&
311 FastMath.abs(deltaHx.getReal()) < thresholdH.getReal() &&
312 FastMath.abs(deltaHy.getReal()) < thresholdH.getReal() &&
313 FastMath.abs(deltaLv.getReal()) < thresholdLv.getReal()) {
314
315 iterationsNb = i;
316
317 return theory.postprocessing(osculating, mean);
318 }
319
320
321 sma = sma.add(deltaA.multiply(damping));
322 ex = ex.add(deltaEx.multiply(damping));
323 ey = ey.add(deltaEy.multiply(damping));
324 hx = hx.add(deltaHx.multiply(damping));
325 hy = hy.add(deltaHy.multiply(damping));
326 lv = lv.add(deltaLv.multiply(damping));
327
328
329 mean = new FieldEquinoctialOrbit<>(sma, ex, ey, hx, hy, lv,
330 PositionAngleType.TRUE,
331 equinoctial.getFrame(),
332 equinoctial.getDate(),
333 equinoctial.getMu());
334 }
335 throw new OrekitException(OrekitMessages.UNABLE_TO_COMPUTE_MEAN_PARAMETERS, theory.getTheoryName(), i);
336 }
337 }