UnivariateProcessNoise.java

  1. /* Copyright 2002-2019 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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 org.hipparchus.analysis.UnivariateFunction;
  19. import org.hipparchus.exception.LocalizedCoreFormats;
  20. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  21. import org.hipparchus.linear.MatrixUtils;
  22. import org.hipparchus.linear.RealMatrix;
  23. import org.orekit.errors.OrekitException;
  24. import org.orekit.frames.LOFType;
  25. import org.orekit.frames.Transform;
  26. import org.orekit.orbits.PositionAngle;
  27. import org.orekit.propagation.SpacecraftState;

  28. /** Provider for a temporal evolution of the process noise matrix.
  29.  * All parameters (orbital or propagation) are time dependent and provided as {@link UnivariateFunction}.
  30.  * The argument of the functions is a duration in seconds (between current and previous spacecraft state).
  31.  * The output of the functions must be of the dimension of a standard deviation.
  32.  * The method {@link #getProcessNoiseMatrix} then square the values so that they are consistent with a covariance matrix.
  33.  * <p>
  34.  * The orbital parameters evolutions are provided in LOF frame and Cartesian (PV);
  35.  * then converted in inertial frame and current {@link org.orekit.orbits.OrbitType} and {@link PositionAngle}
  36.  * when method {@link #getProcessNoiseMatrix} is called.
  37.  * </p>
  38.  * <p>
  39.  * The time-dependent functions define a process noise matrix that is diagonal
  40.  * <em>in the Local Orbital Frame</em>, corresponds to Cartesian elements, abd represents
  41.  * the temporal evolution of (the standard deviation of) the process noise model. The
  42.  * first function is therefore the standard deviation along the LOF X axis, the second
  43.  * function represents the standard deviation along the LOF Y axis...
  44.  * This allows to set up simply a process noise representing an uncertainty that grows
  45.  * mainly along the track. The 6x6 upper left part of output matrix will however not be
  46.  * diagonal as it will be converted to the same inertial frame and orbit type as the
  47.  * {@link SpacecraftState state} used by the {@link KalmanEstimator Kalman estimator}.
  48.  * </p>
  49.  * <p>
  50.  * The propagation parameters are not associated to a specific frame and are appended as
  51.  * is in the lower right part diagonal of the output matrix. This implies this simplified
  52.  * model does not include correlation between the parameters and the orbit, but only
  53.  * evolution of the parameters themselves. If such correlations are needed, users must
  54.  * set up a custom {@link CovarianceMatrixProvider covariance matrix provider}. In most
  55.  * cases, the parameters are constant and their evolution noise is always 0, so the
  56.  * functions can be set to {@code x -> 0}.
  57.  * </p>
  58.  * <p>
  59.  * This class always provides one initial noise matrix or initial covariance matrix and one process noise matrix.
  60.  * </p>
  61.  * @author Luc Maisonobe
  62.  * @author Maxime Journot
  63.  * @since 9.2
  64.  */
  65. public class UnivariateProcessNoise extends AbstractCovarianceMatrixProvider {

  66.     /** Local Orbital Frame (LOF) type used. */
  67.     private final LOFType lofType;

  68.     /** Position angle for the orbital process noise matrix. */
  69.     private final PositionAngle positionAngle;

  70.     /** Array of univariate functions for the six orbital parameters process noise evolution in LOF frame and Cartesian formalism. */
  71.     private final UnivariateFunction[] lofCartesianOrbitalParametersEvolution;

  72.     /** Array of univariate functions for the propagation parameters process noise evolution. */
  73.     private final UnivariateFunction[] propagationParametersEvolution;

  74.     /** Simple constructor.
  75.      * @param initialCovarianceMatrix initial covariance matrix
  76.      * @param lofType the LOF type used
  77.      * @param positionAngle the position angle used for the computation of the process noise
  78.      * @param lofCartesianOrbitalParametersEvolution Array of univariate functions for the six orbital parameters process noise evolution in LOF frame and Cartesian orbit type
  79.      * @param propagationParametersEvolution Array of univariate functions for the propagation parameters process noise evolution
  80.      */
  81.     public UnivariateProcessNoise(final RealMatrix initialCovarianceMatrix,
  82.                                   final LOFType lofType,
  83.                                   final PositionAngle positionAngle,
  84.                                   final UnivariateFunction[] lofCartesianOrbitalParametersEvolution,
  85.                                   final UnivariateFunction[] propagationParametersEvolution) {
  86.         super(initialCovarianceMatrix);
  87.         this.lofType = lofType;
  88.         this.positionAngle = positionAngle;
  89.         this.lofCartesianOrbitalParametersEvolution  = lofCartesianOrbitalParametersEvolution;
  90.         this.propagationParametersEvolution = propagationParametersEvolution;

  91.         // Ensure that the orbital evolution array size is 6
  92.         if (lofCartesianOrbitalParametersEvolution.length != 6) {
  93.             throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  94.                                       lofCartesianOrbitalParametersEvolution, 6);
  95.         }
  96.     }

  97.     /** Getter for the lofType.
  98.      * @return the lofType
  99.      */
  100.     public LOFType getLofType() {
  101.         return lofType;
  102.     }

  103.     /** Getter for the positionAngle.
  104.      * @return the positionAngle
  105.      */
  106.     public PositionAngle getPositionAngle() {
  107.         return positionAngle;
  108.     }

  109.     /** Getter for the lofCartesianOrbitalParametersEvolution.
  110.      * @return the lofCartesianOrbitalParametersEvolution
  111.      */
  112.     public UnivariateFunction[] getLofCartesianOrbitalParametersEvolution() {
  113.         return lofCartesianOrbitalParametersEvolution;
  114.     }

  115.     /** Getter for the propagationParametersEvolution.
  116.      * @return the propagationParametersEvolution
  117.      */
  118.     public UnivariateFunction[] getPropagationParametersEvolution() {
  119.         return propagationParametersEvolution;
  120.     }

  121.     /** {@inheritDoc} */
  122.     @Override
  123.     public RealMatrix getProcessNoiseMatrix(final SpacecraftState previous,
  124.                                             final SpacecraftState current) {

  125.         // Orbital parameters process noise matrix in inertial frame and current orbit type
  126.         final RealMatrix inertialOrbitalProcessNoiseMatrix = getInertialOrbitalProcessNoiseMatrix(previous, current);

  127.         if (propagationParametersEvolution.length == 0) {

  128.             // no propagation parameters contribution, just return the orbital part
  129.             return inertialOrbitalProcessNoiseMatrix;

  130.         } else {

  131.             // Propagation parameters process noise matrix
  132.             final RealMatrix propagationProcessNoiseMatrix = getPropagationProcessNoiseMatrix(previous, current);

  133.             // Concatenate the matrices
  134.             final int        orbitalMatrixSize     = lofCartesianOrbitalParametersEvolution.length;
  135.             final int        propagationMatrixSize = propagationParametersEvolution.length;
  136.             final RealMatrix processNoiseMatrix    = MatrixUtils.createRealMatrix(orbitalMatrixSize + propagationMatrixSize,
  137.                                                                                   orbitalMatrixSize + propagationMatrixSize);
  138.             processNoiseMatrix.setSubMatrix(inertialOrbitalProcessNoiseMatrix.getData(), 0, 0);
  139.             processNoiseMatrix.setSubMatrix(propagationProcessNoiseMatrix.getData(), orbitalMatrixSize, orbitalMatrixSize);
  140.             return processNoiseMatrix;

  141.         }
  142.     }

  143.     /** Get the process noise for the six orbital parameters in current spacecraft inertial frame and current orbit type.
  144.      * @param previous previous state
  145.      * @param current current state
  146.      * @return physical (i.e. non normalized) orbital process noise matrix in inertial frame
  147.      */
  148.     private RealMatrix getInertialOrbitalProcessNoiseMatrix(final SpacecraftState previous,
  149.                                                             final SpacecraftState current) {

  150.         // ΔT = duration in seconds from previous to current spacecraft state
  151.         final double deltaT = current.getDate().durationFrom(previous.getDate());

  152.         // Evaluate the functions, using ΔT as argument
  153.         final int      lofOrbitalprocessNoiseLength = lofCartesianOrbitalParametersEvolution.length;
  154.         final double[] lofOrbitalProcessNoiseValues = new double[lofOrbitalprocessNoiseLength];

  155.         // The function return a value which dimension is that of a standard deviation
  156.         // It needs to be squared before being put in the process noise covariance matrix
  157.         for (int i = 0; i < lofOrbitalprocessNoiseLength; i++) {
  158.             final double functionValue =  lofCartesianOrbitalParametersEvolution[i].value(deltaT);
  159.             lofOrbitalProcessNoiseValues[i] = functionValue * functionValue;
  160.         }

  161.         // Form the diagonal matrix in LOF frame and Cartesian formalism
  162.         final RealMatrix lofCartesianProcessNoiseMatrix = MatrixUtils.createRealDiagonalMatrix(lofOrbitalProcessNoiseValues);

  163.         // Get the rotation matrix from LOF to inertial frame
  164.         final double[][] lofToInertialRotation = lofType.rotationFromInertial(current.getPVCoordinates()).
  165.                                                  revert().getMatrix();

  166.         // Jacobian from LOF to inertial frame
  167.         final RealMatrix jacLofToInertial = MatrixUtils.createRealMatrix(6, 6);
  168.         jacLofToInertial.setSubMatrix(lofToInertialRotation, 0, 0);
  169.         jacLofToInertial.setSubMatrix(lofToInertialRotation, 3, 3);

  170.         // FIXME: Trying to fix the transform from LOF to inertial
  171.         final Transform lofToInertial = lofType.transformFromInertial(current.getDate(), current.getPVCoordinates()).getInverse();
  172.         final Vector3D OM = lofToInertial.getRotationRate().negate();
  173.         final double[][] MOM = new double[3][3];
  174.         MOM[0][1] = -OM.getZ();
  175.         MOM[0][2] = OM.getY();
  176.         MOM[1][0] = OM.getZ();
  177.         MOM[1][2] = -OM.getX();
  178.         MOM[2][0] = -OM.getY();
  179.         MOM[2][1] = OM.getX();
  180.         //jacLofToInertial.setSubMatrix(MOM, 3, 0);
  181.         //debug

  182.         // Jacobian of orbit parameters with respect to Cartesian parameters
  183.         final double[][] dYdC = new double[6][6];
  184.         current.getOrbit().getJacobianWrtCartesian(positionAngle, dYdC);
  185.         final RealMatrix jacParametersWrtCartesian = MatrixUtils.createRealMatrix(dYdC);

  186.         // Complete Jacobian of the transformation
  187.         final RealMatrix jacobian = jacParametersWrtCartesian.multiply(jacLofToInertial);

  188.         // Return the orbital process noise matrix in inertial frame and proper orbit type
  189.         final RealMatrix inertialOrbitalProcessNoiseMatrix = jacobian.
  190.                          multiply(lofCartesianProcessNoiseMatrix).
  191.                          multiply(jacobian.transpose());
  192.         return inertialOrbitalProcessNoiseMatrix;
  193.     }

  194.     /** Get the process noise for the propagation parameters.
  195.      * @param previous previous state
  196.      * @param current current state
  197.      * @return physical (i.e. non normalized) propagation process noise matrix
  198.      */
  199.     private RealMatrix getPropagationProcessNoiseMatrix(final SpacecraftState previous,
  200.                                                         final SpacecraftState current) {

  201.         // ΔT = duration from previous to current spacecraft state (in seconds)
  202.         final double deltaT = current.getDate().durationFrom(previous.getDate());

  203.         // Evaluate the functions, using ΔT as argument
  204.         final int      propagationProcessNoiseLength = propagationParametersEvolution.length;
  205.         final double[] propagationProcessNoiseValues = new double[propagationProcessNoiseLength];

  206.         // The function return a value which dimension is that of a standard deviation
  207.         // It needs to be squared before being put in the process noise covariance matrix
  208.         for (int i = 0; i < propagationProcessNoiseLength; i++) {
  209.             final double functionValue =  propagationParametersEvolution[i].value(deltaT);
  210.             propagationProcessNoiseValues[i] = functionValue * functionValue;
  211.         }

  212.         // Form the diagonal matrix corresponding to propagation parameters process noise
  213.         return MatrixUtils.createRealDiagonalMatrix(propagationProcessNoiseValues);
  214.     }

  215. }