UnivariateProcessNoise.java

  1. /* Copyright 2002-2018 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 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.  * <p>
  62.  * WARNING: as of release 9.2, this feature is still considered experimental
  63.  * </p>
  64.  * @author Luc Maisonobe
  65.  * @author Maxime Journot
  66.  * @since 9.2
  67.  */
  68. public class UnivariateProcessNoise extends AbstractCovarianceMatrixProvider {

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

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

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

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

  77.     /** Simple constructor.
  78.      * @param initialCovarianceMatrix initial covariance matrix
  79.      * @param lofType the LOF type used
  80.      * @param positionAngle the position angle used for the computation of the process noise
  81.      * @param lofCartesianOrbitalParametersEvolution Array of univariate functions for the six orbital parameters process noise evolution in LOF frame and Cartesian orbit type
  82.      * @param propagationParametersEvolution Array of univariate functions for the propagation parameters process noise evolution
  83.      * @throws OrekitException if lofOrbitalParametersEvolution array size is different from 6
  84.      */
  85.     public UnivariateProcessNoise(final RealMatrix initialCovarianceMatrix,
  86.                                   final LOFType lofType,
  87.                                   final PositionAngle positionAngle,
  88.                                   final UnivariateFunction[] lofCartesianOrbitalParametersEvolution,
  89.                                   final UnivariateFunction[] propagationParametersEvolution)
  90.         throws OrekitException {
  91.         super(initialCovarianceMatrix);
  92.         this.lofType = lofType;
  93.         this.positionAngle = positionAngle;
  94.         this.lofCartesianOrbitalParametersEvolution  = lofCartesianOrbitalParametersEvolution;
  95.         this.propagationParametersEvolution = propagationParametersEvolution;

  96.         // Ensure that the orbital evolution array size is 6
  97.         if (lofCartesianOrbitalParametersEvolution.length != 6) {
  98.             throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  99.                                       lofCartesianOrbitalParametersEvolution, 6);
  100.         }
  101.     }

  102.     /** Getter for the lofType.
  103.      * @return the lofType
  104.      */
  105.     public LOFType getLofType() {
  106.         return lofType;
  107.     }

  108.     /** Getter for the positionAngle.
  109.      * @return the positionAngle
  110.      */
  111.     public PositionAngle getPositionAngle() {
  112.         return positionAngle;
  113.     }

  114.     /** Getter for the lofCartesianOrbitalParametersEvolution.
  115.      * @return the lofCartesianOrbitalParametersEvolution
  116.      */
  117.     public UnivariateFunction[] getLofCartesianOrbitalParametersEvolution() {
  118.         return lofCartesianOrbitalParametersEvolution;
  119.     }

  120.     /** Getter for the propagationParametersEvolution.
  121.      * @return the propagationParametersEvolution
  122.      */
  123.     public UnivariateFunction[] getPropagationParametersEvolution() {
  124.         return propagationParametersEvolution;
  125.     }

  126.     /** {@inheritDoc} */
  127.     @Override
  128.     public RealMatrix getProcessNoiseMatrix(final SpacecraftState previous,
  129.                                             final SpacecraftState current) {

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

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

  133.             // no propagation parameters contribution, just return the orbital part
  134.             return inertialOrbitalProcessNoiseMatrix;

  135.         } else {

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

  138.             // Concatenate the matrices
  139.             final int        orbitalMatrixSize     = lofCartesianOrbitalParametersEvolution.length;
  140.             final int        propagationMatrixSize = propagationParametersEvolution.length;
  141.             final RealMatrix processNoiseMatrix    = MatrixUtils.createRealMatrix(orbitalMatrixSize + propagationMatrixSize,
  142.                                                                                   orbitalMatrixSize + propagationMatrixSize);
  143.             processNoiseMatrix.setSubMatrix(inertialOrbitalProcessNoiseMatrix.getData(), 0, 0);
  144.             processNoiseMatrix.setSubMatrix(propagationProcessNoiseMatrix.getData(), orbitalMatrixSize, orbitalMatrixSize);
  145.             return processNoiseMatrix;

  146.         }
  147.     }

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

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

  157.         // Evaluate the functions, using ΔT as argument
  158.         final int      lofOrbitalprocessNoiseLength = lofCartesianOrbitalParametersEvolution.length;
  159.         final double[] lofOrbitalProcessNoiseValues = new double[lofOrbitalprocessNoiseLength];

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

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

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

  171.         // Jacobian from LOF to inertial frame
  172.         final RealMatrix jacLofToInertial = MatrixUtils.createRealMatrix(6, 6);
  173.         jacLofToInertial.setSubMatrix(lofToInertialRotation, 0, 0);
  174.         jacLofToInertial.setSubMatrix(lofToInertialRotation, 3, 3);

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

  187.         // Jacobian of orbit parameters with respect to Cartesian parameters
  188.         final double[][] dYdC = new double[6][6];
  189.         current.getOrbit().getJacobianWrtCartesian(positionAngle, dYdC);
  190.         final RealMatrix jacParametersWrtCartesian = MatrixUtils.createRealMatrix(dYdC);

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

  193.         // Return the orbital process noise matrix in inertial frame and proper orbit type
  194.         final RealMatrix inertialOrbitalProcessNoiseMatrix = jacobian.
  195.                          multiply(lofCartesianProcessNoiseMatrix).
  196.                          multiply(jacobian.transpose());
  197.         return inertialOrbitalProcessNoiseMatrix;
  198.     }

  199.     /** Get the process noise for the propagation parameters.
  200.      * @param previous previous state
  201.      * @param current current state
  202.      * @return physical (i.e. non normalized) propagation process noise matrix
  203.      */
  204.     private RealMatrix getPropagationProcessNoiseMatrix(final SpacecraftState previous,
  205.                                                         final SpacecraftState current) {

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

  208.         // Evaluate the functions, using ΔT as argument
  209.         final int      propagationProcessNoiseLength = propagationParametersEvolution.length;
  210.         final double[] propagationProcessNoiseValues = new double[propagationProcessNoiseLength];

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

  217.         // Form the diagonal matrix corresponding to propagation parameters process noise
  218.         return MatrixUtils.createRealDiagonalMatrix(propagationProcessNoiseValues);
  219.     }

  220. }