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