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 java.util.function.UnaryOperator;
20
21 import org.hipparchus.CalculusFieldElement;
22 import org.hipparchus.Field;
23 import org.hipparchus.analysis.differentiation.Gradient;
24 import org.hipparchus.analysis.differentiation.GradientField;
25 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26 import org.hipparchus.geometry.euclidean.threed.Vector3D;
27 import org.hipparchus.linear.DiagonalMatrix;
28 import org.hipparchus.linear.FieldVector;
29 import org.hipparchus.linear.MatrixUtils;
30 import org.hipparchus.linear.RealMatrix;
31 import org.hipparchus.linear.RealVector;
32 import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresBuilder;
33 import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer;
34 import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem;
35 import org.hipparchus.optim.nonlinear.vector.leastsquares.LevenbergMarquardtOptimizer;
36 import org.hipparchus.optim.nonlinear.vector.leastsquares.MultivariateJacobianFunction;
37 import org.hipparchus.util.Pair;
38 import org.orekit.annotation.DefaultDataContext;
39 import org.orekit.data.DataContext;
40 import org.orekit.frames.Frame;
41 import org.orekit.orbits.FieldKeplerianOrbit;
42 import org.orekit.orbits.KeplerianOrbit;
43 import org.orekit.propagation.FieldSpacecraftState;
44 import org.orekit.propagation.SpacecraftState;
45 import org.orekit.propagation.analytical.tle.FieldTLE;
46 import org.orekit.propagation.analytical.tle.FieldTLEPropagator;
47 import org.orekit.propagation.analytical.tle.TLE;
48 import org.orekit.propagation.analytical.tle.TLEPropagator;
49 import org.orekit.time.AbsoluteDate;
50 import org.orekit.time.FieldAbsoluteDate;
51 import org.orekit.time.TimeScale;
52 import org.orekit.utils.FieldPVCoordinates;
53 import org.orekit.utils.PVCoordinates;
54 import org.orekit.utils.ParameterDriver;
55
56
57
58
59
60
61
62 public class LeastSquaresTleGenerationAlgorithm implements TleGenerationAlgorithm {
63
64
65 public static final int DEFAULT_MAX_ITERATIONS = 1000;
66
67
68 private final TimeScale utc;
69
70
71 private final Frame teme;
72
73
74 private final int maxIterations;
75
76
77 private double rms;
78
79
80
81
82
83
84
85
86 @DefaultDataContext
87 public LeastSquaresTleGenerationAlgorithm() {
88 this(DEFAULT_MAX_ITERATIONS);
89 }
90
91
92
93
94
95
96
97
98 @DefaultDataContext
99 public LeastSquaresTleGenerationAlgorithm(final int maxIterations) {
100 this(maxIterations, DataContext.getDefault().getTimeScales().getUTC(),
101 DataContext.getDefault().getFrames().getTEME());
102 }
103
104
105
106
107
108
109
110 public LeastSquaresTleGenerationAlgorithm(final int maxIterations,
111 final TimeScale utc, final Frame teme) {
112 this.maxIterations = maxIterations;
113 this.utc = utc;
114 this.teme = teme;
115 this.rms = Double.MAX_VALUE;
116 }
117
118
119 @Override
120 public TLE generate(final SpacecraftState state, final TLE templateTLE) {
121
122
123 final AbsoluteDate epoch = state.getDate();
124
125
126 final RealVector stateVector = MatrixUtils.createRealVector(6);
127
128 final Vector3D position = state.getPVCoordinates().getPosition();
129 final Vector3D velocity = state.getPVCoordinates().getVelocity();
130
131
132 stateVector.setEntry(0, position.getX());
133 stateVector.setEntry(1, position.getY());
134 stateVector.setEntry(2, position.getZ());
135 stateVector.setEntry(3, velocity.getX());
136 stateVector.setEntry(4, velocity.getY());
137 stateVector.setEntry(5, velocity.getZ());
138
139
140 final RealVector startState = MatrixUtils.createRealVector(7);
141 startState.setSubVector(0, stateVector.getSubVector(0, 6));
142
143
144 final double[] weights = new double[6];
145 final double velocityWeight = state.getPVCoordinates().getVelocity().getNorm() * state.getPosition().getNormSq() / state.getMu();
146 for (int i = 0; i < 3; i++) {
147 weights[i] = 1.0;
148 weights[i + 3] = velocityWeight;
149 }
150
151
152 final double dt = state.getDate().durationFrom(templateTLE.getDate());
153
154
155 final LeastSquaresProblem problem =
156 new LeastSquaresBuilder().maxIterations(maxIterations)
157 .maxEvaluations(maxIterations)
158 .model(new ObjectiveFunction(templateTLE, dt))
159 .target(stateVector)
160 .weight(new DiagonalMatrix(weights))
161 .start(startState)
162 .build();
163
164
165 final LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
166 final LeastSquaresOptimizer.Optimum optimum = optimizer.optimize(problem);
167 rms = optimum.getRMS();
168
169
170 final Vector3D positionEstimated = new Vector3D(optimum.getPoint().getSubVector(0, 3).toArray());
171 final Vector3D velocityEstimated = new Vector3D(optimum.getPoint().getSubVector(3, 3).toArray());
172 final PVCoordinates pvCoordinates = new PVCoordinates(positionEstimated, velocityEstimated);
173 final KeplerianOrbit orbit = new KeplerianOrbit(pvCoordinates, teme, epoch, state.getMu());
174 final TLE generated = TleGenerationUtil.newTLE(orbit, templateTLE, templateTLE.getBStar(), utc);
175
176
177 for (final ParameterDriver templateDrivers : templateTLE.getParametersDrivers()) {
178 if (templateDrivers.isSelected()) {
179
180 generated.getParameterDriver(templateDrivers.getName()).setSelected(true);
181 }
182 }
183
184
185 return generated;
186
187 }
188
189
190
191
192
193
194
195
196
197
198 public double getRms() {
199 return rms;
200 }
201
202
203 @Override
204 public <T extends CalculusFieldElement<T>> FieldTLE<T> generate(final FieldSpacecraftState<T> state,
205 final FieldTLE<T> templateTLE) {
206 throw new UnsupportedOperationException();
207 }
208
209
210 private class ObjectiveFunction implements MultivariateJacobianFunction {
211
212
213 private final FieldTLE<Gradient> templateTLE;
214
215
216 private final double dt;
217
218
219
220
221
222
223 ObjectiveFunction(final TLE templateTLE, final double dt) {
224 this.dt = dt;
225
226 final Field<Gradient> field = GradientField.getField(7);
227 this.templateTLE = new FieldTLE<>(field, templateTLE.getLine1(), templateTLE.getLine2(), utc);
228 }
229
230
231 @Override
232 public Pair<RealVector, RealMatrix> value(final RealVector point) {
233 final RealVector objectiveOscState = MatrixUtils.createRealVector(6);
234 final RealMatrix objectiveJacobian = MatrixUtils.createRealMatrix(6, 7);
235 getTransformedAndJacobian(state -> meanStateToPV(state), point, objectiveOscState, objectiveJacobian);
236 return new Pair<>(objectiveOscState, objectiveJacobian);
237 }
238
239
240
241
242
243
244
245
246 private void getTransformedAndJacobian(final UnaryOperator<FieldVector<Gradient>> operator,
247 final RealVector state, final RealVector transformed,
248 final RealMatrix jacobian) {
249
250
251 final int stateDim = state.getDimension();
252
253
254 final GradientField field = GradientField.getField(stateDim);
255 final FieldVector<Gradient> fieldState = MatrixUtils.createFieldVector(field, stateDim);
256 for (int i = 0; i < stateDim; ++i) {
257 fieldState.setEntry(i, Gradient.variable(stateDim, i, state.getEntry(i)));
258 }
259
260
261 final FieldVector<Gradient> fieldTransformed = operator.apply(fieldState);
262
263
264 final int outDim = fieldTransformed.getDimension();
265
266
267 for (int i = 0; i < outDim; ++i) {
268 transformed.setEntry(i, fieldTransformed.getEntry(i).getReal());
269 jacobian.setRow(i, fieldTransformed.getEntry(i).getGradient());
270 }
271
272 }
273
274
275
276
277
278
279 private FieldVector<Gradient> meanStateToPV(final FieldVector<Gradient> state) {
280
281 final FieldAbsoluteDate<Gradient> epoch = templateTLE.getDate();
282
283
284 final Gradient[] bStar = state.getSubVector(6, 1).toArray();
285
286
287 final Field<Gradient> field = epoch.getField();
288
289
290 final FieldVector3D<Gradient> position = new FieldVector3D<>(state.getSubVector(0, 3).toArray());
291 final FieldVector3D<Gradient> velocity = new FieldVector3D<>(state.getSubVector(3, 3).toArray());
292 final FieldPVCoordinates<Gradient> pvCoordinates = new FieldPVCoordinates<>(position, velocity);
293 final FieldKeplerianOrbit<Gradient> orbit = new FieldKeplerianOrbit<>(pvCoordinates, teme, epoch, field.getZero().newInstance(TLEPropagator.getMU()));
294
295
296 final FieldTLE<Gradient> tle = TleGenerationUtil.newTLE(orbit, templateTLE, bStar[0], utc);
297
298
299 final FieldPVCoordinates<Gradient> propagatedCoordinates =
300 FieldTLEPropagator.selectExtrapolator(tle, teme, bStar).getPVCoordinates(epoch.shiftedBy(dt), bStar);
301
302
303 final FieldVector<Gradient> osculating = MatrixUtils.createFieldVector(field, 6);
304 osculating.setEntry(0, propagatedCoordinates.getPosition().getX());
305 osculating.setEntry(1, propagatedCoordinates.getPosition().getY());
306 osculating.setEntry(2, propagatedCoordinates.getPosition().getZ());
307 osculating.setEntry(3, propagatedCoordinates.getVelocity().getX());
308 osculating.setEntry(4, propagatedCoordinates.getVelocity().getY());
309 osculating.setEntry(5, propagatedCoordinates.getVelocity().getZ());
310
311
312 return osculating;
313
314 }
315
316 }
317
318 }