Covariance Matrix Conversion from EME2000 to RSW(LVLH)

Hi All,

I would like to ask you a question related to the frame conversion.
I have tried to reproduce the same results contained in the reference:
http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=228F9B8C8C12C753831CCFA81843FE5B?doi=10.1.1.112.5780&rep=rep1&type=pdf

In particular I tried to reproduce the transformation of the covariance matrix from EME2000 to the RSW (LVLH)
frame at page 19.

What I have seen, is that I am able to reproduce the same results of the reference only when using the freeze()
method when getting the Transform from EME2000 to the RSW.
By using this method the resulting Jacobian has the lower left block full of zeros, due to the angular term which is discarded.
While when not using it, the lower left block takes into account the angular rotation term.

Here below I have attached the main method that I am using:

public static void main(String[] args) throws OrekitException {

    String orekitDataPath = args[0];
    DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(new File(orekitDataPath)));

    AbsoluteDate date = new AbsoluteDate(2000, 12, 15, 16, 58, 50.208, TimeScalesFactory.getUTC());

    Frame eme2000 = FramesFactory.getEME2000();

    Vector3D position = new Vector3D(-605792.21660, -5870229.51108, 3493053.19896);
    Vector3D velocity = new Vector3D(-1568.25429, -3702.34891, -6479.48395);
    PVCoordinates pvCoordinates = new PVCoordinates(position, velocity);

    CartesianOrbit orbit = new CartesianOrbit(pvCoordinates, eme2000, date, Constants.EGM96_EARTH_MU);
    LocalOrbitalFrame rsw = new LocalOrbitalFrame(eme2000, LOFType.LVLH, orbit, "RSW");

    Array2DRowRealMatrix covariance = new Array2DRowRealMatrix(
            new double[][] {
                { 1,    1e-2, 1e-2, 1e-4, 1e-4, 1e-4 },
                { 1e-2, 1,    1e-2, 1e-4, 1e-4, 1e-4 },
                { 1e-2, 1e-2, 1,    1e-4, 1e-4, 1e-4 },
                { 1e-4, 1e-4, 1e-4, 1e-6, 1e-6, 1e-6 },
                { 1e-4, 1e-4, 1e-4, 1e-6, 1e-6, 1e-6 },
                { 1e-4, 1e-4, 1e-4, 1e-6, 1e-6, 1e-6 } });

    double[][] jacobianDoubleArray = new double[6][6];

    Transform t = eme2000.getTransformTo(rsw, date);

    t.getJacobian(CartesianDerivativesFilter.USE_PV, jacobianDoubleArray);

    RealMatrix jacobianNoFreeze = new Array2DRowRealMatrix(jacobianDoubleArray);

    RealMatrix transformedCovariance = jacobianNoFreeze.multiply(covariance.multiply(jacobianNoFreeze.transpose()));

    System.out.println("----------- COVARIANCE RSW NO FREEZE--------------");
    for (int i = 0; i <= 5; i++) {

        for (int j = 0; j <= 5; j++) {
            System.out.println("Component" + "[" + i + "]" + "[" + j + "]" + " = " + String.format("%6.6e", transformedCovariance.getEntry(i, j)));
        }
    }

    System.out.println("----------- JACOBIAN EME2000 -> RSW NO FREEZE--------------");
    for (int i = 0; i <= 5; i++) {

        for (int j = 0; j <= 5; j++) {
            System.out.println("Component" + "[" + i + "]" + "[" + j + "]" + " = " + String.format("%6.6e", jacobianNoFreeze.getEntry(i, j)));
        }
    }

        t = eme2000.getTransformTo(rsw, date).freeze();

        t.getJacobian(CartesianDerivativesFilter.USE_PV, jacobianDoubleArray);

        RealMatrix jacobianFreeze = new Array2DRowRealMatrix(jacobianDoubleArray);

        transformedCovariance = jacobianFreeze.multiply(covariance.multiply(jacobianFreeze.transpose()));

    System.out.println("----------- COVARIANCE RSW WITH FREEZE--------------");
    for (int i = 0; i <= 5; i++) {

        for (int j = 0; j <= 5; j++) {
            System.out.println("Component" + "[" + i + "]" + "[" + j + "]" + " = " + String.format("%6.6e", transformedCovariance.getEntry(i, j)));
        }
    }

    System.out.println("----------- JACOBIAN EME2000 -> RSW WITH FREEZE--------------");
    for (int i = 0; i <= 5; i++) {

        for (int j = 0; j <= 5; j++) {
            System.out.println("Component" + "[" + i + "]" + "[" + j + "]" + " = " + String.format("%6.6e", jacobianFreeze.getEntry(i, j)));
        }
    }

    System.out.println("----------- DELTA JACOBIAN -------------");
    for (int i = 0; i <= 5; i++) {

        for (int j = 0; j <= 5; j++) {
            System.out.println("Component" + "[" + i + "]" + "[" + j + "]" + " = " + (jacobianFreeze.getEntry(i, j) - jacobianNoFreeze.getEntry(i, j)));
        }
    }

}

Coming to my questions:

  • In the references that I was able to find (including the one that I have linked), the Jacobian to transform from an inertial frame to the RSW has always the lower left block filled with zeros.
    Why instead when queering for the same Jacobian in Orekit the default behavior is to take the angular term into account also for this transformation?
  • Is the freeze() method supposed to be used for such a case?

Thank you really much for your time and your answer.

Leonardo

Hi Leonardo,

In Vallado’s paper that you reference he assumes that RSW is an inertial frame, though he does not specifically state this assumption. Having zeros is lower left block is correct for transforming between two frames that are not moving w.r.t. each other. In Orekit local orbital frames move with the satellite they’re attached to, correctly accounting for the relative motion. If you want an inertial frame that is aligned with LVLH at a particular instant in time then using the freeze method is the correct way to do that. So Orekit provides both options. Does that answer your question?

Regards,
Evan

2 Likes

Hi Evan,

thank you really much for your reply. Yes, your answer is what I was looking for.

Thanks again

Regards,
Leonardo

1 Like

Thank you both, very useful question and answer!