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 @Override
128 public double getThreshold() {
129 return threshold;
130 }
131
132
133
134
135
136 public void setThreshold(final double threshold) {
137 this.threshold = threshold;
138 }
139
140
141
142
143
144 public int getMaxIterations() {
145 return maxIterations;
146 }
147
148
149
150
151
152 public void setMaxIterations(final int maxIterations) {
153 this.maxIterations = maxIterations;
154 }
155
156
157
158
159
160 public double getDamping() {
161 return damping;
162 }
163
164
165
166
167
168 public void setDamping(final double damping) {
169 this.damping = damping;
170 }
171
172
173
174
175
176 public int getIterationsNb() {
177 return iterationsNb;
178 }
179
180
181
182
183 @Override
184 public Orbit convertToMean(final Orbit osculating) {
185
186
187 if (osculating.getA() < theory.getReferenceRadius()) {
188 throw new OrekitException(OrekitMessages.TRAJECTORY_INSIDE_BRILLOUIN_SPHERE,
189 osculating.getA());
190 }
191
192
193 final Orbit equinoctial = theory.preprocessing(osculating);
194 double sma = equinoctial.getA();
195 double ex = equinoctial.getEquinoctialEx();
196 double ey = equinoctial.getEquinoctialEy();
197 double hx = equinoctial.getHx();
198 double hy = equinoctial.getHy();
199 double lv = equinoctial.getLv();
200
201
202 final double thresholdA = threshold * FastMath.abs(sma);
203 final double thresholdE = threshold * (1 + FastMath.hypot(ex, ey));
204 final double thresholdH = threshold * (1 + FastMath.hypot(hx, hy));
205 final double thresholdLv = threshold * FastMath.PI;
206
207
208 Orbit mean = theory.initialize(equinoctial);
209
210 int i = 0;
211 while (i++ < maxIterations) {
212
213
214 final Orbit updated = theory.meanToOsculating(mean);
215
216
217 final double deltaA = equinoctial.getA() - updated.getA();
218 final double deltaEx = equinoctial.getEquinoctialEx() - updated.getEquinoctialEx();
219 final double deltaEy = equinoctial.getEquinoctialEy() - updated.getEquinoctialEy();
220 final double deltaHx = equinoctial.getHx() - updated.getHx();
221 final double deltaHy = equinoctial.getHy() - updated.getHy();
222 final double deltaLv = MathUtils.normalizeAngle(equinoctial.getLv() - updated.getLv(), 0.0);
223
224
225 if (FastMath.abs(deltaA) < thresholdA &&
226 FastMath.abs(deltaEx) < thresholdE &&
227 FastMath.abs(deltaEy) < thresholdE &&
228 FastMath.abs(deltaHx) < thresholdH &&
229 FastMath.abs(deltaHy) < thresholdH &&
230 FastMath.abs(deltaLv) < thresholdLv) {
231
232 iterationsNb = i;
233
234 return theory.postprocessing(osculating, mean);
235 }
236
237
238 sma += damping * deltaA;
239 ex += damping * deltaEx;
240 ey += damping * deltaEy;
241 hx += damping * deltaHx;
242 hy += damping * deltaHy;
243 lv += damping * deltaLv;
244
245
246 mean = new EquinoctialOrbit(sma, ex, ey, hx, hy, lv,
247 PositionAngleType.TRUE,
248 equinoctial.getFrame(),
249 equinoctial.getDate(),
250 equinoctial.getMu());
251 }
252 throw new OrekitException(OrekitMessages.UNABLE_TO_COMPUTE_MEAN_PARAMETERS, theory.getTheoryName(), i);
253 }
254
255
256
257
258 @Override
259 public <T extends CalculusFieldElement<T>> FieldOrbit<T> convertToMean(final FieldOrbit<T> osculating) {
260
261
262 if (osculating.getA().getReal() < theory.getReferenceRadius()) {
263 throw new OrekitException(OrekitMessages.TRAJECTORY_INSIDE_BRILLOUIN_SPHERE,
264 osculating.getA().getReal());
265 }
266
267
268 final FieldAbsoluteDate<T> date = osculating.getDate();
269 final Field<T> field = date.getField();
270 final T zero = field.getZero();
271 final T pi = zero.getPi();
272
273
274 final FieldOrbit<T> equinoctial = theory.preprocessing(osculating);
275 T sma = equinoctial.getA();
276 T ex = equinoctial.getEquinoctialEx();
277 T ey = equinoctial.getEquinoctialEy();
278 T hx = equinoctial.getHx();
279 T hy = equinoctial.getHy();
280 T lv = equinoctial.getLv();
281
282
283 final T thresholdA = sma.abs().multiply(threshold);
284 final T thresholdE = FastMath.hypot(ex, ey).add(1).multiply(threshold);
285 final T thresholdH = FastMath.hypot(hx, hy).add(1).multiply(threshold);
286 final T thresholdLv = pi.multiply(threshold);
287
288
289 FieldOrbit<T> mean = theory.initialize(equinoctial);
290
291 int i = 0;
292 while (i++ < maxIterations) {
293
294
295 final FieldOrbit<T> updated = theory.meanToOsculating(mean);
296
297
298 final T deltaA = equinoctial.getA().subtract(updated.getA());
299 final T deltaEx = equinoctial.getEquinoctialEx().subtract(updated.getEquinoctialEx());
300 final T deltaEy = equinoctial.getEquinoctialEy().subtract(updated.getEquinoctialEy());
301 final T deltaHx = equinoctial.getHx().subtract(updated.getHx());
302 final T deltaHy = equinoctial.getHy().subtract(updated.getHy());
303 final T deltaLv = MathUtils.normalizeAngle(equinoctial.getLv().subtract(updated.getLv()), zero);
304
305
306 if (FastMath.abs(deltaA.getReal()) < thresholdA.getReal() &&
307 FastMath.abs(deltaEx.getReal()) < thresholdE.getReal() &&
308 FastMath.abs(deltaEy.getReal()) < thresholdE.getReal() &&
309 FastMath.abs(deltaHx.getReal()) < thresholdH.getReal() &&
310 FastMath.abs(deltaHy.getReal()) < thresholdH.getReal() &&
311 FastMath.abs(deltaLv.getReal()) < thresholdLv.getReal()) {
312
313 iterationsNb = i;
314
315 return theory.postprocessing(osculating, mean);
316 }
317
318
319 sma = sma.add(deltaA.multiply(damping));
320 ex = ex.add(deltaEx.multiply(damping));
321 ey = ey.add(deltaEy.multiply(damping));
322 hx = hx.add(deltaHx.multiply(damping));
323 hy = hy.add(deltaHy.multiply(damping));
324 lv = lv.add(deltaLv.multiply(damping));
325
326
327 mean = new FieldEquinoctialOrbit<>(sma, ex, ey, hx, hy, lv,
328 PositionAngleType.TRUE,
329 equinoctial.getFrame(),
330 equinoctial.getDate(),
331 equinoctial.getMu());
332 }
333 throw new OrekitException(OrekitMessages.UNABLE_TO_COMPUTE_MEAN_PARAMETERS, theory.getTheoryName(), i);
334 }
335 }