1 /* Copyright 2002-2024 CS GROUP
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.estimation.sequential;
18
19 import java.util.List;
20
21 import org.hipparchus.filtering.kalman.ProcessEstimate;
22 import org.hipparchus.filtering.kalman.unscented.UnscentedKalmanFilter;
23 import org.hipparchus.linear.MatrixDecomposer;
24 import org.hipparchus.util.UnscentedTransformProvider;
25 import org.orekit.estimation.measurements.ObservedMeasurement;
26 import org.orekit.propagation.Propagator;
27 import org.orekit.propagation.conversion.DSSTPropagatorBuilder;
28 import org.orekit.propagation.conversion.PropagatorBuilder;
29 import org.orekit.time.AbsoluteDate;
30 import org.orekit.utils.ParameterDriver;
31 import org.orekit.utils.ParameterDriversList;
32
33 /**
34 * Implementation of an Unscented Kalman filter to perform orbit determination.
35 * <p>
36 * The filter uses a {@link PropagatorBuilder} to initialize its reference trajectory.
37 * </p>
38 * <p>
39 * The estimated parameters are driven by {@link ParameterDriver} objects. They are of 3 different types:<ol>
40 * <li><b>Orbital parameters</b>:The position and velocity of the spacecraft, or, more generally, its orbit.<br>
41 * These parameters are retrieved from the reference trajectory propagator builder when the filter is initialized.</li>
42 * <li><b>Propagation parameters</b>: Some parameters modelling physical processes (SRP or drag coefficients etc...).<br>
43 * They are also retrieved from the propagator builder during the initialization phase.</li>
44 * <li><b>Measurements parameters</b>: Parameters related to measurements (station biases, positions etc...).<br>
45 * They are passed down to the filter in its constructor.</li>
46 * </ol>
47 * <p>
48 * The total number of estimated parameters is m, the size of the state vector.
49 * </p>
50 * <p>
51 * The Kalman filter implementation used is provided by the underlying mathematical library Hipparchus.
52 * </p>
53 *
54 * <p>An {@link UnscentedKalmanEstimator} object is built using the {@link UnscentedKalmanEstimatorBuilder#build() build}
55 * method of a {@link UnscentedKalmanEstimatorBuilder}. The builder is generalized to accept any {@link PropagatorBuilder}.
56 * Howerver, it is absolutely not recommended to use a {@link DSSTPropagatorBuilder}.
57 * A specific {@link SemiAnalyticalUnscentedKalmanEstimatorBuilder semi-analytical unscented Kalman Filter} is implemented
58 * and shall be used.
59 * </p>
60 *
61 * @author Gaƫtan Pierre
62 * @author Bryan Cazabonne
63 * @since 11.3
64 */
65 public class UnscentedKalmanEstimator extends AbstractKalmanEstimator {
66
67 /** Reference date. */
68 private final AbsoluteDate referenceDate;
69
70 /** Unscented Kalman filter process model. */
71 private final UnscentedKalmanModel processModel;
72
73 /** Filter. */
74 private final UnscentedKalmanFilter<MeasurementDecorator> filter;
75
76 /** Observer to retrieve current estimation info. */
77 private KalmanObserver observer;
78
79 /** Unscented Kalman filter estimator constructor (package private).
80 * @param decomposer decomposer to use for the correction phase
81 * @param propagatorBuilders propagators builders used to evaluate the orbit.
82 * @param processNoiseMatricesProviders providers for process noise matrices
83 * @param estimatedMeasurementParameters measurement parameters to estimate
84 * @param measurementProcessNoiseMatrix provider for measurement process noise matrix
85 * @param utProvider provider for the unscented transform.
86 */
87 UnscentedKalmanEstimator(final MatrixDecomposer decomposer,
88 final List<PropagatorBuilder> propagatorBuilders,
89 final List<CovarianceMatrixProvider> processNoiseMatricesProviders,
90 final ParameterDriversList estimatedMeasurementParameters,
91 final CovarianceMatrixProvider measurementProcessNoiseMatrix,
92 final UnscentedTransformProvider utProvider) {
93 super(propagatorBuilders);
94 this.referenceDate = propagatorBuilders.get(0).getInitialOrbitDate();
95 this.observer = null;
96
97 // Build the process model and measurement model
98 this.processModel = new UnscentedKalmanModel(propagatorBuilders, processNoiseMatricesProviders,
99 estimatedMeasurementParameters, measurementProcessNoiseMatrix);
100
101 this.filter = new UnscentedKalmanFilter<>(decomposer, processModel, processModel.getEstimate(), utProvider);
102
103 }
104
105 /** {@inheritDoc}. */
106 @Override
107 protected KalmanEstimation getKalmanEstimation() {
108 return processModel;
109 }
110
111 /** Set the observer.
112 * @param observer the observer
113 */
114 public void setObserver(final KalmanObserver observer) {
115 this.observer = observer;
116 }
117
118 /** Process a single measurement.
119 * <p>
120 * Update the filter with the new measurement by calling the estimate method.
121 * </p>
122 * @param observedMeasurement the measurement to process
123 * @return estimated propagator
124 */
125 public Propagator[] estimationStep(final ObservedMeasurement<?> observedMeasurement) {
126 final ProcessEstimate estimate = filter.estimationStep(KalmanEstimatorUtil.decorate(observedMeasurement, referenceDate));
127 processModel.finalizeEstimation(observedMeasurement, estimate);
128 if (observer != null) {
129 observer.evaluationPerformed(processModel);
130 }
131 return processModel.getEstimatedPropagators();
132 }
133
134 /** Process several measurements.
135 * @param observedMeasurements the measurements to process in <em>chronologically sorted</em> order
136 * @return estimated propagator
137 */
138 public Propagator[] processMeasurements(final Iterable<ObservedMeasurement<?>> observedMeasurements) {
139 Propagator[] propagators = null;
140 for (ObservedMeasurement<?> observedMeasurement : observedMeasurements) {
141 propagators = estimationStep(observedMeasurement);
142 }
143 return propagators;
144 }
145
146 }