1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.leastsquares;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.IdentityHashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.hipparchus.linear.Array2DRowRealMatrix;
28 import org.hipparchus.linear.ArrayRealVector;
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.MultivariateJacobianFunction;
33 import org.hipparchus.util.FastMath;
34 import org.hipparchus.util.Incrementor;
35 import org.hipparchus.util.Pair;
36 import org.orekit.estimation.measurements.EstimatedMeasurement;
37 import org.orekit.estimation.measurements.ObservedMeasurement;
38 import org.orekit.orbits.Orbit;
39 import org.orekit.propagation.MatricesHarvester;
40 import org.orekit.propagation.Propagator;
41 import org.orekit.propagation.PropagatorsParallelizer;
42 import org.orekit.propagation.SpacecraftState;
43 import org.orekit.propagation.conversion.OrbitDeterminationPropagatorBuilder;
44 import org.orekit.propagation.integration.AbstractJacobiansMapper;
45 import org.orekit.propagation.sampling.MultiSatStepHandler;
46 import org.orekit.time.AbsoluteDate;
47 import org.orekit.time.ChronologicalComparator;
48 import org.orekit.utils.ParameterDriver;
49 import org.orekit.utils.ParameterDriversList;
50 import org.orekit.utils.ParameterDriversList.DelegatingDriver;
51
52
53
54
55
56
57
58
59
60 public abstract class AbstractBatchLSModel implements MultivariateJacobianFunction {
61
62
63 private final OrbitDeterminationPropagatorBuilder[] builders;
64
65
66
67
68 private final ParameterDriversList[] estimatedOrbitalParameters;
69
70
71 private final ParameterDriversList[] estimatedPropagationParameters;
72
73
74 private final ParameterDriversList estimatedMeasurementsParameters;
75
76
77 private final List<ObservedMeasurement<?>> measurements;
78
79
80 private final int[] orbitsStartColumns;
81
82
83 private final int[] orbitsEndColumns;
84
85
86 private final Map<String, Integer> propagationParameterColumns;
87
88
89 private final Map<String, Integer> measurementParameterColumns;
90
91
92 private final Map<ObservedMeasurement<?>, EstimatedMeasurement<?>> evaluations;
93
94
95 private final ModelObserver observer;
96
97
98 private Incrementor evaluationsCounter;
99
100
101 private Incrementor iterationsCounter;
102
103
104 private AbsoluteDate firstDate;
105
106
107 private AbsoluteDate lastDate;
108
109
110 private final boolean forwardPropagation;
111
112
113 private RealVector value;
114
115
116
117
118 private final MatricesHarvester[] harvesters;
119
120
121 private RealMatrix jacobian;
122
123
124
125
126
127
128
129
130
131
132
133 @Deprecated
134 public AbstractBatchLSModel(final OrbitDeterminationPropagatorBuilder[] propagatorBuilders,
135 final List<ObservedMeasurement<?>> measurements,
136 final ParameterDriversList estimatedMeasurementsParameters,
137 final MatricesHarvester[] harvesters,
138 final ModelObserver observer) {
139 this(propagatorBuilders, measurements, estimatedMeasurementsParameters, observer);
140 }
141
142
143
144
145
146
147
148
149 public AbstractBatchLSModel(final OrbitDeterminationPropagatorBuilder[] propagatorBuilders,
150 final List<ObservedMeasurement<?>> measurements,
151 final ParameterDriversList estimatedMeasurementsParameters,
152 final ModelObserver observer) {
153
154 this.builders = propagatorBuilders.clone();
155 this.measurements = measurements;
156 this.estimatedMeasurementsParameters = estimatedMeasurementsParameters;
157 this.measurementParameterColumns = new HashMap<>(estimatedMeasurementsParameters.getDrivers().size());
158 this.estimatedOrbitalParameters = new ParameterDriversList[builders.length];
159 this.estimatedPropagationParameters = new ParameterDriversList[builders.length];
160 this.evaluations = new IdentityHashMap<>(measurements.size());
161 this.observer = observer;
162 this.harvesters = new MatricesHarvester[builders.length];
163
164
165 int rows = 0;
166 for (final ObservedMeasurement<?> measurement : measurements) {
167 rows += measurement.getDimension();
168 }
169
170 this.orbitsStartColumns = new int[builders.length];
171 this.orbitsEndColumns = new int[builders.length];
172 int columns = 0;
173 for (int i = 0; i < builders.length; ++i) {
174 this.orbitsStartColumns[i] = columns;
175 for (final ParameterDriver driver : builders[i].getOrbitalParametersDrivers().getDrivers()) {
176 if (driver.isSelected()) {
177 ++columns;
178 }
179 }
180 this.orbitsEndColumns[i] = columns;
181 }
182
183
184 final List<String> estimatedPropagationParametersNames = new ArrayList<>();
185 for (int i = 0; i < builders.length; ++i) {
186
187
188 for (final DelegatingDriver delegating : getSelectedPropagationDriversForBuilder(i).getDrivers()) {
189 final String driverName = delegating.getName();
190
191 if (!estimatedPropagationParametersNames.contains(driverName)) {
192 estimatedPropagationParametersNames.add(driverName);
193 }
194 }
195 }
196
197 propagationParameterColumns = new HashMap<>(estimatedPropagationParametersNames.size());
198 for (final String driverName : estimatedPropagationParametersNames) {
199 propagationParameterColumns.put(driverName, columns);
200 ++columns;
201 }
202
203
204 for (final ParameterDriver parameter : estimatedMeasurementsParameters.getDrivers()) {
205 measurementParameterColumns.put(parameter.getName(), columns);
206 ++columns;
207 }
208
209
210 value = new ArrayRealVector(rows);
211 jacobian = MatrixUtils.createRealMatrix(rows, columns);
212
213
214
215
216 final AbsoluteDate refDate = builders[0].getInitialOrbitDate();
217
218
219 measurements.sort(new ChronologicalComparator());
220 firstDate = measurements.get(0).getDate();
221 lastDate = measurements.get(measurements.size() - 1).getDate();
222
223
224 if (FastMath.abs(refDate.durationFrom(firstDate)) <= FastMath.abs(refDate.durationFrom(lastDate))) {
225
226 forwardPropagation = true;
227 } else {
228
229 forwardPropagation = false;
230 }
231 }
232
233
234
235
236 public void setEvaluationsCounter(final Incrementor evaluationsCounter) {
237 this.evaluationsCounter = evaluationsCounter;
238 }
239
240
241
242
243 public void setIterationsCounter(final Incrementor iterationsCounter) {
244 this.iterationsCounter = iterationsCounter;
245 }
246
247
248
249
250 public boolean isForwardPropagation() {
251 return forwardPropagation;
252 }
253
254
255
256
257
258 protected MatricesHarvester configureHarvester(final Propagator propagator) {
259
260
261 return configureDerivatives(propagator);
262 }
263
264
265
266
267
268
269 @Deprecated
270 protected abstract AbstractJacobiansMapper configureDerivatives(Propagator propagators);
271
272
273
274
275
276
277
278
279
280 protected abstract Orbit configureOrbits(MatricesHarvester harvester, Propagator propagator);
281
282
283 @Override
284 public Pair<RealVector, RealMatrix> value(final RealVector point) {
285
286
287 final Propagator[] propagators = createPropagators(point);
288 final Orbit[] orbits = new Orbit[propagators.length];
289 for (int i = 0; i < propagators.length; ++i) {
290 harvesters[i] = configureHarvester(propagators[i]);
291 orbits[i] = configureOrbits(harvesters[i], propagators[i]);
292 }
293 final PropagatorsParallelizer parallelizer =
294 new PropagatorsParallelizer(Arrays.asList(propagators), configureMeasurements(point));
295
296
297 evaluations.clear();
298 value.set(0.0);
299 for (int i = 0; i < jacobian.getRowDimension(); ++i) {
300 for (int j = 0; j < jacobian.getColumnDimension(); ++j) {
301 jacobian.setEntry(i, j, 0.0);
302 }
303 }
304
305
306 if (isForwardPropagation()) {
307
308 parallelizer.propagate(firstDate.shiftedBy(-1.0), lastDate.shiftedBy(+1.0));
309 } else {
310
311 parallelizer.propagate(lastDate.shiftedBy(+1.0), firstDate.shiftedBy(-1.0));
312 }
313
314 observer.modelCalled(orbits, evaluations);
315
316 return new Pair<RealVector, RealMatrix>(value, jacobian);
317
318 }
319
320
321
322
323
324
325 public ParameterDriversList getSelectedOrbitalParametersDriversForBuilder(final int iBuilder) {
326
327
328 if (estimatedOrbitalParameters[iBuilder] == null) {
329
330
331 final ParameterDriversList selectedOrbitalDrivers = new ParameterDriversList();
332 for (final DelegatingDriver delegating : builders[iBuilder].getOrbitalParametersDrivers().getDrivers()) {
333 if (delegating.isSelected()) {
334 for (final ParameterDriver driver : delegating.getRawDrivers()) {
335 selectedOrbitalDrivers.add(driver);
336 }
337 }
338 }
339
340
341 estimatedOrbitalParameters[iBuilder] = selectedOrbitalDrivers;
342 }
343 return estimatedOrbitalParameters[iBuilder];
344 }
345
346
347
348
349
350 public ParameterDriversList getSelectedPropagationDriversForBuilder(final int iBuilder) {
351
352
353 if (estimatedPropagationParameters[iBuilder] == null) {
354
355
356 final ParameterDriversList selectedPropagationDrivers = new ParameterDriversList();
357 for (final DelegatingDriver delegating : builders[iBuilder].getPropagationParametersDrivers().getDrivers()) {
358 if (delegating.isSelected()) {
359 for (final ParameterDriver driver : delegating.getRawDrivers()) {
360 selectedPropagationDrivers.add(driver);
361 }
362 }
363 }
364
365
366
367 selectedPropagationDrivers.sort();
368
369
370 estimatedPropagationParameters[iBuilder] = selectedPropagationDrivers;
371 }
372 return estimatedPropagationParameters[iBuilder];
373 }
374
375
376
377
378
379 public Propagator[] createPropagators(final RealVector point) {
380
381 final Propagator[] propagators = new Propagator[builders.length];
382
383
384 for (int i = 0; i < builders.length; ++i) {
385
386
387 final int nbOrb = orbitsEndColumns[i] - orbitsStartColumns[i];
388
389
390 final ParameterDriversList selectedPropagationDrivers = getSelectedPropagationDriversForBuilder(i);
391 final int nbParams = selectedPropagationDrivers.getNbParams();
392
393
394 final double[] propagatorArray = new double[nbOrb + nbParams];
395
396
397 for (int j = 0; j < nbOrb; ++j) {
398 propagatorArray[j] = point.getEntry(orbitsStartColumns[i] + j);
399 }
400
401
402 for (int j = 0; j < nbParams; ++j) {
403 propagatorArray[nbOrb + j] =
404 point.getEntry(propagationParameterColumns.get(selectedPropagationDrivers.getDrivers().get(j).getName()));
405 }
406
407
408 propagators[i] = builders[i].buildPropagator(propagatorArray);
409 }
410
411 return propagators;
412
413 }
414
415
416
417
418
419 public void fetchEvaluatedMeasurement(final int index, final EstimatedMeasurement<?> evaluation) {
420
421
422 final SpacecraftState[] evaluationStates = evaluation.getStates();
423 final ObservedMeasurement<?> observedMeasurement = evaluation.getObservedMeasurement();
424
425
426 evaluations.put(observedMeasurement, evaluation);
427 if (evaluation.getStatus() == EstimatedMeasurement.Status.REJECTED) {
428 return;
429 }
430
431 final double[] evaluated = evaluation.getEstimatedValue();
432 final double[] observed = observedMeasurement.getObservedValue();
433 final double[] sigma = observedMeasurement.getTheoreticalStandardDeviation();
434 final double[] weight = evaluation.getObservedMeasurement().getBaseWeight();
435 for (int i = 0; i < evaluated.length; ++i) {
436 value.setEntry(index + i, weight[i] * (evaluated[i] - observed[i]) / sigma[i]);
437 }
438
439 for (int k = 0; k < evaluationStates.length; ++k) {
440
441 final int p = observedMeasurement.getSatellites().get(k).getPropagatorIndex();
442
443
444 final double[][] aCY = new double[6][6];
445 final Orbit currentOrbit = evaluationStates[k].getOrbit();
446 currentOrbit.getJacobianWrtParameters(builders[p].getPositionAngle(), aCY);
447 final RealMatrix dCdY = new Array2DRowRealMatrix(aCY, false);
448
449
450 final RealMatrix dMdC = new Array2DRowRealMatrix(evaluation.getStateDerivatives(k), false);
451 final RealMatrix dMdY = dMdC.multiply(dCdY);
452
453
454 final ParameterDriversList selectedOrbitalDrivers = getSelectedOrbitalParametersDriversForBuilder(p);
455 final int nbOrbParams = selectedOrbitalDrivers.getNbParams();
456 if (nbOrbParams > 0) {
457 final RealMatrix dYdY0 = harvesters[p].getStateTransitionMatrix(evaluationStates[k]);
458 final RealMatrix dMdY0 = dMdY.multiply(dYdY0);
459 for (int i = 0; i < dMdY0.getRowDimension(); ++i) {
460 int jOrb = orbitsStartColumns[p];
461 for (int j = 0; j < dMdY0.getColumnDimension(); ++j) {
462 final ParameterDriver driver = selectedOrbitalDrivers.getDrivers().get(j);
463 jacobian.setEntry(index + i, jOrb++,
464 weight[i] * dMdY0.getEntry(i, j) / sigma[i] * driver.getScale());
465 }
466 }
467 }
468
469
470 final ParameterDriversList selectedPropagationDrivers = getSelectedPropagationDriversForBuilder(p);
471 final int nbParams = selectedPropagationDrivers.getNbParams();
472 if (nbParams > 0) {
473 final RealMatrix dYdPp = harvesters[p].getParametersJacobian(evaluationStates[k]);
474 final RealMatrix dMdPp = dMdY.multiply(dYdPp);
475 for (int i = 0; i < dMdPp.getRowDimension(); ++i) {
476 for (int j = 0; j < nbParams; ++j) {
477 final ParameterDriver delegating = selectedPropagationDrivers.getDrivers().get(j);
478 jacobian.addToEntry(index + i, propagationParameterColumns.get(delegating.getName()),
479 weight[i] * dMdPp.getEntry(i, j) / sigma[i] * delegating.getScale());
480 }
481 }
482 }
483 }
484
485 for (final ParameterDriver driver : observedMeasurement.getParametersDrivers()) {
486 if (driver.isSelected()) {
487 final double[] aMPm = evaluation.getParameterDerivatives(driver);
488 for (int i = 0; i < aMPm.length; ++i) {
489 jacobian.setEntry(index + i, measurementParameterColumns.get(driver.getName()),
490 weight[i] * aMPm[i] / sigma[i] * driver.getScale());
491 }
492 }
493 }
494
495 }
496
497
498
499
500
501 private MultiSatStepHandler configureMeasurements(final RealVector point) {
502
503
504 int index = orbitsEndColumns[builders.length - 1] + propagationParameterColumns.size();
505 for (final ParameterDriver parameter : estimatedMeasurementsParameters.getDrivers()) {
506 parameter.setNormalizedValue(point.getEntry(index++));
507 }
508
509
510 final List<PreCompensation> precompensated = new ArrayList<>();
511 for (final ObservedMeasurement<?> measurement : measurements) {
512 if (measurement.isEnabled()) {
513 precompensated.add(new PreCompensation(measurement, evaluations.get(measurement)));
514 }
515 }
516 precompensated.sort(new ChronologicalComparator());
517
518
519 firstDate = precompensated.get(0).getDate();
520 lastDate = precompensated.get(precompensated.size() - 1).getDate();
521
522
523 if (!forwardPropagation) {
524 Collections.reverse(precompensated);
525 }
526
527 return new MeasurementHandler(this, precompensated);
528
529 }
530
531
532
533
534 public int getIterationsCount() {
535 return iterationsCounter.getCount();
536 }
537
538
539
540
541 public int getEvaluationsCount() {
542 return evaluationsCounter.getCount();
543 }
544
545 }