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