1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.analytical.tle.generation;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.Rotation;
22 import org.hipparchus.util.FastMath;
23 import org.hipparchus.util.MathUtils;
24 import org.orekit.annotation.DefaultDataContext;
25 import org.orekit.attitudes.FrameAlignedProvider;
26 import org.orekit.data.DataContext;
27 import org.orekit.errors.OrekitException;
28 import org.orekit.errors.OrekitMessages;
29 import org.orekit.frames.Frame;
30 import org.orekit.orbits.EquinoctialOrbit;
31 import org.orekit.orbits.FieldEquinoctialOrbit;
32 import org.orekit.orbits.FieldKeplerianOrbit;
33 import org.orekit.orbits.FieldOrbit;
34 import org.orekit.orbits.KeplerianOrbit;
35 import org.orekit.orbits.Orbit;
36 import org.orekit.orbits.OrbitType;
37 import org.orekit.orbits.PositionAngleType;
38 import org.orekit.propagation.FieldSpacecraftState;
39 import org.orekit.propagation.SpacecraftState;
40 import org.orekit.propagation.analytical.tle.FieldTLE;
41 import org.orekit.propagation.analytical.tle.FieldTLEPropagator;
42 import org.orekit.propagation.analytical.tle.TLE;
43 import org.orekit.propagation.analytical.tle.TLEConstants;
44 import org.orekit.propagation.analytical.tle.TLEPropagator;
45 import org.orekit.time.AbsoluteDate;
46 import org.orekit.time.TimeScale;
47 import org.orekit.utils.ParameterDriver;
48
49
50
51
52
53
54
55
56
57
58
59
60 public class FixedPointTleGenerationAlgorithm implements TleGenerationAlgorithm {
61
62
63 public static final double EPSILON_DEFAULT = 1.0e-10;
64
65
66 public static final int MAX_ITERATIONS_DEFAULT = 100;
67
68
69 public static final double SCALE_DEFAULT = 1.0;
70
71
72 private final double epsilon;
73
74
75 private final int maxIterations;
76
77
78 private final double scale;
79
80
81 private final TimeScale utc;
82
83
84 private final Frame teme;
85
86
87
88
89
90
91
92
93
94 @DefaultDataContext
95 public FixedPointTleGenerationAlgorithm() {
96 this(EPSILON_DEFAULT, MAX_ITERATIONS_DEFAULT, SCALE_DEFAULT);
97 }
98
99
100
101
102
103
104
105
106
107
108 @DefaultDataContext
109 public FixedPointTleGenerationAlgorithm(final double epsilon, final int maxIterations,
110 final double scale) {
111 this(epsilon, maxIterations, scale,
112 DataContext.getDefault().getTimeScales().getUTC(),
113 DataContext.getDefault().getFrames().getTEME());
114 }
115
116
117
118
119
120
121
122
123
124 public FixedPointTleGenerationAlgorithm(final double epsilon, final int maxIterations,
125 final double scale, final TimeScale utc,
126 final Frame teme) {
127 this.epsilon = epsilon;
128 this.maxIterations = maxIterations;
129 this.scale = scale;
130 this.utc = utc;
131 this.teme = teme;
132 }
133
134
135 @Override
136 public TLE generate(final SpacecraftState state, final TLE templateTLE) {
137
138
139 final AbsoluteDate epoch = state.getDate();
140
141
142 final EquinoctialOrbit equinoctialOrbit = convert(state.getOrbit());
143 double sma = equinoctialOrbit.getA();
144 double ex = equinoctialOrbit.getEquinoctialEx();
145 double ey = equinoctialOrbit.getEquinoctialEy();
146 double hx = equinoctialOrbit.getHx();
147 double hy = equinoctialOrbit.getHy();
148 double lv = equinoctialOrbit.getLv();
149
150
151 final KeplerianOrbit keplerianOrbit = (KeplerianOrbit) OrbitType.KEPLERIAN.convertType(equinoctialOrbit);
152 TLE current = TleGenerationUtil.newTLE(keplerianOrbit, templateTLE, templateTLE.getBStar(epoch), utc);
153
154
155 final double thrA = epsilon * (1 + sma);
156 final double thrE = epsilon * (1 + FastMath.hypot(ex, ey));
157 final double thrH = epsilon * (1 + FastMath.hypot(hx, hy));
158 final double thrV = epsilon * FastMath.PI;
159
160 int k = 0;
161 while (k++ < maxIterations) {
162
163
164 final TLEPropagator propagator = TLEPropagator.selectExtrapolator(current,
165 new FrameAlignedProvider(Rotation.IDENTITY, teme),
166 state.getMass(), teme);
167 final Orbit recoveredOrbit = propagator.getInitialState().getOrbit();
168 final EquinoctialOrbit recoveredEquiOrbit = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(recoveredOrbit);
169
170
171 final double deltaSma = equinoctialOrbit.getA() - recoveredEquiOrbit.getA();
172 final double deltaEx = equinoctialOrbit.getEquinoctialEx() - recoveredEquiOrbit.getEquinoctialEx();
173 final double deltaEy = equinoctialOrbit.getEquinoctialEy() - recoveredEquiOrbit.getEquinoctialEy();
174 final double deltaHx = equinoctialOrbit.getHx() - recoveredEquiOrbit.getHx();
175 final double deltaHy = equinoctialOrbit.getHy() - recoveredEquiOrbit.getHy();
176 final double deltaLv = MathUtils.normalizeAngle(equinoctialOrbit.getLv() - recoveredEquiOrbit.getLv(), 0.0);
177
178
179 if (FastMath.abs(deltaSma) < thrA &&
180 FastMath.abs(deltaEx) < thrE &&
181 FastMath.abs(deltaEy) < thrE &&
182 FastMath.abs(deltaHx) < thrH &&
183 FastMath.abs(deltaHy) < thrH &&
184 FastMath.abs(deltaLv) < thrV) {
185
186
187 for (final ParameterDriver templateDrivers : templateTLE.getParametersDrivers()) {
188 if (templateDrivers.isSelected()) {
189
190 current.getParameterDriver(templateDrivers.getName()).setSelected(true);
191 }
192 }
193
194
195 return current;
196 }
197
198
199 sma += scale * deltaSma;
200 ex += scale * deltaEx;
201 ey += scale * deltaEy;
202 hx += scale * deltaHx;
203 hy += scale * deltaHy;
204 lv += scale * deltaLv;
205 final EquinoctialOrbit newEquinoctialOrbit =
206 new EquinoctialOrbit(sma, ex, ey, hx, hy, lv, PositionAngleType.TRUE,
207 equinoctialOrbit.getFrame(), equinoctialOrbit.getDate(), equinoctialOrbit.getMu());
208 final KeplerianOrbit newKeplerianOrbit = (KeplerianOrbit) OrbitType.KEPLERIAN.convertType(newEquinoctialOrbit);
209
210
211 current = TleGenerationUtil.newTLE(newKeplerianOrbit, templateTLE, templateTLE.getBStar(epoch), utc);
212
213 }
214
215
216 throw new OrekitException(OrekitMessages.UNABLE_TO_COMPUTE_TLE, k);
217
218 }
219
220
221 @Override
222 public <T extends CalculusFieldElement<T>> FieldTLE<T> generate(final FieldSpacecraftState<T> state,
223 final FieldTLE<T> templateTLE) {
224
225
226 final FieldEquinoctialOrbit<T> equinoctialOrbit = convert(state.getOrbit());
227 T sma = equinoctialOrbit.getA();
228 T ex = equinoctialOrbit.getEquinoctialEx();
229 T ey = equinoctialOrbit.getEquinoctialEy();
230 T hx = equinoctialOrbit.getHx();
231 T hy = equinoctialOrbit.getHy();
232 T lv = equinoctialOrbit.getLv();
233
234
235 final T bStar = state.getA().getField().getZero().newInstance(templateTLE.getBStar());
236 final FieldKeplerianOrbit<T> keplerianOrbit = (FieldKeplerianOrbit<T>) OrbitType.KEPLERIAN.convertType(equinoctialOrbit);
237 FieldTLE<T> current = TleGenerationUtil.newTLE(keplerianOrbit, templateTLE, bStar, utc);
238
239
240 final Field<T> field = state.getDate().getField();
241
242
243 final T thrA = sma.add(1).multiply(epsilon);
244 final T thrE = FastMath.hypot(ex, ey).add(1).multiply(epsilon);
245 final T thrH = FastMath.hypot(hx, hy).add(1).multiply(epsilon);
246 final T thrV = sma.getPi().multiply(epsilon);
247
248 int k = 0;
249 while (k++ < maxIterations) {
250
251
252 final FieldTLEPropagator<T> propagator = FieldTLEPropagator.selectExtrapolator(current, new FrameAlignedProvider(Rotation.IDENTITY, teme),
253 state.getMass(), teme, templateTLE.getParameters(field));
254 final FieldOrbit<T> recoveredOrbit = propagator.getInitialState().getOrbit();
255 final FieldEquinoctialOrbit<T> recoveredEquinoctialOrbit = (FieldEquinoctialOrbit<T>) OrbitType.EQUINOCTIAL.convertType(recoveredOrbit);
256
257
258 final T deltaSma = equinoctialOrbit.getA().subtract(recoveredEquinoctialOrbit.getA());
259 final T deltaEx = equinoctialOrbit.getEquinoctialEx().subtract(recoveredEquinoctialOrbit.getEquinoctialEx());
260 final T deltaEy = equinoctialOrbit.getEquinoctialEy().subtract(recoveredEquinoctialOrbit.getEquinoctialEy());
261 final T deltaHx = equinoctialOrbit.getHx().subtract(recoveredEquinoctialOrbit.getHx());
262 final T deltaHy = equinoctialOrbit.getHy().subtract(recoveredEquinoctialOrbit.getHy());
263 final T deltaLv = MathUtils.normalizeAngle(equinoctialOrbit.getLv().subtract(recoveredEquinoctialOrbit.getLv()), field.getZero());
264
265
266 if (FastMath.abs(deltaSma.getReal()) < thrA.getReal() &&
267 FastMath.abs(deltaEx.getReal()) < thrE.getReal() &&
268 FastMath.abs(deltaEy.getReal()) < thrE.getReal() &&
269 FastMath.abs(deltaHx.getReal()) < thrH.getReal() &&
270 FastMath.abs(deltaHy.getReal()) < thrH.getReal() &&
271 FastMath.abs(deltaLv.getReal()) < thrV.getReal()) {
272
273
274 return current;
275
276 }
277
278
279 sma = sma.add(deltaSma.multiply(scale));
280 ex = ex.add(deltaEx.multiply(scale));
281 ey = ey.add(deltaEy.multiply(scale));
282 hx = hx.add(deltaHx.multiply(scale));
283 hy = hy.add(deltaHy.multiply(scale));
284 lv = lv.add(deltaLv.multiply(scale));
285 final FieldEquinoctialOrbit<T> newEquinoctialOrbit =
286 new FieldEquinoctialOrbit<>(sma, ex, ey, hx, hy, lv, PositionAngleType.TRUE,
287 equinoctialOrbit.getFrame(), equinoctialOrbit.getDate(), equinoctialOrbit.getMu());
288 final FieldKeplerianOrbit<T> newKeplerianOrbit = (FieldKeplerianOrbit<T>) OrbitType.KEPLERIAN.convertType(newEquinoctialOrbit);
289
290
291 current = TleGenerationUtil.newTLE(newKeplerianOrbit, templateTLE, bStar, utc);
292
293 }
294
295 throw new OrekitException(OrekitMessages.UNABLE_TO_COMPUTE_TLE, k);
296
297 }
298
299
300
301
302
303
304 private EquinoctialOrbit convert(final Orbit orbitIn) {
305 return new EquinoctialOrbit(orbitIn.getPVCoordinates(teme), teme, TLEConstants.MU);
306 }
307
308
309
310
311
312
313
314 private <T extends CalculusFieldElement<T>> FieldEquinoctialOrbit<T> convert(final FieldOrbit<T> orbitIn) {
315 return new FieldEquinoctialOrbit<T>(orbitIn.getPVCoordinates(teme), teme, orbitIn.getMu().newInstance(TLEConstants.MU));
316 }
317
318 }