SemiAnalyticalKalmanEstimator.java

  1. /* Copyright 2002-2022 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. import java.util.List;

  19. import org.hipparchus.exception.MathRuntimeException;
  20. import org.hipparchus.filtering.kalman.extended.ExtendedKalmanFilter;
  21. import org.hipparchus.linear.MatrixDecomposer;
  22. import org.hipparchus.linear.RealMatrix;
  23. import org.hipparchus.linear.RealVector;
  24. import org.orekit.errors.OrekitException;
  25. import org.orekit.estimation.measurements.ObservedMeasurement;
  26. import org.orekit.propagation.conversion.DSSTPropagatorBuilder;
  27. import org.orekit.propagation.semianalytical.dsst.DSSTPropagator;
  28. import org.orekit.time.AbsoluteDate;
  29. import org.orekit.utils.ParameterDriver;
  30. import org.orekit.utils.ParameterDriversList;
  31. import org.orekit.utils.ParameterDriversList.DelegatingDriver;

  32. /**
  33.  * Implementation of an Extended Semi-analytical Kalman Filter (ESKF) to perform orbit determination.
  34.  * <p>
  35.  * The filter uses a {@link DSSTPropagatorBuilder}.
  36.  * </p>
  37.  * <p>
  38.  * The estimated parameters are driven by {@link ParameterDriver} objects. They are of 3 different types:<ol>
  39.  *   <li><b>Orbital parameters</b>:The position and velocity of the spacecraft, or, more generally, its orbit.<br>
  40.  *       These parameters are retrieved from the reference trajectory propagator builder when the filter is initialized.</li>
  41.  *   <li><b>Propagation parameters</b>: Some parameters modelling physical processes (SRP or drag coefficients).<br>
  42.  *       They are also retrieved from the propagator builder during the initialization phase.</li>
  43.  *   <li><b>Measurements parameters</b>: Parameters related to measurements (station biases, positions etc...).<br>
  44.  *       They are passed down to the filter in its constructor.</li>
  45.  * </ol>
  46.  * <p>
  47.  * The Kalman filter implementation used is provided by the underlying mathematical library Hipparchus.
  48.  * All the variables seen by Hipparchus (states, covariances, measurement matrices...) are normalized
  49.  * using a specific scale for each estimated parameters or standard deviation noise for each measurement components.
  50.  * </p>
  51.  *
  52.  * @see "Folcik Z., Orbit Determination Using Modern Filters/Smoothers and Continuous Thrust Modeling,
  53.  *       Master of Science Thesis, Department of Aeronautics and Astronautics, MIT, June, 2008."
  54.  *
  55.  * @see "Cazabonne B., Bayard J., Journot M., and Cefola P. J., A Semi-analytical Approach for Orbit
  56.  *       Determination based on Extended Kalman Filter, AAS Paper 21-614, AAS/AIAA Astrodynamics
  57.  *       Specialist Conference, Big Sky, August 2021."
  58.  *
  59.  * @author Julie Bayard
  60.  * @author Bryan Cazabonne
  61.  * @author Maxime Journot
  62.  * @since 11.1
  63.  */
  64. public class SemiAnalyticalKalmanEstimator {

  65.     /** Builders for orbit propagators. */
  66.     private DSSTPropagatorBuilder propagatorBuilder;

  67.     /** Kalman filter process model. */
  68.     private final SemiAnalyticalKalmanModel processModel;

  69.     /** Filter. */
  70.     private final ExtendedKalmanFilter<MeasurementDecorator> filter;

  71.     /** Observer to retrieve current estimation info. */
  72.     private KalmanObserver observer;

  73.     /** Kalman filter estimator constructor (package private).
  74.      * @param decomposer decomposer to use for the correction phase
  75.      * @param propagatorBuilder propagator builder used to evaluate the orbit.
  76.      * @param covarianceMatrixProvider provider for process noise matrix
  77.      * @param estimatedMeasurementParameters measurement parameters to estimate
  78.      * @param measurementProcessNoiseMatrix provider for measurement process noise matrix
  79.      */
  80.     public SemiAnalyticalKalmanEstimator(final MatrixDecomposer decomposer,
  81.                                          final DSSTPropagatorBuilder propagatorBuilder,
  82.                                          final CovarianceMatrixProvider covarianceMatrixProvider,
  83.                                          final ParameterDriversList estimatedMeasurementParameters,
  84.                                          final CovarianceMatrixProvider measurementProcessNoiseMatrix) {

  85.         this.propagatorBuilder = propagatorBuilder;
  86.         this.observer          = null;

  87.         // Build the process model and measurement model
  88.         this.processModel = new SemiAnalyticalKalmanModel(propagatorBuilder, covarianceMatrixProvider,
  89.                                                           estimatedMeasurementParameters,  measurementProcessNoiseMatrix);

  90.         // Extended Kalman Filter of Hipparchus
  91.         this.filter = new ExtendedKalmanFilter<>(decomposer, processModel, processModel.getEstimate());

  92.     }

  93.     /** Set the observer.
  94.      * @param observer the observer
  95.      */
  96.     public void setObserver(final KalmanObserver observer) {
  97.         this.observer = observer;
  98.     }

  99.     /** Get the current measurement number.
  100.      * @return current measurement number
  101.      */
  102.     public int getCurrentMeasurementNumber() {
  103.         return processModel.getCurrentMeasurementNumber();
  104.     }

  105.     /** Get the current date.
  106.      * @return current date
  107.      */
  108.     public AbsoluteDate getCurrentDate() {
  109.         return processModel.getCurrentDate();
  110.     }

  111.     /** Get the "physical" estimated state (i.e. not normalized)
  112.      * @return the "physical" estimated state
  113.      */
  114.     public RealVector getPhysicalEstimatedState() {
  115.         return processModel.getPhysicalEstimatedState();
  116.     }

  117.     /** Get the "physical" estimated covariance matrix (i.e. not normalized)
  118.      * @return the "physical" estimated covariance matrix
  119.      */
  120.     public RealMatrix getPhysicalEstimatedCovarianceMatrix() {
  121.         return processModel.getPhysicalEstimatedCovarianceMatrix();
  122.     }

  123.     /** Get the orbital parameters supported by this estimator.
  124.      * <p>
  125.      * If there are more than one propagator builder, then the names
  126.      * of the drivers have an index marker in square brackets appended
  127.      * to them in order to distinguish the various orbits. So for example
  128.      * with one builder generating Keplerian orbits the names would be
  129.      * simply "a", "e", "i"... but if there are several builders the
  130.      * names would be "a[0]", "e[0]", "i[0]"..."a[1]", "e[1]", "i[1]"...
  131.      * </p>
  132.      * @param estimatedOnly if true, only estimated parameters are returned
  133.      * @return orbital parameters supported by this estimator
  134.      */
  135.     public ParameterDriversList getOrbitalParametersDrivers(final boolean estimatedOnly) {

  136.         final ParameterDriversList estimated = new ParameterDriversList();
  137.         for (final ParameterDriver driver : propagatorBuilder.getOrbitalParametersDrivers().getDrivers()) {
  138.             if (driver.isSelected() || !estimatedOnly) {
  139.                 driver.setName(driver.getName());
  140.                 estimated.add(driver);
  141.             }
  142.         }
  143.         return estimated;
  144.     }

  145.     /** Get the propagator parameters supported by this estimator.
  146.      * @param estimatedOnly if true, only estimated parameters are returned
  147.      * @return propagator parameters supported by this estimator
  148.      */
  149.     public ParameterDriversList getPropagationParametersDrivers(final boolean estimatedOnly) {

  150.         final ParameterDriversList estimated = new ParameterDriversList();
  151.         for (final DelegatingDriver delegating : propagatorBuilder.getPropagationParametersDrivers().getDrivers()) {
  152.             if (delegating.isSelected() || !estimatedOnly) {
  153.                 for (final ParameterDriver driver : delegating.getRawDrivers()) {
  154.                     estimated.add(driver);
  155.                 }
  156.             }
  157.         }
  158.         return estimated;
  159.     }

  160.     /** Get the list of estimated measurements parameters.
  161.      * @return the list of estimated measurements parameters
  162.      */
  163.     public ParameterDriversList getEstimatedMeasurementsParameters() {
  164.         return processModel.getEstimatedMeasurementsParameters();
  165.     }

  166.     /** Process a single measurement.
  167.      * <p>
  168.      * Update the filter with the new measurement by calling the estimate method.
  169.      * </p>
  170.      * @param observedMeasurements the list of measurements to process
  171.      * @return estimated propagators
  172.      */
  173.     public DSSTPropagator processMeasurements(final List<ObservedMeasurement<?>> observedMeasurements) {
  174.         try {
  175.             processModel.setObserver(observer);
  176.             return processModel.processMeasurements(observedMeasurements, filter);
  177.         } catch (MathRuntimeException mrte) {
  178.             throw new OrekitException(mrte);
  179.         }
  180.     }

  181. }