1   /* Copyright 2002-2025 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.KalmanFilter;
22  import org.hipparchus.linear.MatrixDecomposer;
23  import org.hipparchus.linear.RealMatrix;
24  import org.hipparchus.linear.RealVector;
25  import org.orekit.propagation.conversion.PropagatorBuilder;
26  import org.orekit.time.AbsoluteDate;
27  import org.orekit.utils.ParameterDriver;
28  import org.orekit.utils.ParameterDriversList;
29  import org.orekit.utils.ParameterDriversList.DelegatingDriver;
30  
31  /**
32   * Base class for Kalman estimators.
33   * @author Romain Gerbaud
34   * @author Maxime Journot
35   * @author Luc Maisonobe
36   * @since 11.3
37   */
38  public abstract class AbstractKalmanEstimator {
39  
40      /** List of propagator builder. */
41      private final List<? extends PropagatorBuilder> builders;
42  
43      /** Reference date. */
44      private final AbsoluteDate referenceDate;
45  
46      /** Observer to retrieve current estimation info. */
47      private KalmanObserver observer;
48  
49      /** Matrix decomposer for filter. */
50      private final MatrixDecomposer decomposer;
51  
52      /**
53       * Constructor.
54       * @param decomposer matrix decomposer for filter
55       * @param builders list of propagator builders
56       */
57      protected AbstractKalmanEstimator(final MatrixDecomposer decomposer,
58                                        final List<? extends PropagatorBuilder> builders) {
59          this.builders = builders;
60          this.referenceDate = builders.get(0).getInitialOrbitDate();
61          this.decomposer = decomposer;
62          this.observer = null;
63      }
64  
65      /** Get the orbital parameters supported by this estimator.
66       * <p>
67       * If there are more than one propagator builder, then the names
68       * of the drivers have an index marker in square brackets appended
69       * to them in order to distinguish the various orbits. So for example
70       * with one builder generating Keplerian orbits the names would be
71       * simply "a", "e", "i"... but if there are several builders the
72       * names would be "a[0]", "e[0]", "i[0]"..."a[1]", "e[1]", "i[1]"...
73       * </p>
74       * @param estimatedOnly if true, only estimated parameters are returned
75       * @return orbital parameters supported by this estimator
76       */
77      public ParameterDriversList getOrbitalParametersDrivers(final boolean estimatedOnly) {
78  
79          final ParameterDriversList estimated = new ParameterDriversList();
80          for (int i = 0; i < builders.size(); ++i) {
81              final String suffix = builders.size() > 1 ? "[" + i + "]" : null;
82              for (final ParameterDriver driver : builders.get(i).getOrbitalParametersDrivers().getDrivers()) {
83                  if (driver.isSelected() || !estimatedOnly) {
84                      if (suffix != null && !driver.getName().endsWith(suffix)) {
85                          // we add suffix only conditionally because the method may already have been called
86                          // and suffixes may have already been appended
87                          driver.setName(driver.getName() + suffix);
88                      }
89                      estimated.add(driver);
90                  }
91              }
92          }
93          return estimated;
94      }
95  
96      /** Get the propagator parameters supported by this estimator.
97       * @param estimatedOnly if true, only estimated parameters are returned
98       * @return propagator parameters supported by this estimator
99       */
100     public ParameterDriversList getPropagationParametersDrivers(final boolean estimatedOnly) {
101 
102         final ParameterDriversList estimated = new ParameterDriversList();
103         for (PropagatorBuilder builder : builders) {
104             for (final DelegatingDriver delegating : builder.getPropagationParametersDrivers().getDrivers()) {
105                 if (delegating.isSelected() || !estimatedOnly) {
106                     for (final ParameterDriver driver : delegating.getRawDrivers()) {
107                         estimated.add(driver);
108                     }
109                 }
110             }
111         }
112         return estimated;
113     }
114 
115 
116     /** Get the current measurement number.
117      * @return current measurement number
118      */
119     public int getCurrentMeasurementNumber() {
120         return getKalmanEstimation().getCurrentMeasurementNumber();
121     }
122 
123     /** Get the current date.
124      * @return current date
125      */
126     public AbsoluteDate getCurrentDate() {
127         return getKalmanEstimation().getCurrentDate();
128     }
129 
130     /** Set the observer.
131      * @param observer the observer
132      */
133     public void setObserver(final KalmanObserver observer) {
134         this.observer = observer;
135         observer.init(getKalmanEstimation());
136     }
137 
138     /** Get the observer.
139      * @return the observer
140      */
141     public KalmanObserver getObserver() {
142         return observer;
143     }
144 
145     /** Get the "physical" estimated state (i.e. not normalized)
146      * <p>
147      * For the Semi-analytical Kalman Filters
148      * it corresponds to the corrected filter correction.
149      * In other words, it doesn't represent an orbital state.
150      * </p>
151      * @return the "physical" estimated state
152      */
153     public RealVector getPhysicalEstimatedState() {
154         return getKalmanEstimation().getPhysicalEstimatedState();
155     }
156 
157     /** Get the "physical" estimated covariance matrix (i.e. not normalized)
158      * @return the "physical" estimated covariance matrix
159      */
160     public RealMatrix getPhysicalEstimatedCovarianceMatrix() {
161         return getKalmanEstimation().getPhysicalEstimatedCovarianceMatrix();
162     }
163 
164     /** Get the list of estimated measurements parameters.
165      * @return the list of estimated measurements parameters
166      */
167     public ParameterDriversList getEstimatedMeasurementsParameters() {
168         return getKalmanEstimation().getEstimatedMeasurementsParameters();
169     }
170 
171     protected List<? extends PropagatorBuilder> getBuilders() {
172         return builders;
173     }
174 
175     /** Get the provider for kalman filter estimations.
176      * @return the provider for Kalman filter estimations
177      */
178     protected abstract KalmanEstimation getKalmanEstimation();
179 
180     /** Get the matrix decomposer.
181      * @return the decomposer
182      */
183     protected MatrixDecomposer getMatrixDecomposer() {
184         return decomposer;
185     }
186 
187     /** Get the reference date.
188      * @return the date
189      */
190     protected AbsoluteDate getReferenceDate() {
191         return referenceDate;
192     }
193 
194     /** Get the Hipparchus filter.
195      * @return the filter
196      */
197     protected abstract KalmanFilter<MeasurementDecorator> getKalmanFilter();
198 
199     /** Get the parameter scaling factors.
200      * @return the parameters scale
201      */
202     protected abstract double[] getScale();
203 
204 }