PV.java
/* Copyright 2002-2018 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.estimation.measurements;
import java.util.Arrays;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.orekit.errors.OrekitException;
import org.orekit.propagation.SpacecraftState;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.TimeStampedPVCoordinates;
/** Class modeling a position-velocity state.
* @author Luc Maisonobe
* @since 8.0
*/
public class PV extends AbstractMeasurement<PV> {
/** Identity matrix, for states derivatives. */
private static final double[][] IDENTITY = new double[][] {
{
1, 0, 0, 0, 0, 0
}, {
0, 1, 0, 0, 0, 0
}, {
0, 0, 1, 0, 0, 0
}, {
0, 0, 0, 1, 0, 0
}, {
0, 0, 0, 0, 1, 0
}, {
0, 0, 0, 0, 0, 1
}
};
/** Covariance matrix of the PV measurement (size 6x6). */
private final double[][] covarianceMatrix;
/** Constructor with two double for the standard deviations.
* The first double is the position's standard deviation, common to the 3 position's components.
* The second double is the position's standard deviation, common to the 3 position's components.
* <p>
* The measurement must be in the orbit propagation frame.
* </p>
* This constructor uses 0 as the index of the propagator related
* to this measurement, thus being well suited for mono-satellite
* orbit determination.
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param sigmaPosition theoretical standard deviation on position components
* @param sigmaVelocity theoretical standard deviation on velocity components
* @param baseWeight base weight
* @throws OrekitException if the built inside covariance matrix does not have the proper size
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double sigmaPosition, final double sigmaVelocity, final double baseWeight) throws OrekitException {
this(date, position, velocity, sigmaPosition, sigmaVelocity, baseWeight, 0);
}
/** Constructor with two double for the standard deviations.
* The first double is the position's standard deviation, common to the 3 position's components.
* The second double is the position's standard deviation, common to the 3 position's components.
* <p>
* The measurement must be in the orbit propagation frame.
* </p>
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param sigmaPosition theoretical standard deviation on position components
* @param sigmaVelocity theoretical standard deviation on velocity components
* @param baseWeight base weight
* @param propagatorIndex index of the propagator related to this measurement
* @throws OrekitException if the built inside covariance matrix does not have the proper size
* @since 9.0
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double sigmaPosition, final double sigmaVelocity, final double baseWeight,
final int propagatorIndex) throws OrekitException {
this(date, position, velocity,
new double[] {
sigmaPosition,
sigmaPosition,
sigmaPosition,
sigmaVelocity,
sigmaVelocity,
sigmaVelocity
}, baseWeight, propagatorIndex);
}
/** Constructor with two vectors for the standard deviations and default value for propagator index..
* One 3-sized vectors for position standard deviations.
* One 3-sized vectors for velocity standard deviations.
* The 3-sized vectors are the square root of the diagonal elements of the covariance matrix.
* <p>The measurement must be in the orbit propagation frame.</p>
* This constructor uses 0 as the index of the propagator related
* to this measurement, thus being well suited for mono-satellite
* orbit determination.
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param sigmaPosition 3-sized vector of the standard deviations of the position
* @param sigmaVelocity 3-sized vector of the standard deviations of the velocity
* @param baseWeight base weight
* @throws OrekitException if input standard deviations vectors do not have the proper sizes
* @since 9.2
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double[] sigmaPosition, final double[] sigmaVelocity, final double baseWeight) throws OrekitException {
this(date, position, velocity, sigmaPosition, sigmaVelocity, baseWeight, 0);
}
/** Constructor with two vectors for the standard deviations.
* One 3-sized vectors for position standard deviations.
* One 3-sized vectors for velocity standard deviations.
* The 3-sized vectors are the square root of the diagonal elements of the covariance matrix.
* <p>The measurement must be in the orbit propagation frame.</p>
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param sigmaPosition 3-sized vector of the standard deviations of the position
* @param sigmaVelocity 3-sized vector of the standard deviations of the velocity
* @param baseWeight base weight
* @param propagatorIndex index of the propagator related to this measurement
* @throws OrekitException if input standard deviations vectors do not have the proper sizes
* @since 9.2
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double[] sigmaPosition, final double[] sigmaVelocity,
final double baseWeight, final int propagatorIndex) throws OrekitException {
this(date, position, velocity,
buildPvCovarianceMatrix(sigmaPosition, sigmaVelocity),
baseWeight, propagatorIndex);
}
/** Constructor with one vector for the standard deviations and default value for propagator index.
* The 6-sized vector is the square root of the diagonal elements of the covariance matrix.
* <p>The measurement must be in the orbit propagation frame.</p>
* This constructor uses 0 as the index of the propagator related
* to this measurement, thus being well suited for mono-satellite
* orbit determination.
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param sigmaPV 6-sized vector of the standard deviations
* @param baseWeight base weight
* @throws OrekitException if input standard deviations vector does not have the proper size
* @since 9.2
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double[] sigmaPV, final double baseWeight) throws OrekitException {
this(date, position, velocity, sigmaPV, baseWeight, 0);
}
/** Constructor with one vector for the standard deviations.
* The 6-sized vector is the square root of the diagonal elements of the covariance matrix.
* <p>The measurement must be in the orbit propagation frame.</p>
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param sigmaPV 6-sized vector of the standard deviations
* @param baseWeight base weight
* @param propagatorIndex index of the propagator related to this measurement
* @throws OrekitException if input standard deviations vector does not have the proper size
* @since 9.2
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double[] sigmaPV, final double baseWeight, final int propagatorIndex) throws OrekitException {
this(date, position, velocity,
buildPvCovarianceMatrix(sigmaPV),
baseWeight, propagatorIndex);
}
/**
* Constructor with 2 smaller covariance matrices and default value for propagator index.
* One 3x3 covariance matrix for position and one 3x3 covariance matrix for velocity.
* The fact that the covariance matrices are symmetric and positive definite is not checked.
* <p>The measurement must be in the orbit propagation frame.</p>
* This constructor uses 0 as the index of the propagator related
* to this measurement, thus being well suited for mono-satellite
* orbit determination.
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param positionCovarianceMatrix 3x3 covariance matrix of the position
* @param velocityCovarianceMatrix 3x3 covariance matrix of the velocity
* @param baseWeight base weight
* @throws OrekitException if input covariance matrices do not have the proper sizes
* @since 9.2
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double[][] positionCovarianceMatrix, final double[][] velocityCovarianceMatrix,
final double baseWeight) throws OrekitException {
this(date, position, velocity, positionCovarianceMatrix, velocityCovarianceMatrix, baseWeight, 0);
}
/**
* Constructor with 2 smaller covariance matrices.
* One 3x3 covariance matrix for position and one 3x3 covariance matrix for velocity.
* The fact that the covariance matrices are symmetric and positive definite is not checked.
* <p>The measurement must be in the orbit propagation frame.</p>
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param positionCovarianceMatrix 3x3 covariance matrix of the position
* @param velocityCovarianceMatrix 3x3 covariance matrix of the velocity
* @param baseWeight base weight
* @param propagatorIndex index of the propagator related to this measurement
* @throws OrekitException if input covariance matrices do not have the proper sizes
* @since 9.2
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double[][] positionCovarianceMatrix, final double[][] velocityCovarianceMatrix,
final double baseWeight, final int propagatorIndex) throws OrekitException {
this(date, position, velocity,
buildPvCovarianceMatrix(positionCovarianceMatrix, velocityCovarianceMatrix),
baseWeight, propagatorIndex);
}
/**
* Constructor with full covariance matrix but default index for propagator.
* The fact that the covariance matrix is symmetric and positive definite is not checked.
* <p>The measurement must be in the orbit propagation frame.</p>
* This constructor uses 0 as the index of the propagator related
* to this measurement, thus being well suited for mono-satellite
* orbit determination.
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param covarianceMatrix 6x6 covariance matrix of the PV measurement
* @param baseWeight base weight
* @throws OrekitException if input covariance matrix does not have the proper size
* @since 9.2
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double[][] covarianceMatrix, final double baseWeight) throws OrekitException {
this(date, position, velocity, covarianceMatrix, baseWeight, 0);
}
/** Constructor with full covariance matrix and all inputs.
* The fact that the covariance matrix is symmetric and positive definite is not checked.
* <p>The measurement must be in the orbit propagation frame.</p>
* @param date date of the measurement
* @param position position
* @param velocity velocity
* @param covarianceMatrix 6x6 covariance matrix of the PV measurement
* @param baseWeight base weight
* @param propagatorIndex index of the propagator related to this measurement
* @throws OrekitException if input covariance matrix does not have the proper size
* @since 9.2
*/
public PV(final AbsoluteDate date, final Vector3D position, final Vector3D velocity,
final double[][] covarianceMatrix, final double baseWeight, final int propagatorIndex)
throws OrekitException {
super(date,
new double[] {
position.getX(), position.getY(), position.getZ(),
velocity.getX(), velocity.getY(), velocity.getZ()
}, extractSigmas(covarianceMatrix),
new double[] {
baseWeight, baseWeight, baseWeight,
baseWeight, baseWeight, baseWeight
}, Arrays.asList(propagatorIndex));
this.covarianceMatrix = covarianceMatrix;
}
/** Get the position.
* @return position
*/
public Vector3D getPosition() {
final double[] pv = getObservedValue();
return new Vector3D(pv[0], pv[1], pv[2]);
}
/** Get the velocity.
* @return velocity
*/
public Vector3D getVelocity() {
final double[] pv = getObservedValue();
return new Vector3D(pv[3], pv[4], pv[5]);
}
/** Get the covariance matrix.
* @return the covariance matrix
*/
public double[][] getCovarianceMatrix() {
return covarianceMatrix;
}
/** Get the correlation coefficients matrix.
* <br>This is the 6x6 matrix M such that:</br>
* <br>Mij = Pij/(σi.σj)</br>
* <br>Where: <ul>
* <li> P is the covariance matrix
* <li> σi is the i-th standard deviation (σi² = Pii)
* </ul>
* @return the correlation coefficient matrix (6x6)
*/
public double[][] getCorrelationCoefficientsMatrix() {
// Get the standard deviations
final double[] sigmas = getTheoreticalStandardDeviation();
// Initialize the correlation coefficients matric to the covariance matrix
final double[][] corrCoefMatrix = new double[sigmas.length][sigmas.length];
// Divide by the standard deviations
for (int i = 0; i < sigmas.length; i++) {
for (int j = 0; j < sigmas.length; j++) {
corrCoefMatrix[i][j] = covarianceMatrix[i][j] / (sigmas[i] * sigmas[j]);
}
}
return corrCoefMatrix;
}
/** {@inheritDoc} */
@Override
protected EstimatedMeasurement<PV> theoreticalEvaluation(final int iteration, final int evaluation,
final SpacecraftState[] states)
throws OrekitException {
// PV value
final TimeStampedPVCoordinates pv = states[getPropagatorsIndices().get(0)].getPVCoordinates();
// prepare the evaluation
final EstimatedMeasurement<PV> estimated =
new EstimatedMeasurement<>(this, iteration, evaluation, states,
new TimeStampedPVCoordinates[] {
pv
});
estimated.setEstimatedValue(new double[] {
pv.getPosition().getX(), pv.getPosition().getY(), pv.getPosition().getZ(),
pv.getVelocity().getX(), pv.getVelocity().getY(), pv.getVelocity().getZ()
});
// partial derivatives with respect to state
estimated.setStateDerivatives(0, IDENTITY);
return estimated;
}
/** Extract standard deviations from a 6x6 PV covariance matrix.
* Check the size of the PV covariance matrix first.
* @param pvCovarianceMatrix the 6x6 PV covariance matrix
* @return the standard deviations (6-sized vector), they are
* the square roots of the diagonal elements of the covariance matrix in input.
* @throws OrekitException if the PV covariance matrix is not a 6x6 matrix
*/
private static double[] extractSigmas(final double[][] pvCovarianceMatrix) throws OrekitException {
// Check the size of the covariance matrix, should be 6x6
if (pvCovarianceMatrix[0].length != 6 || pvCovarianceMatrix[1].length != 6) {
throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
pvCovarianceMatrix[0].length, pvCovarianceMatrix[1],
6, 6);
}
// Extract the standard deviations (square roots of the diagonal elements)
final double[] sigmas = new double[6];
for (int i = 0; i < sigmas.length; i++) {
sigmas[i] = FastMath.sqrt(pvCovarianceMatrix[i][i]);
}
return sigmas;
}
/** Build a 6x6 PV covariance matrix from two 3x3 matrices (covariances in position and velocity).
* Check the size of the matrices first.
* @param positionCovarianceMatrix the 3x3 covariance matrix in position
* @param velocityCovarianceMatrix the 3x3 covariance matrix in velocity
* @return the 6x6 PV covariance matrix
* @throws OrekitException if the matrices do not have the proper size
*/
private static double[][] buildPvCovarianceMatrix(final double[][] positionCovarianceMatrix,
final double[][] velocityCovarianceMatrix)
throws OrekitException {
// Check the sizes of the matrices first
if (positionCovarianceMatrix[0].length != 3 || positionCovarianceMatrix[1].length != 3) {
throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
positionCovarianceMatrix[0].length, positionCovarianceMatrix[1],
3, 3);
}
if (velocityCovarianceMatrix[0].length != 3 || velocityCovarianceMatrix[1].length != 3) {
throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
velocityCovarianceMatrix[0].length, velocityCovarianceMatrix[1],
3, 3);
}
// Build the PV 6x6 covariance matrix
final double[][] pvCovarianceMatrix = new double[6][6];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
pvCovarianceMatrix[i][j] = positionCovarianceMatrix[i][j];
pvCovarianceMatrix[i + 3][j + 3] = velocityCovarianceMatrix[i][j];
}
}
return pvCovarianceMatrix;
}
/** Build a 6x6 PV covariance matrix from a 6-sized vector (position and velocity standard deviations).
* Check the size of the vector first.
* @param sigmaPV 6-sized vector with position standard deviations on the first 3 elements
* and velocity standard deviations on the last 3 elements
* @return the 6x6 PV covariance matrix
* @throws OrekitException if the size of the vector is different from 6
*/
private static double[][] buildPvCovarianceMatrix(final double[] sigmaPV) throws OrekitException {
// Check the size of the vector first
if (sigmaPV.length != 6) {
throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH, sigmaPV.length, 6);
}
// Build the PV 6x6 covariance matrix
final double[][] pvCovarianceMatrix = new double[6][6];
for (int i = 0; i < sigmaPV.length; i++) {
pvCovarianceMatrix[i][i] = sigmaPV[i] * sigmaPV[i];
}
return pvCovarianceMatrix;
}
/** Build a 6x6 PV covariance matrix from two 3-sized vectors (position and velocity standard deviations).
* Check the sizes of the vectors first.
* @param sigmaPosition standard deviations of the position (3-size vector)
* @param sigmaVelocity standard deviations of the velocity (3-size vector)
* @return the 6x6 PV covariance matrix
* @throws OrekitException if the vectors do not have the proper sizes
*/
private static double[][] buildPvCovarianceMatrix(final double[] sigmaPosition,
final double[] sigmaVelocity)
throws OrekitException {
// Check the sizes of the vectors first
if (sigmaPosition.length != 3) {
throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH, sigmaPosition.length, 3);
}
if (sigmaVelocity.length != 3) {
throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH, sigmaVelocity.length, 3);
}
// Build the PV 6x6 covariance matrix
final double[][] pvCovarianceMatrix = new double[6][6];
for (int i = 0; i < sigmaPosition.length; i++) {
pvCovarianceMatrix[i][i] = sigmaPosition[i] * sigmaPosition[i];
pvCovarianceMatrix[i + 3][i + 3] = sigmaVelocity[i] * sigmaVelocity[i];
}
return pvCovarianceMatrix;
}
}