1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.sequential;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Comparator;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.hipparchus.filtering.kalman.ProcessEstimate;
27 import org.hipparchus.filtering.kalman.extended.NonLinearEvolution;
28 import org.hipparchus.filtering.kalman.extended.NonLinearProcess;
29 import org.hipparchus.linear.Array2DRowRealMatrix;
30 import org.hipparchus.linear.ArrayRealVector;
31 import org.hipparchus.linear.MatrixUtils;
32 import org.hipparchus.linear.RealMatrix;
33 import org.hipparchus.linear.RealVector;
34 import org.hipparchus.util.FastMath;
35 import org.orekit.errors.OrekitException;
36 import org.orekit.errors.OrekitMessages;
37 import org.orekit.estimation.measurements.EstimatedMeasurement;
38 import org.orekit.estimation.measurements.EstimationModifier;
39 import org.orekit.estimation.measurements.ObservableSatellite;
40 import org.orekit.estimation.measurements.ObservedMeasurement;
41 import org.orekit.estimation.measurements.modifiers.DynamicOutlierFilter;
42 import org.orekit.orbits.Orbit;
43 import org.orekit.propagation.PropagationType;
44 import org.orekit.propagation.Propagator;
45 import org.orekit.propagation.SpacecraftState;
46 import org.orekit.propagation.conversion.OrbitDeterminationPropagatorBuilder;
47 import org.orekit.propagation.integration.AbstractJacobiansMapper;
48 import org.orekit.time.AbsoluteDate;
49 import org.orekit.utils.ParameterDriver;
50 import org.orekit.utils.ParameterDriversList;
51 import org.orekit.utils.ParameterDriversList.DelegatingDriver;
52
53
54
55
56
57
58
59
60 public abstract class AbstractKalmanModel implements KalmanEstimation, NonLinearProcess<MeasurementDecorator> {
61
62
63 private final List<OrbitDeterminationPropagatorBuilder> builders;
64
65
66 private final ParameterDriversList allEstimatedOrbitalParameters;
67
68
69 private final ParameterDriversList allEstimatedPropagationParameters;
70
71
72 private final ParameterDriversList[] estimatedPropagationParameters;
73
74
75 private final ParameterDriversList estimatedMeasurementsParameters;
76
77
78 private final int[] orbitsStartColumns;
79
80
81 private final int[] orbitsEndColumns;
82
83
84 private final Map<String, Integer> propagationParameterColumns;
85
86
87 private final Map<String, Integer> measurementParameterColumns;
88
89
90 private final List<CovarianceMatrixProvider> covarianceMatricesProviders;
91
92
93 private final CovarianceMatrixProvider measurementProcessNoiseMatrix;
94
95
96 private final int[][] covarianceIndirection;
97
98
99 private final double[] scale;
100
101
102 private AbstractJacobiansMapper[] mappers;
103
104
105 private Propagator[] referenceTrajectories;
106
107
108 private ProcessEstimate correctedEstimate;
109
110
111 private int currentMeasurementNumber;
112
113
114 private AbsoluteDate referenceDate;
115
116
117 private AbsoluteDate currentDate;
118
119
120 private SpacecraftState[] predictedSpacecraftStates;
121
122
123 private SpacecraftState[] correctedSpacecraftStates;
124
125
126 private EstimatedMeasurement<?> predictedMeasurement;
127
128
129 private EstimatedMeasurement<?> correctedMeasurement;
130
131
132 private PropagationType propagationType;
133
134
135 private PropagationType stateType;
136
137
138
139
140
141
142
143
144
145
146 protected AbstractKalmanModel(final List<OrbitDeterminationPropagatorBuilder> propagatorBuilders,
147 final List<CovarianceMatrixProvider> covarianceMatricesProviders,
148 final ParameterDriversList estimatedMeasurementParameters,
149 final CovarianceMatrixProvider measurementProcessNoiseMatrix,
150 final AbstractJacobiansMapper[] mappers) {
151 this(propagatorBuilders, covarianceMatricesProviders, estimatedMeasurementParameters,
152 measurementProcessNoiseMatrix, mappers, PropagationType.MEAN, PropagationType.MEAN);
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166 protected AbstractKalmanModel(final List<OrbitDeterminationPropagatorBuilder> propagatorBuilders,
167 final List<CovarianceMatrixProvider> covarianceMatricesProviders,
168 final ParameterDriversList estimatedMeasurementParameters,
169 final CovarianceMatrixProvider measurementProcessNoiseMatrix,
170 final AbstractJacobiansMapper[] mappers,
171 final PropagationType propagationType,
172 final PropagationType stateType) {
173
174 this.builders = propagatorBuilders;
175 this.estimatedMeasurementsParameters = estimatedMeasurementParameters;
176 this.measurementParameterColumns = new HashMap<>(estimatedMeasurementsParameters.getDrivers().size());
177 this.currentMeasurementNumber = 0;
178 this.referenceDate = propagatorBuilders.get(0).getInitialOrbitDate();
179 this.currentDate = referenceDate;
180 this.propagationType = propagationType;
181 this.stateType = stateType;
182
183 final Map<String, Integer> orbitalParameterColumns = new HashMap<>(6 * builders.size());
184 orbitsStartColumns = new int[builders.size()];
185 orbitsEndColumns = new int[builders.size()];
186 int columns = 0;
187 allEstimatedOrbitalParameters = new ParameterDriversList();
188 for (int k = 0; k < builders.size(); ++k) {
189 orbitsStartColumns[k] = columns;
190 final String suffix = propagatorBuilders.size() > 1 ? "[" + k + "]" : null;
191 for (final ParameterDriver driver : builders.get(k).getOrbitalParametersDrivers().getDrivers()) {
192 if (driver.getReferenceDate() == null) {
193 driver.setReferenceDate(currentDate);
194 }
195 if (suffix != null && !driver.getName().endsWith(suffix)) {
196
197
198 driver.setName(driver.getName() + suffix);
199 }
200 if (driver.isSelected()) {
201 allEstimatedOrbitalParameters.add(driver);
202 orbitalParameterColumns.put(driver.getName(), columns++);
203 }
204 }
205 orbitsEndColumns[k] = columns;
206 }
207
208
209 allEstimatedPropagationParameters = new ParameterDriversList();
210 estimatedPropagationParameters = new ParameterDriversList[builders.size()];
211 final List<String> estimatedPropagationParametersNames = new ArrayList<>();
212 for (int k = 0; k < builders.size(); ++k) {
213 estimatedPropagationParameters[k] = new ParameterDriversList();
214 for (final ParameterDriver driver : builders.get(k).getPropagationParametersDrivers().getDrivers()) {
215 if (driver.getReferenceDate() == null) {
216 driver.setReferenceDate(currentDate);
217 }
218 if (driver.isSelected()) {
219 allEstimatedPropagationParameters.add(driver);
220 estimatedPropagationParameters[k].add(driver);
221 final String driverName = driver.getName();
222
223 if (!estimatedPropagationParametersNames.contains(driverName)) {
224 estimatedPropagationParametersNames.add(driverName);
225 }
226 }
227 }
228 }
229 estimatedPropagationParametersNames.sort(Comparator.naturalOrder());
230
231
232 propagationParameterColumns = new HashMap<>(estimatedPropagationParametersNames.size());
233 for (final String driverName : estimatedPropagationParametersNames) {
234 propagationParameterColumns.put(driverName, columns);
235 ++columns;
236 }
237
238
239 for (final ParameterDriver parameter : estimatedMeasurementsParameters.getDrivers()) {
240 if (parameter.getReferenceDate() == null) {
241 parameter.setReferenceDate(currentDate);
242 }
243 measurementParameterColumns.put(parameter.getName(), columns);
244 ++columns;
245 }
246
247
248 this.covarianceMatricesProviders = covarianceMatricesProviders;
249 this.measurementProcessNoiseMatrix = measurementProcessNoiseMatrix;
250 this.covarianceIndirection = new int[covarianceMatricesProviders.size()][columns];
251 for (int k = 0; k < covarianceIndirection.length; ++k) {
252 final ParameterDriversList orbitDrivers = builders.get(k).getOrbitalParametersDrivers();
253 final ParameterDriversList parametersDrivers = builders.get(k).getPropagationParametersDrivers();
254 Arrays.fill(covarianceIndirection[k], -1);
255 int i = 0;
256 for (final ParameterDriver driver : orbitDrivers.getDrivers()) {
257 final Integer c = orbitalParameterColumns.get(driver.getName());
258 covarianceIndirection[k][i++] = (c == null) ? -1 : c.intValue();
259 }
260 for (final ParameterDriver driver : parametersDrivers.getDrivers()) {
261 final Integer c = propagationParameterColumns.get(driver.getName());
262 if (c != null) {
263 covarianceIndirection[k][i++] = c.intValue();
264 }
265 }
266 for (final ParameterDriver driver : estimatedMeasurementParameters.getDrivers()) {
267 final Integer c = measurementParameterColumns.get(driver.getName());
268 if (c != null) {
269 covarianceIndirection[k][i++] = c.intValue();
270 }
271 }
272 }
273
274
275 this.scale = new double[columns];
276 int index = 0;
277 for (final ParameterDriver driver : allEstimatedOrbitalParameters.getDrivers()) {
278 scale[index++] = driver.getScale();
279 }
280 for (final ParameterDriver driver : allEstimatedPropagationParameters.getDrivers()) {
281 scale[index++] = driver.getScale();
282 }
283 for (final ParameterDriver driver : estimatedMeasurementsParameters.getDrivers()) {
284 scale[index++] = driver.getScale();
285 }
286
287
288 this.mappers = mappers.clone();
289 updateReferenceTrajectories(getEstimatedPropagators(), propagationType, stateType);
290 this.predictedSpacecraftStates = new SpacecraftState[referenceTrajectories.length];
291 for (int i = 0; i < predictedSpacecraftStates.length; ++i) {
292 predictedSpacecraftStates[i] = referenceTrajectories[i].getInitialState();
293 };
294 this.correctedSpacecraftStates = predictedSpacecraftStates.clone();
295
296
297 final RealVector correctedState = MatrixUtils.createRealVector(columns);
298
299 int p = 0;
300 for (final ParameterDriver driver : allEstimatedOrbitalParameters.getDrivers()) {
301 correctedState.setEntry(p++, driver.getNormalizedValue());
302 }
303 for (final ParameterDriver driver : allEstimatedPropagationParameters.getDrivers()) {
304 correctedState.setEntry(p++, driver.getNormalizedValue());
305 }
306 for (final ParameterDriver driver : estimatedMeasurementsParameters.getDrivers()) {
307 correctedState.setEntry(p++, driver.getNormalizedValue());
308 }
309
310
311 final RealMatrix physicalProcessNoise = MatrixUtils.createRealMatrix(columns, columns);
312 for (int k = 0; k < covarianceMatricesProviders.size(); ++k) {
313
314
315 final int nbMeas = estimatedMeasurementParameters.getNbParams();
316
317
318 final int nbDyn = orbitsEndColumns[k] - orbitsStartColumns[k] +
319 estimatedPropagationParameters[k].getNbParams();
320
321
322 final RealMatrix noiseK = MatrixUtils.createRealMatrix(nbDyn + nbMeas, nbDyn + nbMeas);
323 final RealMatrix noiseP = covarianceMatricesProviders.get(k).
324 getInitialCovarianceMatrix(correctedSpacecraftStates[k]);
325 noiseK.setSubMatrix(noiseP.getData(), 0, 0);
326 if (measurementProcessNoiseMatrix != null) {
327 final RealMatrix noiseM = measurementProcessNoiseMatrix.
328 getInitialCovarianceMatrix(correctedSpacecraftStates[k]);
329 noiseK.setSubMatrix(noiseM.getData(), nbDyn, nbDyn);
330 }
331
332 checkDimension(noiseK.getRowDimension(),
333 builders.get(k).getOrbitalParametersDrivers(),
334 builders.get(k).getPropagationParametersDrivers(),
335 estimatedMeasurementsParameters);
336
337 final int[] indK = covarianceIndirection[k];
338 for (int i = 0; i < indK.length; ++i) {
339 if (indK[i] >= 0) {
340 for (int j = 0; j < indK.length; ++j) {
341 if (indK[j] >= 0) {
342 physicalProcessNoise.setEntry(indK[i], indK[j], noiseK.getEntry(i, j));
343 }
344 }
345 }
346 }
347
348 }
349 final RealMatrix correctedCovariance = normalizeCovarianceMatrix(physicalProcessNoise);
350
351 correctedEstimate = new ProcessEstimate(0.0, correctedState, correctedCovariance);
352
353 }
354
355
356
357
358
359
360 protected abstract void updateReferenceTrajectories(Propagator[] propagators,
361 PropagationType pType,
362 PropagationType sType);
363
364
365
366
367
368
369 protected abstract void analyticalDerivativeComputations(AbstractJacobiansMapper mapper, SpacecraftState state);
370
371
372
373
374
375
376
377 private void checkDimension(final int dimension,
378 final ParameterDriversList orbitalParameters,
379 final ParameterDriversList propagationParameters,
380 final ParameterDriversList measurementParameters) {
381
382
383
384 int requiredDimension = orbitalParameters.getNbParams();
385 for (final ParameterDriver driver : propagationParameters.getDrivers()) {
386 if (driver.isSelected()) {
387 ++requiredDimension;
388 }
389 }
390 for (final ParameterDriver driver : measurementParameters.getDrivers()) {
391 if (driver.isSelected()) {
392 ++requiredDimension;
393 }
394 }
395
396 if (dimension != requiredDimension) {
397
398 final StringBuilder builder = new StringBuilder();
399 for (final ParameterDriver driver : orbitalParameters.getDrivers()) {
400 if (builder.length() > 0) {
401 builder.append(", ");
402 }
403 builder.append(driver.getName());
404 }
405 for (final ParameterDriver driver : propagationParameters.getDrivers()) {
406 if (driver.isSelected()) {
407 builder.append(driver.getName());
408 }
409 }
410 for (final ParameterDriver driver : measurementParameters.getDrivers()) {
411 if (driver.isSelected()) {
412 builder.append(driver.getName());
413 }
414 }
415 throw new OrekitException(OrekitMessages.DIMENSION_INCONSISTENT_WITH_PARAMETERS,
416 dimension, builder.toString());
417 }
418
419 }
420
421
422 @Override
423 public RealMatrix getPhysicalStateTransitionMatrix() {
424
425
426
427
428
429
430 final RealMatrix normalizedSTM = correctedEstimate.getStateTransitionMatrix();
431
432 if (normalizedSTM == null) {
433 return null;
434 } else {
435
436 final int nbParams = normalizedSTM.getRowDimension();
437 final RealMatrix physicalSTM = MatrixUtils.createRealMatrix(nbParams, nbParams);
438
439
440 for (int i = 0; i < nbParams; ++i) {
441 for (int j = 0; j < nbParams; ++j) {
442 physicalSTM.setEntry(i, j,
443 normalizedSTM.getEntry(i, j) * scale[i] / scale[j]);
444 }
445 }
446 return physicalSTM;
447 }
448 }
449
450
451 @Override
452 public RealMatrix getPhysicalMeasurementJacobian() {
453
454
455
456
457
458
459
460
461 final RealMatrix normalizedH = correctedEstimate.getMeasurementJacobian();
462
463 if (normalizedH == null) {
464 return null;
465 } else {
466
467 final double[] sigmas = correctedMeasurement.getObservedMeasurement().getTheoreticalStandardDeviation();
468
469
470 final int nbLine = normalizedH.getRowDimension();
471 final int nbCol = normalizedH.getColumnDimension();
472 final RealMatrix physicalH = MatrixUtils.createRealMatrix(nbLine, nbCol);
473
474
475 for (int i = 0; i < nbLine; ++i) {
476 for (int j = 0; j < nbCol; ++j) {
477 physicalH.setEntry(i, j, normalizedH.getEntry(i, j) * sigmas[i] / scale[j]);
478 }
479 }
480 return physicalH;
481 }
482 }
483
484
485 @Override
486 public RealMatrix getPhysicalInnovationCovarianceMatrix() {
487
488
489
490
491
492
493 final RealMatrix normalizedS = correctedEstimate.getInnovationCovariance();
494
495 if (normalizedS == null) {
496 return null;
497 } else {
498
499 final double[] sigmas = correctedMeasurement.getObservedMeasurement().getTheoreticalStandardDeviation();
500
501
502 final int nbMeas = sigmas.length;
503 final RealMatrix physicalS = MatrixUtils.createRealMatrix(nbMeas, nbMeas);
504
505
506 for (int i = 0; i < nbMeas; ++i) {
507 for (int j = 0; j < nbMeas; ++j) {
508 physicalS.setEntry(i, j, normalizedS.getEntry(i, j) * sigmas[i] * sigmas[j]);
509 }
510 }
511 return physicalS;
512 }
513 }
514
515
516 @Override
517 public RealMatrix getPhysicalKalmanGain() {
518
519
520
521
522
523
524
525
526 final RealMatrix normalizedK = correctedEstimate.getKalmanGain();
527
528 if (normalizedK == null) {
529 return null;
530 } else {
531
532 final double[] sigmas = correctedMeasurement.getObservedMeasurement().getTheoreticalStandardDeviation();
533
534
535 final int nbLine = normalizedK.getRowDimension();
536 final int nbCol = normalizedK.getColumnDimension();
537 final RealMatrix physicalK = MatrixUtils.createRealMatrix(nbLine, nbCol);
538
539
540 for (int i = 0; i < nbLine; ++i) {
541 for (int j = 0; j < nbCol; ++j) {
542 physicalK.setEntry(i, j, normalizedK.getEntry(i, j) * scale[i] / sigmas[j]);
543 }
544 }
545 return physicalK;
546 }
547 }
548
549
550 @Override
551 public SpacecraftState[] getPredictedSpacecraftStates() {
552 return predictedSpacecraftStates.clone();
553 }
554
555
556 @Override
557 public SpacecraftState[] getCorrectedSpacecraftStates() {
558 return correctedSpacecraftStates.clone();
559 }
560
561
562 @Override
563 public int getCurrentMeasurementNumber() {
564 return currentMeasurementNumber;
565 }
566
567
568 @Override
569 public AbsoluteDate getCurrentDate() {
570 return currentDate;
571 }
572
573
574 @Override
575 public EstimatedMeasurement<?> getPredictedMeasurement() {
576 return predictedMeasurement;
577 }
578
579
580 @Override
581 public EstimatedMeasurement<?> getCorrectedMeasurement() {
582 return correctedMeasurement;
583 }
584
585
586 @Override
587 public RealVector getPhysicalEstimatedState() {
588
589
590
591 final RealVector physicalEstimatedState = new ArrayRealVector(scale.length);
592 int i = 0;
593 for (final DelegatingDriver driver : getEstimatedOrbitalParameters().getDrivers()) {
594 physicalEstimatedState.setEntry(i++, driver.getValue());
595 }
596 for (final DelegatingDriver driver : getEstimatedPropagationParameters().getDrivers()) {
597 physicalEstimatedState.setEntry(i++, driver.getValue());
598 }
599 for (final DelegatingDriver driver : getEstimatedMeasurementsParameters().getDrivers()) {
600 physicalEstimatedState.setEntry(i++, driver.getValue());
601 }
602
603 return physicalEstimatedState;
604 }
605
606
607 @Override
608 public RealMatrix getPhysicalEstimatedCovarianceMatrix() {
609
610
611
612
613
614
615
616 final RealMatrix normalizedP = correctedEstimate.getCovariance();
617
618
619 final int nbParams = normalizedP.getRowDimension();
620 final RealMatrix physicalP = MatrixUtils.createRealMatrix(nbParams, nbParams);
621
622
623 for (int i = 0; i < nbParams; ++i) {
624 for (int j = 0; j < nbParams; ++j) {
625 physicalP.setEntry(i, j, normalizedP.getEntry(i, j) * scale[i] * scale[j]);
626 }
627 }
628 return physicalP;
629 }
630
631
632 @Override
633 public ParameterDriversList getEstimatedOrbitalParameters() {
634 return allEstimatedOrbitalParameters;
635 }
636
637
638 @Override
639 public ParameterDriversList getEstimatedPropagationParameters() {
640 return allEstimatedPropagationParameters;
641 }
642
643
644 @Override
645 public ParameterDriversList getEstimatedMeasurementsParameters() {
646 return estimatedMeasurementsParameters;
647 }
648
649
650
651
652 public ProcessEstimate getEstimate() {
653 return correctedEstimate;
654 }
655
656
657
658
659
660
661
662 private RealMatrix getErrorStateTransitionMatrix() {
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686 final RealMatrix stm = MatrixUtils.createRealIdentityMatrix(correctedEstimate.getState().getDimension());
687
688
689 for (int k = 0; k < predictedSpacecraftStates.length; ++k) {
690
691
692 final int[] indK = covarianceIndirection[k];
693
694
695 analyticalDerivativeComputations(mappers[k], predictedSpacecraftStates[k]);
696
697
698 final double[][] dYdY0 = new double[6][6];
699 mappers[k].getStateJacobian(predictedSpacecraftStates[k], dYdY0 );
700
701
702 final List<ParameterDriversList.DelegatingDriver> drivers =
703 builders.get(k).getOrbitalParametersDrivers().getDrivers();
704 for (int i = 0; i < dYdY0.length; ++i) {
705 if (drivers.get(i).isSelected()) {
706 for (int j = 0; j < dYdY0[i].length; ++j) {
707 if (drivers.get(j).isSelected()) {
708 stm.setEntry(indK[i], indK[j], dYdY0[i][j]);
709 }
710 }
711 }
712 }
713
714
715 final int nbParams = estimatedPropagationParameters[k].getNbParams();
716 if (nbParams > 0) {
717 final double[][] dYdPp = new double[6][nbParams];
718 mappers[k].getParametersJacobian(predictedSpacecraftStates[k], dYdPp);
719
720
721 for (int i = 0; i < dYdPp.length; ++i) {
722 for (int j = 0; j < nbParams; ++j) {
723 stm.setEntry(indK[i], indK[j + 6], dYdPp[i][j]);
724 }
725 }
726
727 }
728
729 }
730
731
732
733 for (int i = 0; i < scale.length; i++) {
734 for (int j = 0; j < scale.length; j++ ) {
735 stm.setEntry(i, j, stm.getEntry(i, j) * scale[j] / scale[i]);
736 }
737 }
738
739
740 return stm;
741
742 }
743
744
745
746
747
748
749 private RealMatrix getMeasurementMatrix() {
750
751
752 final SpacecraftState[] evaluationStates = predictedMeasurement.getStates();
753 final ObservedMeasurement<?> observedMeasurement = predictedMeasurement.getObservedMeasurement();
754 final double[] sigma = observedMeasurement.getTheoreticalStandardDeviation();
755
756
757
758
759 final RealMatrix measurementMatrix = MatrixUtils.
760 createRealMatrix(observedMeasurement.getDimension(),
761 correctedEstimate.getState().getDimension());
762
763
764 for (int k = 0; k < evaluationStates.length; ++k) {
765 final int p = observedMeasurement.getSatellites().get(k).getPropagatorIndex();
766
767
768 final Orbit predictedOrbit = evaluationStates[k].getOrbit();
769
770
771
772
773
774 final double[][] aCY = new double[6][6];
775 predictedOrbit.getJacobianWrtParameters(builders.get(p).getPositionAngle(), aCY);
776 final RealMatrix dCdY = new Array2DRowRealMatrix(aCY, false);
777
778
779 final RealMatrix dMdC = new Array2DRowRealMatrix(predictedMeasurement.getStateDerivatives(k), false);
780
781
782 final RealMatrix dMdY = dMdC.multiply(dCdY);
783
784
785 for (int i = 0; i < dMdY.getRowDimension(); ++i) {
786 int jOrb = orbitsStartColumns[p];
787 for (int j = 0; j < dMdY.getColumnDimension(); ++j) {
788 final ParameterDriver driver = builders.get(p).getOrbitalParametersDrivers().getDrivers().get(j);
789 if (driver.isSelected()) {
790 measurementMatrix.setEntry(i, jOrb++,
791 dMdY.getEntry(i, j) / sigma[i] * driver.getScale());
792 }
793 }
794 }
795
796
797
798
799
800 final int nbParams = estimatedPropagationParameters[p].getNbParams();
801 if (nbParams > 0) {
802 final double[][] aYPp = new double[6][nbParams];
803 mappers[p].getParametersJacobian(evaluationStates[k], aYPp);
804 final RealMatrix dYdPp = new Array2DRowRealMatrix(aYPp, false);
805 final RealMatrix dMdPp = dMdY.multiply(dYdPp);
806 for (int i = 0; i < dMdPp.getRowDimension(); ++i) {
807 for (int j = 0; j < nbParams; ++j) {
808 final ParameterDriver delegating = estimatedPropagationParameters[p].getDrivers().get(j);
809 measurementMatrix.setEntry(i, propagationParameterColumns.get(delegating.getName()),
810 dMdPp.getEntry(i, j) / sigma[i] * delegating.getScale());
811 }
812 }
813 }
814
815
816
817
818
819
820 for (final ParameterDriver driver : observedMeasurement.getParametersDrivers()) {
821 if (driver.isSelected()) {
822
823 final double[] aMPm = predictedMeasurement.getParameterDerivatives(driver);
824
825
826 if (measurementParameterColumns.get(driver.getName()) != null) {
827
828 final int driverColumn = measurementParameterColumns.get(driver.getName());
829
830
831 for (int i = 0; i < aMPm.length; ++i) {
832 measurementMatrix.setEntry(i, driverColumn,
833 aMPm[i] / sigma[i] * driver.getScale());
834 }
835 }
836 }
837 }
838 }
839
840
841 return measurementMatrix;
842
843 }
844
845
846
847
848
849
850
851
852 private RealMatrix normalizeCovarianceMatrix(final RealMatrix physicalCovarianceMatrix) {
853
854
855 final int nbParams = physicalCovarianceMatrix.getRowDimension();
856 final RealMatrix normalizedCovarianceMatrix = MatrixUtils.createRealMatrix(nbParams, nbParams);
857
858
859 for (int i = 0; i < nbParams; ++i) {
860 for (int j = 0; j < nbParams; ++j) {
861 normalizedCovarianceMatrix.setEntry(i, j,
862 physicalCovarianceMatrix.getEntry(i, j) /
863 (scale[i] * scale[j]));
864 }
865 }
866 return normalizedCovarianceMatrix;
867 }
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883 private <T extends ObservedMeasurement<T>> void applyDynamicOutlierFilter(final EstimatedMeasurement<T> measurement,
884 final RealMatrix innovationCovarianceMatrix) {
885
886
887 final ObservedMeasurement<T> observedMeasurement = measurement.getObservedMeasurement();
888
889
890
891 for (EstimationModifier<T> modifier : observedMeasurement.getModifiers()) {
892 if (modifier instanceof DynamicOutlierFilter<?>) {
893 final DynamicOutlierFilter<T> dynamicOutlierFilter = (DynamicOutlierFilter<T>) modifier;
894
895
896 final double[] sigmaDynamic = new double[innovationCovarianceMatrix.getColumnDimension()];
897 final double[] sigmaMeasurement = observedMeasurement.getTheoreticalStandardDeviation();
898
899
900
901
902
903
904
905
906
907
908
909
910 for (int i = 0; i < sigmaDynamic.length; i++) {
911 sigmaDynamic[i] = FastMath.sqrt(innovationCovarianceMatrix.getEntry(i, i)) * sigmaMeasurement[i];
912 }
913 dynamicOutlierFilter.setSigma(sigmaDynamic);
914
915
916 modifier.modify(measurement);
917
918
919 dynamicOutlierFilter.setSigma(null);
920 }
921 }
922 }
923
924
925 @Override
926 public NonLinearEvolution getEvolution(final double previousTime, final RealVector previousState,
927 final MeasurementDecorator measurement) {
928
929
930 final ObservedMeasurement<?> observedMeasurement = measurement.getObservedMeasurement();
931 for (final ParameterDriver driver : observedMeasurement.getParametersDrivers()) {
932 if (driver.getReferenceDate() == null) {
933 driver.setReferenceDate(builders.get(0).getInitialOrbitDate());
934 }
935 }
936
937 ++currentMeasurementNumber;
938 currentDate = measurement.getObservedMeasurement().getDate();
939
940
941
942
943
944
945
946
947
948
949 final RealVector predictedState = predictState(observedMeasurement.getDate());
950
951
952 final RealMatrix stateTransitionMatrix = getErrorStateTransitionMatrix();
953
954
955
956
957
958
959
960
961
962
963 predictedMeasurement = observedMeasurement.estimate(currentMeasurementNumber,
964 currentMeasurementNumber,
965 filterRelevant(observedMeasurement, predictedSpacecraftStates));
966
967
968 final RealMatrix measurementMatrix = getMeasurementMatrix();
969
970
971 final RealMatrix physicalProcessNoise = MatrixUtils.createRealMatrix(previousState.getDimension(),
972 previousState.getDimension());
973 for (int k = 0; k < covarianceMatricesProviders.size(); ++k) {
974
975
976 final int nbMeas = estimatedMeasurementsParameters.getNbParams();
977
978
979 final int nbDyn = orbitsEndColumns[k] - orbitsStartColumns[k] +
980 estimatedPropagationParameters[k].getNbParams();
981
982
983 final RealMatrix noiseK = MatrixUtils.createRealMatrix(nbDyn + nbMeas, nbDyn + nbMeas);
984 final RealMatrix noiseP = covarianceMatricesProviders.get(k).
985 getProcessNoiseMatrix(correctedSpacecraftStates[k],
986 predictedSpacecraftStates[k]);
987 noiseK.setSubMatrix(noiseP.getData(), 0, 0);
988 if (measurementProcessNoiseMatrix != null) {
989 final RealMatrix noiseM = measurementProcessNoiseMatrix.
990 getProcessNoiseMatrix(correctedSpacecraftStates[k],
991 predictedSpacecraftStates[k]);
992 noiseK.setSubMatrix(noiseM.getData(), nbDyn, nbDyn);
993 }
994
995 checkDimension(noiseK.getRowDimension(),
996 builders.get(k).getOrbitalParametersDrivers(),
997 builders.get(k).getPropagationParametersDrivers(),
998 estimatedMeasurementsParameters);
999
1000 final int[] indK = covarianceIndirection[k];
1001 for (int i = 0; i < indK.length; ++i) {
1002 if (indK[i] >= 0) {
1003 for (int j = 0; j < indK.length; ++j) {
1004 if (indK[j] >= 0) {
1005 physicalProcessNoise.setEntry(indK[i], indK[j], noiseK.getEntry(i, j));
1006 }
1007 }
1008 }
1009 }
1010
1011 }
1012 final RealMatrix normalizedProcessNoise = normalizeCovarianceMatrix(physicalProcessNoise);
1013
1014 return new NonLinearEvolution(measurement.getTime(), predictedState,
1015 stateTransitionMatrix, normalizedProcessNoise, measurementMatrix);
1016
1017 }
1018
1019
1020
1021 @Override
1022 public RealVector getInnovation(final MeasurementDecorator measurement, final NonLinearEvolution evolution,
1023 final RealMatrix innovationCovarianceMatrix) {
1024
1025
1026 applyDynamicOutlierFilter(predictedMeasurement, innovationCovarianceMatrix);
1027 if (predictedMeasurement.getStatus() == EstimatedMeasurement.Status.REJECTED) {
1028
1029 return null;
1030 } else {
1031
1032 final double[] observed = predictedMeasurement.getObservedMeasurement().getObservedValue();
1033 final double[] estimated = predictedMeasurement.getEstimatedValue();
1034 final double[] sigma = predictedMeasurement.getObservedMeasurement().getTheoreticalStandardDeviation();
1035 final double[] residuals = new double[observed.length];
1036
1037 for (int i = 0; i < observed.length; i++) {
1038 residuals[i] = (observed[i] - estimated[i]) / sigma[i];
1039 }
1040 return MatrixUtils.createRealVector(residuals);
1041 }
1042 }
1043
1044
1045
1046
1047
1048 public void finalizeEstimation(final ObservedMeasurement<?> observedMeasurement,
1049 final ProcessEstimate estimate) {
1050
1051
1052 correctedEstimate = estimate;
1053 updateParameters();
1054
1055
1056
1057 final Propagator[] estimatedPropagators = getEstimatedPropagators();
1058 for (int k = 0; k < estimatedPropagators.length; ++k) {
1059 correctedSpacecraftStates[k] = estimatedPropagators[k].getInitialState();
1060 }
1061
1062
1063 correctedMeasurement = observedMeasurement.estimate(currentMeasurementNumber,
1064 currentMeasurementNumber,
1065 filterRelevant(observedMeasurement, correctedSpacecraftStates));
1066
1067
1068 updateReferenceTrajectories(estimatedPropagators, propagationType, stateType);
1069
1070 }
1071
1072
1073
1074
1075
1076
1077
1078 private SpacecraftState[] filterRelevant(final ObservedMeasurement<?> observedMeasurement, final SpacecraftState[] allStates) {
1079 final List<ObservableSatellite> satellites = observedMeasurement.getSatellites();
1080 final SpacecraftState[] relevantStates = new SpacecraftState[satellites.size()];
1081 for (int i = 0; i < relevantStates.length; ++i) {
1082 relevantStates[i] = allStates[satellites.get(i).getPropagatorIndex()];
1083 }
1084 return relevantStates;
1085 }
1086
1087
1088
1089
1090
1091
1092 private RealVector predictState(final AbsoluteDate date) {
1093
1094
1095 final RealVector predictedState = correctedEstimate.getState().copy();
1096
1097
1098 int jOrb = 0;
1099
1100 for (int k = 0; k < predictedSpacecraftStates.length; ++k) {
1101
1102
1103 predictedSpacecraftStates[k] = referenceTrajectories[k].propagate(date);
1104
1105
1106
1107 builders.get(k).resetOrbit(predictedSpacecraftStates[k].getOrbit());
1108
1109
1110
1111
1112
1113 for (DelegatingDriver orbitalDriver : builders.get(k).getOrbitalParametersDrivers().getDrivers()) {
1114 if (orbitalDriver.isSelected()) {
1115 predictedState.setEntry(jOrb++, orbitalDriver.getNormalizedValue());
1116 }
1117 }
1118
1119 }
1120
1121 return predictedState;
1122
1123 }
1124
1125
1126
1127
1128 private void updateParameters() {
1129 final RealVector correctedState = correctedEstimate.getState();
1130 int i = 0;
1131 for (final DelegatingDriver driver : getEstimatedOrbitalParameters().getDrivers()) {
1132
1133 driver.setNormalizedValue(correctedState.getEntry(i));
1134 correctedState.setEntry(i++, driver.getNormalizedValue());
1135 }
1136 for (final DelegatingDriver driver : getEstimatedPropagationParameters().getDrivers()) {
1137
1138 driver.setNormalizedValue(correctedState.getEntry(i));
1139 correctedState.setEntry(i++, driver.getNormalizedValue());
1140 }
1141 for (final DelegatingDriver driver : getEstimatedMeasurementsParameters().getDrivers()) {
1142
1143 driver.setNormalizedValue(correctedState.getEntry(i));
1144 correctedState.setEntry(i++, driver.getNormalizedValue());
1145 }
1146 }
1147
1148
1149
1150
1151 public List<OrbitDeterminationPropagatorBuilder> getBuilders() {
1152 return builders;
1153 }
1154
1155
1156
1157
1158 public Propagator[] getReferenceTrajectories() {
1159 return referenceTrajectories.clone();
1160 }
1161
1162
1163
1164
1165 public void setReferenceTrajectories(final Propagator[] referenceTrajectories) {
1166 this.referenceTrajectories = referenceTrajectories.clone();
1167 }
1168
1169
1170
1171
1172 public AbstractJacobiansMapper[] getMappers() {
1173 return mappers.clone();
1174 }
1175
1176
1177
1178
1179 public void setMappers(final AbstractJacobiansMapper[] mappers) {
1180 this.mappers = mappers.clone();
1181 }
1182
1183
1184
1185
1186 public Propagator[] getEstimatedPropagators() {
1187
1188 final Propagator[] propagators = new Propagator[getBuilders().size()];
1189 for (int k = 0; k < getBuilders().size(); ++k) {
1190 propagators[k] = getBuilders().get(k).buildPropagator(getBuilders().get(k).getSelectedNormalizedParameters());
1191 }
1192 return propagators;
1193 }
1194
1195 }