Hello,
I have some doubts regarding covariance propagation.
First of all I’d like to ask you some theoretical notions, just to make sure I am fully understanding the logics behind what implemented in this regard.
Following the Vallado “Fundamentals of Astrodynamics and Applications”, I understood that the state transition matrix and the error state transtion matrix are two different things. Can you confirm me that with the MatricesHarvester.getStateTransitionMatrix what I retrieve is actually the error state transition matrix (which is nothing else than the Jacobian matrix dY/dY0)?
Going into the code, I initially implemented the following example:
public static void main(String[] args) {
// Initial state
Vector3D position = new Vector3D(-605000.7922166, -5870000.2295111, 3493000.0531990);
Vector3D velocity = new Vector3D(-1568.254290, -3702.348910, -6479.483950);
PVCoordinates cartCoord = new PVCoordinates(position, velocity);
AbsoluteDate startingEpoch = new AbsoluteDate(2022, 01, 01, 00, 00, 0.0, TimeScalesFactory.getTAI());
AbsoluteDate finalEpoch = new AbsoluteDate(2022, 01, 01, 01, 00, 0.0, TimeScalesFactory.getTAI());
CartesianOrbit initOrbit = new CartesianOrbit(cartCoord, FramesFactory.getGCRF(), startingEpoch, Constants.IERS2010_EARTH_MU);
double[][] cartCov = {{1.000000e+02, 1.000000e-02, 1.000000e-02, 1.000000e-04, 1.000000e-04, 1.000000e-04},
{1.000000e-02, 1.000000e+02, 1.000000e-02, 1.000000e-04, 1.000000e-04, 1.000000e-04},
{1.000000e-02, 1.000000e-02, 1.000000e+02, 1.000000e-04, 1.000000e-04, 1.000000e-04},
{1.000000e-04, 1.000000e-04, 1.000000e-04, 1.000000e-04, 1.000000e-06, 1.000000e-06},
{1.000000e-04, 1.000000e-04, 1.000000e-04, 1.000000e-06, 1.000000e-04, 1.000000e-06},
{1.000000e-04, 1.000000e-04, 1.000000e-04, 1.000000e-06, 1.000000e-06, 1.000000e-04}};
RealMatrix covariance = new Array2DRowRealMatrix(cartCov);
// numerical propagator
double[][] tolerance = NumericalPropagator.tolerances(1, 0.1, initOrbit, OrbitType.CARTESIAN);
ODEIntegrator odeIntegrator = new DormandPrince853Integrator(0.01, 10, tolerance[0], tolerance[1]);
NumericalPropagator prop = new NumericalPropagator(odeIntegrator);
prop.setInitialState(new SpacecraftState(initOrbit));
prop.setOrbitType(OrbitType.CARTESIAN);
MatricesHarvester harvester = prop.setupMatricesComputation("stm", null, null);
List<SpacecraftState> spacecraftStateList = new ArrayList<SpacecraftState>();
prop.getMultiplexer().add(60, new PropagationStepHandler(spacecraftStateList, harvester, covariance));
prop.propagate(finalEpoch);
}
// Step handler
private static class PropagationStepHandler implements OrekitFixedStepHandler {
private MatricesHarvester harvester;
private RealMatrix covariance;
public PropagationStepHandler(List<SpacecraftState> spacecraftStateList, MatricesHarvester harvester, RealMatrix covariance) {
this.harvester = harvester;
this.covariance = covariance;
}
@Override
public void handleStep(SpacecraftState currentState) {
RealMatrix dYdY0 = harvester.getStateTransitionMatrix(currentState);
covariance = dYdY0.multiply(covariance.multiplyTransposed(dYdY0));
System.out.println(currentState.getDate() + " = " + Math.sqrt(Math.pow(covariance.getEntry(0, 0), 2) +
Math.pow(covariance.getEntry(1, 1), 2) +
Math.pow(covariance.getEntry(2, 2), 2)));
harvester.setReferenceState(currentState);
}
}
With this implementation, the results are really bad. To get reasonable results, I had to change the handleStep method as follows:
@Override
public void handleStep(SpacecraftState currentState) {
RealMatrix dYdY0 = harvester.getStateTransitionMatrix(currentState);
RealMatrix currentCovariance = dYdY0.multiply(initialCovariance.multiplyTransposed(dYdY0));
System.out.println(currentState.getDate() + " = " + Math.sqrt(Math.pow(currentCovariance.getEntry(0, 0), 2) +
Math.pow(currentCovariance.getEntry(1, 1), 2) +
Math.pow(currentCovariance.getEntry(2, 2), 2)));
}
Based on this, I have some questions…
In this case, it seems to me that I am always computing the STM based on the initial reference conditions “Y0”. Since the STM comes from a linearization process, isn’t it wrong to always refer to that initial point? That is why in my previous version I thought it was correct to set a different reference state of the harvester at each iteration, and then calculate the new covariance matrix starting from the last one (and not always from the initial covariance matrix).
Referring to src/main/java/org/orekit/tutorials/propagation/CovariancePropagation.java · develop · Orekit / Orekit tutorials · GitLab, also in here I don’t understand why we can compute the propagated covariance matrix after one entire day using a STM which has as reference point the very initial Y0 conditions.
Sorry for the very long message.
Have a nice evening!
Claudio