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