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