PV.java

  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.measurements;

  18. import java.util.Collections;

  19. import org.hipparchus.exception.LocalizedCoreFormats;
  20. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  21. import org.hipparchus.util.FastMath;
  22. import org.orekit.errors.OrekitException;
  23. import org.orekit.propagation.SpacecraftState;
  24. import org.orekit.time.AbsoluteDate;
  25. import org.orekit.utils.TimeStampedPVCoordinates;

  26. /** Class modeling a position-velocity measurement.
  27.  * <p>
  28.  * For position-only measurement see {@link Position}.
  29.  * </p>
  30.  * @see Position
  31.  * @author Luc Maisonobe
  32.  * @since 8.0
  33.  */
  34. public class PV extends AbstractMeasurement<PV> {

  35.     /** Type of the measurement. */
  36.     public static final String MEASUREMENT_TYPE = "PV";

  37.     /** Identity matrix, for states derivatives. */
  38.     private static final double[][] IDENTITY = new double[][] {
  39.         {
  40.             1, 0, 0, 0, 0, 0
  41.         }, {
  42.             0, 1, 0, 0, 0, 0
  43.         }, {
  44.             0, 0, 1, 0, 0, 0
  45.         }, {
  46.             0, 0, 0, 1, 0, 0
  47.         }, {
  48.             0, 0, 0, 0, 1, 0
  49.         }, {
  50.             0, 0, 0, 0, 0, 1
  51.         }
  52.     };

  53.     /** Covariance matrix of the PV measurement (size 6x6). */
  54.     private final double[][] covarianceMatrix;

  55.     /** Constructor with two double for the standard deviations.
  56.      * <p>The first double is the position's standard deviation, common to the 3 position's components.
  57.      * The second double is the position's standard deviation, common to the 3 position's components.</p>
  58.      * <p>
  59.      * The measurement must be in the orbit propagation frame.
  60.      * </p>
  61.      * @param date date of the measurement
  62.      * @param position position
  63.      * @param velocity velocity
  64.      * @param sigmaPosition theoretical standard deviation on position components
  65.      * @param sigmaVelocity theoretical standard deviation on velocity components
  66.      * @param baseWeight base weight
  67.      * @param satellite satellite related to this measurement
  68.      * @since 9.3
  69.      */
  70.     public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
  71.               final double sigmaPosition, final double sigmaVelocity, final double baseWeight,
  72.               final ObservableSatellite satellite) {
  73.         this(date, position, velocity,
  74.              new double[] {
  75.                  sigmaPosition,
  76.                  sigmaPosition,
  77.                  sigmaPosition,
  78.                  sigmaVelocity,
  79.                  sigmaVelocity,
  80.                  sigmaVelocity
  81.              }, baseWeight, satellite);
  82.     }

  83.     /** Constructor with two vectors for the standard deviations.
  84.      * <p>One 3-sized vectors for position standard deviations.
  85.      * One 3-sized vectors for velocity standard deviations.
  86.      * The 3-sized vectors are the square root of the diagonal elements of the covariance matrix.</p>
  87.      * <p>The measurement must be in the orbit propagation frame.</p>
  88.      * @param date date of the measurement
  89.      * @param position position
  90.      * @param velocity velocity
  91.      * @param sigmaPosition 3-sized vector of the standard deviations of the position
  92.      * @param sigmaVelocity 3-sized vector of the standard deviations of the velocity
  93.      * @param baseWeight base weight
  94.      * @param satellite satellite related to this measurement
  95.      * @since 9.3
  96.      */
  97.     public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
  98.               final double[] sigmaPosition, final double[] sigmaVelocity,
  99.               final double baseWeight, final ObservableSatellite satellite) {
  100.         this(date, position, velocity,
  101.              buildPvCovarianceMatrix(sigmaPosition, sigmaVelocity),
  102.              baseWeight, satellite);
  103.     }

  104.     /** Constructor with one vector for the standard deviations.
  105.      * <p>The 6-sized vector is the square root of the diagonal elements of the covariance matrix.</p>
  106.      * <p>The measurement must be in the orbit propagation frame.</p>
  107.      * @param date date of the measurement
  108.      * @param position position
  109.      * @param velocity velocity
  110.      * @param sigmaPV 6-sized vector of the standard deviations
  111.      * @param baseWeight base weight
  112.      * @param satellite satellite related to this measurement
  113.      * @since 9.3
  114.      */
  115.     public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
  116.               final double[] sigmaPV, final double baseWeight, final ObservableSatellite satellite) {
  117.         this(date, position, velocity, buildPvCovarianceMatrix(sigmaPV), baseWeight, satellite);
  118.     }

  119.     /**
  120.      * Constructor with 2 smaller covariance matrices.
  121.      * <p>One 3x3 covariance matrix for position and one 3x3 covariance matrix for velocity.
  122.      * The fact that the covariance matrices are symmetric and positive definite is not checked.</p>
  123.      * <p>The measurement must be in the orbit propagation frame.</p>
  124.      * @param date date of the measurement
  125.      * @param position position
  126.      * @param velocity velocity
  127.      * @param positionCovarianceMatrix 3x3 covariance matrix of the position
  128.      * @param velocityCovarianceMatrix 3x3 covariance matrix of the velocity
  129.      * @param baseWeight base weight
  130.      * @param satellite satellite related to this measurement
  131.      * @since 9.3
  132.      */
  133.     public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
  134.               final double[][] positionCovarianceMatrix, final double[][] velocityCovarianceMatrix,
  135.               final double baseWeight, final ObservableSatellite satellite) {
  136.         this(date, position, velocity,
  137.              buildPvCovarianceMatrix(positionCovarianceMatrix, velocityCovarianceMatrix),
  138.              baseWeight, satellite);
  139.     }

  140.     /** Constructor with full covariance matrix and all inputs.
  141.      * <p>The fact that the covariance matrix is symmetric and positive definite is not checked.</p>
  142.      * <p>The measurement must be in the orbit propagation frame.</p>
  143.      * @param date date of the measurement
  144.      * @param position position
  145.      * @param velocity velocity
  146.      * @param covarianceMatrix 6x6 covariance matrix of the PV measurement
  147.      * @param baseWeight base weight
  148.      * @param satellite satellite related to this measurement
  149.      * @since 9.3
  150.      */
  151.     public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
  152.               final double[][] covarianceMatrix, final double baseWeight, final ObservableSatellite satellite) {
  153.         super(date,
  154.               new double[] {
  155.                   position.getX(), position.getY(), position.getZ(),
  156.                   velocity.getX(), velocity.getY(), velocity.getZ()
  157.               }, extractSigmas(covarianceMatrix),
  158.               new double[] {
  159.                   baseWeight, baseWeight, baseWeight,
  160.                   baseWeight, baseWeight, baseWeight
  161.               }, Collections.singletonList(satellite));
  162.         this.covarianceMatrix = covarianceMatrix.clone();
  163.     }

  164.     /** Get the position.
  165.      * @return position
  166.      */
  167.     public Vector3D getPosition() {
  168.         final double[] pv = getObservedValue();
  169.         return new Vector3D(pv[0], pv[1], pv[2]);
  170.     }

  171.     /** Get the velocity.
  172.      * @return velocity
  173.      */
  174.     public Vector3D getVelocity() {
  175.         final double[] pv = getObservedValue();
  176.         return new Vector3D(pv[3], pv[4], pv[5]);
  177.     }

  178.     /** Get the covariance matrix.
  179.      * @return the covariance matrix
  180.      */
  181.     public double[][] getCovarianceMatrix() {
  182.         return covarianceMatrix.clone();
  183.     }

  184.     /** Get the correlation coefficients matrix.
  185.      * <p>This is the 6x6 matrix M such that:
  186.      * <p>Mij = Pij/(σi.σj)
  187.      * <p>Where:
  188.      * <ul>
  189.      * <li>P is the covariance matrix
  190.      * <li>σi is the i-th standard deviation (σi² = Pii)
  191.      * </ul>
  192.      * @return the correlation coefficient matrix (6x6)
  193.      */
  194.     public double[][] getCorrelationCoefficientsMatrix() {

  195.         // Get the standard deviations
  196.         final double[] sigmas = getTheoreticalStandardDeviation();

  197.         // Initialize the correlation coefficients matric to the covariance matrix
  198.         final double[][] corrCoefMatrix = new double[sigmas.length][sigmas.length];

  199.         // Divide by the standard deviations
  200.         for (int i = 0; i < sigmas.length; i++) {
  201.             for (int j = 0; j < sigmas.length; j++) {
  202.                 corrCoefMatrix[i][j] = covarianceMatrix[i][j] / (sigmas[i] * sigmas[j]);
  203.             }
  204.         }
  205.         return corrCoefMatrix;
  206.     }

  207.     /** {@inheritDoc} */
  208.     @Override
  209.     protected EstimatedMeasurementBase<PV> theoreticalEvaluationWithoutDerivatives(final int iteration, final int evaluation,
  210.                                                                                    final SpacecraftState[] states) {

  211.         // PV value
  212.         final TimeStampedPVCoordinates pv = states[0].getPVCoordinates();

  213.         // prepare the evaluation
  214.         final EstimatedMeasurementBase<PV> estimated =
  215.                         new EstimatedMeasurementBase<>(this, iteration, evaluation, states,
  216.                                                        new TimeStampedPVCoordinates[] {
  217.                                                            pv
  218.                                                        });

  219.         estimated.setEstimatedValue(pv.getPosition().getX(), pv.getPosition().getY(), pv.getPosition().getZ(),
  220.                 pv.getVelocity().getX(), pv.getVelocity().getY(), pv.getVelocity().getZ());

  221.         return estimated;

  222.     }

  223.     /** {@inheritDoc} */
  224.     @Override
  225.     protected EstimatedMeasurement<PV> theoreticalEvaluation(final int iteration, final int evaluation,
  226.                                                              final SpacecraftState[] states) {
  227.         final EstimatedMeasurement<PV> estimated = new EstimatedMeasurement<>(theoreticalEvaluationWithoutDerivatives(iteration, evaluation, states));

  228.         // partial derivatives with respect to state
  229.         estimated.setStateDerivatives(0, IDENTITY);

  230.         return estimated;
  231.     }

  232.     /** Extract standard deviations from a 6x6 PV covariance matrix.
  233.      * Check the size of the PV covariance matrix first.
  234.      * @param pvCovarianceMatrix the 6x6 PV covariance matrix
  235.      * @return the standard deviations (6-sized vector), they are
  236.      * the square roots of the diagonal elements of the covariance matrix in input.
  237.      */
  238.     private static double[] extractSigmas(final double[][] pvCovarianceMatrix) {

  239.         // Check the size of the covariance matrix, should be 6x6
  240.         if (pvCovarianceMatrix.length != 6 || pvCovarianceMatrix[0].length != 6) {
  241.             throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  242.                                       pvCovarianceMatrix.length, pvCovarianceMatrix[0],
  243.                                       6, 6);
  244.         }

  245.         // Extract the standard deviations (square roots of the diagonal elements)
  246.         final double[] sigmas = new double[6];
  247.         for (int i = 0; i < sigmas.length; i++) {
  248.             sigmas[i] = FastMath.sqrt(pvCovarianceMatrix[i][i]);
  249.         }
  250.         return sigmas;
  251.     }

  252.     /** Build a 6x6 PV covariance matrix from two 3x3 matrices (covariances in position and velocity).
  253.      * Check the size of the matrices first.
  254.      * @param positionCovarianceMatrix the 3x3 covariance matrix in position
  255.      * @param velocityCovarianceMatrix the 3x3 covariance matrix in velocity
  256.      * @return the 6x6 PV covariance matrix
  257.      */
  258.     private static double[][] buildPvCovarianceMatrix(final double[][] positionCovarianceMatrix,
  259.                                                       final double[][] velocityCovarianceMatrix) {
  260.         // Check the sizes of the matrices first
  261.         if (positionCovarianceMatrix.length != 3 || positionCovarianceMatrix[0].length != 3) {
  262.             throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  263.                                       positionCovarianceMatrix.length, positionCovarianceMatrix[0],
  264.                                       3, 3);
  265.         }
  266.         if (velocityCovarianceMatrix.length != 3 || velocityCovarianceMatrix[0].length != 3) {
  267.             throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  268.                                       velocityCovarianceMatrix.length, velocityCovarianceMatrix[0],
  269.                                       3, 3);
  270.         }

  271.         // Build the PV 6x6 covariance matrix
  272.         final double[][] pvCovarianceMatrix = new double[6][6];
  273.         for (int i = 0; i < 3; i++) {
  274.             for (int j = 0; j < 3; j++) {
  275.                 pvCovarianceMatrix[i][j]         = positionCovarianceMatrix[i][j];
  276.                 pvCovarianceMatrix[i + 3][j + 3] = velocityCovarianceMatrix[i][j];
  277.             }
  278.         }
  279.         return pvCovarianceMatrix;
  280.     }

  281.     /** Build a 6x6 PV covariance matrix from a 6-sized vector (position and velocity standard deviations).
  282.      * Check the size of the vector first.
  283.      * @param sigmaPV 6-sized vector with position standard deviations on the first 3 elements
  284.      * and velocity standard deviations on the last 3 elements
  285.      * @return the 6x6 PV covariance matrix
  286.      */
  287.     private static double[][] buildPvCovarianceMatrix(final double[] sigmaPV) {
  288.         // Check the size of the vector first
  289.         if (sigmaPV.length != 6) {
  290.             throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH, sigmaPV.length, 6);

  291.         }

  292.         // Build the PV 6x6 covariance matrix
  293.         final double[][] pvCovarianceMatrix = new double[6][6];
  294.         for (int i = 0; i < sigmaPV.length; i++) {
  295.             pvCovarianceMatrix[i][i] =  sigmaPV[i] * sigmaPV[i];
  296.         }
  297.         return pvCovarianceMatrix;
  298.     }

  299.     /** Build a 6x6 PV covariance matrix from two 3-sized vectors (position and velocity standard deviations).
  300.      * Check the sizes of the vectors first.
  301.      * @param sigmaPosition standard deviations of the position (3-size vector)
  302.      * @param sigmaVelocity standard deviations of the velocity (3-size vector)
  303.      * @return the 6x6 PV covariance matrix
  304.      */
  305.     private static double[][] buildPvCovarianceMatrix(final double[] sigmaPosition,
  306.                                                       final double[] sigmaVelocity) {

  307.         // Check the sizes of the vectors first
  308.         if (sigmaPosition.length != 3) {
  309.             throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH, sigmaPosition.length, 3);

  310.         }
  311.         if (sigmaVelocity.length != 3) {
  312.             throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH, sigmaVelocity.length, 3);

  313.         }

  314.         // Build the PV 6x6 covariance matrix
  315.         final double[][] pvCovarianceMatrix = new double[6][6];
  316.         for (int i = 0; i < sigmaPosition.length; i++) {
  317.             pvCovarianceMatrix[i][i]         =  sigmaPosition[i] * sigmaPosition[i];
  318.             pvCovarianceMatrix[i + 3][i + 3] =  sigmaVelocity[i] * sigmaVelocity[i];
  319.         }
  320.         return pvCovarianceMatrix;
  321.     }
  322. }