org.orekit.frames.TIRFProviderTest.java Source code

Java tutorial

Introduction

Here is the source code for org.orekit.frames.TIRFProviderTest.java

Source

/* Licensed to CS Systmes 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.frames;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.apache.commons.math3.util.FastMath;
import org.apache.commons.math3.util.Precision;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.errors.OrekitException;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.TimeComponents;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.AngularCoordinates;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinates;

/**
 * Unit tests for {@link TIRFProvider}.
 *
 * @author Evan Ward
 */
public class TIRFProviderTest {

    @Test
    public void testAASReferenceLEO() throws OrekitException {

        // this reference test has been extracted from the following paper:
        // Implementation Issues Surrounding the New IAU Reference Systems for Astrodynamics
        // David A. Vallado, John H. Seago, P. Kenneth Seidelmann
        // http://www.centerforspace.com/downloads/files/pubs/AAS-06-134.pdf
        // Reference position & velocity from : "Fundamentals of Astrodynamics and Applications", Third edition, David A. Vallado
        Utils.setLoaders(IERSConventions.IERS_2010, Utils.buildEOPList(IERSConventions.IERS_2010, new double[][] {
                { 53098, -0.4399619, 0.0015563, -0.140682, 0.333309, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53099, -0.4399619, 0.0015563, -0.140682, 0.333309, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53100, -0.4399619, 0.0015563, -0.140682, 0.333309, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53101, -0.4399619, 0.0015563, -0.140682, 0.333309, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53102, -0.4399619, 0.0015563, -0.140682, 0.333309, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53103, -0.4399619, 0.0015563, -0.140682, 0.333309, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53104, -0.4399619, 0.0015563, -0.140682, 0.333309, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53105, -0.4399619, 0.0015563, -0.140682, 0.333309, Double.NaN, Double.NaN, -0.000199,
                        -0.000252 } }));
        AbsoluteDate t0 = new AbsoluteDate(new DateComponents(2004, 04, 06), new TimeComponents(07, 51, 28.386009),
                TimeScalesFactory.getUTC());

        // Positions LEO
        Frame itrfA = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
        PVCoordinates pvITRF = new PVCoordinates(new Vector3D(-1033479.3830, 7901295.2754, 6380356.5958),
                new Vector3D(-3225.636520, -2872.451450, 5531.924446));

        // Reference coordinates
        Frame tirf = FramesFactory.getTIRF(IERSConventions.IERS_2010);
        PVCoordinates pvTIRF = new PVCoordinates(new Vector3D(-1033475.0312, 7901305.5856, 6380344.5328),
                new Vector3D(-3225.632747, -2872.442511, 5531.931288));
        checkPV(pvTIRF, itrfA.getTransformTo(tirf, t0).transformPVCoordinates(pvITRF), 6.379e-5, 3.78e-7);

        Frame cirf = FramesFactory.getCIRF(IERSConventions.IERS_2010, true);
        PVCoordinates pvCIRF = new PVCoordinates(new Vector3D(5100018.4047, 6122786.3648, 6380344.5328),
                new Vector3D(-4745.380330, 790.341453, 5531.931288));
        checkPV(pvCIRF, tirf.getTransformTo(cirf, t0).transformPVCoordinates(pvTIRF), 8.59e-3, 4.65e-6);

    }

    @Test
    public void testAASReferenceGEO() throws OrekitException {

        // this reference test has been extracted from the following paper:
        // Implementation Issues Surrounding the New IAU Reference Systems for Astrodynamics
        // David A. Vallado, John H. Seago, P. Kenneth Seidelmann
        // http://www.centerforspace.com/downloads/files/pubs/AAS-06-134.pdf
        Utils.setLoaders(IERSConventions.IERS_2010, Utils.buildEOPList(IERSConventions.IERS_2010, new double[][] {
                { 53153, -0.4709050, 0.0000000, -0.083853, 0.467217, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53154, -0.4709050, 0.0000000, -0.083853, 0.467217, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53155, -0.4709050, 0.0000000, -0.083853, 0.467217, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53156, -0.4709050, 0.0000000, -0.083853, 0.467217, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53157, -0.4709050, 0.0000000, -0.083853, 0.467217, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53158, -0.4709050, 0.0000000, -0.083853, 0.467217, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53159, -0.4709050, 0.0000000, -0.083853, 0.467217, Double.NaN, Double.NaN, -0.000199, -0.000252 },
                { 53160, -0.4709050, 0.0000000, -0.083853, 0.467217, Double.NaN, Double.NaN, -0.000199,
                        -0.000252 } }));

        AbsoluteDate t0 = new AbsoluteDate(new DateComponents(2004, 06, 01), TimeComponents.H00,
                TimeScalesFactory.getUTC());

        //  Positions GEO
        Frame itrfA = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
        PVCoordinates pvITRF = new PVCoordinates(new Vector3D(24796919.2915, -34115870.9234, 10226.0621),
                new Vector3D(-0.979178, -1.476538, -0.928776));

        Frame tirf = FramesFactory.getTIRF(IERSConventions.IERS_2010);
        PVCoordinates pvTIRF = new PVCoordinates(new Vector3D(24796919.2953, -34115870.9004, 10293.2583),
                new Vector3D(-0.979178, -1.476540, -0.928772));
        checkPV(pvTIRF, itrfA.getTransformTo(tirf, t0).transformPVCoordinates(pvITRF), 5.697e-5, 4.69e-7);

        Frame cirf = FramesFactory.getCIRF(IERSConventions.IERS_2010, true);
        PVCoordinates pvCIRF = new PVCoordinates(new Vector3D(-40588158.1236, -11462167.0709, 10293.2583),
                new Vector3D(834.787843, -2958.305669, -0.928772));
        checkPV(pvCIRF, tirf.getTransformTo(cirf, t0).transformPVCoordinates(pvTIRF), 0.0505, 3.60e-6);

    }

    @Test
    public void testSerialization() throws OrekitException, IOException, ClassNotFoundException {
        TIRFProvider provider = new TIRFProvider(FramesFactory.getEOPHistory(IERSConventions.IERS_2010, true));

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(provider);

        Assert.assertTrue(bos.size() > 280000);
        Assert.assertTrue(bos.size() < 285000);

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        TIRFProvider deserialized = (TIRFProvider) ois.readObject();
        for (int i = 0; i < FastMath.min(100, provider.getEOPHistory().getEntries().size()); ++i) {
            AbsoluteDate date = provider.getEOPHistory().getEntries().get(i).getDate();
            Transform expectedIdentity = new Transform(date, provider.getTransform(date).getInverse(),
                    deserialized.getTransform(date));
            Assert.assertEquals(0.0, expectedIdentity.getTranslation().getNorm(), 1.0e-15);
            Assert.assertEquals(0.0, expectedIdentity.getRotation().getAngle(), 1.0e-15);
        }

    }

    /**
     * Checks that {@link TIRFProvider#getTransform(AbsoluteDate)} is thread safe.
     */
    @Test
    public void testConcurrentGetTransform() throws OrekitException, InterruptedException, ExecutionException {

        // subject under test
        final TIRFProvider tirf = new TIRFProvider(FramesFactory.getEOPHistory(IERSConventions.IERS_2010, false));
        // arbitrary date
        final AbsoluteDate start = new AbsoluteDate("2009-09-19T23:59:45.000", TimeScalesFactory.getUTC());
        // in seconds = 15min
        final double timeStep = 300;
        // the number of possible concurrent threads
        final int nJobs = 24;
        // the number of calculations per thread
        final int nPerJob = 1000;
        // tolerance of comparisons
        final double absTol = Precision.EPSILON;
        // the expected result
        final List<Transform> expecteds = new ArrayList<Transform>();
        for (int j = 0; j < nPerJob; j++) {
            final AbsoluteDate date = start.shiftedBy(timeStep * j);
            // action
            final Transform expected = tirf.getTransform(date);
            // verify
            expecteds.add(expected);
        }

        // build jobs for concurrent execution
        final List<Callable<Boolean>> jobs = new ArrayList<Callable<Boolean>>();
        for (int i = 0; i < nJobs; i++) {
            jobs.add(new Callable<Boolean>() {
                public Boolean call() throws Exception {
                    for (int j = 0; j < nPerJob; j++) {
                        final AbsoluteDate date = start.shiftedBy(timeStep * j);
                        // action
                        final Transform actual = tirf.getTransform(date);
                        // verify
                        assertTransformEquals(expecteds.get(j), actual, absTol);
                    }
                    return true;
                }
            });
        }

        // run the jobs
        runConcurrentlyAndCheck(jobs, nJobs);
    }

    /**
     * Runs several jobs at concurrently in the given number of threads.
     *
     * @param jobs
     *            the jobs to execute
     * @param threads
     *            the size of the thread pool
     */
    private static void runConcurrentlyAndCheck(List<Callable<Boolean>> jobs, int threads)
            throws InterruptedException, ExecutionException {

        // action
        final List<Future<Boolean>> futures = Executors.newFixedThreadPool(threads).invokeAll(jobs);

        // verify - necessary to throw AssertionErrors from the Callable
        for (Future<Boolean> future : futures) {
            Assert.assertEquals(true, future.get());
        }

    }

    /**
     * Check the two {@link Transform}s are the same to within an absolute tolerance.
     */
    private static void assertTransformEquals(Transform expected, Transform actual, double absTol) {
        final AngularCoordinates expectedAngular = expected.getAngular();
        final AngularCoordinates actualAngular = actual.getAngular();
        final Rotation expectedRotation = expectedAngular.getRotation();
        final Rotation actualRotation = actualAngular.getRotation();
        final PVCoordinates expectedPV = expected.getCartesian();
        final PVCoordinates actualPV = actual.getCartesian();

        // transform
        Assert.assertEquals(Rotation.distance(actualRotation, expectedRotation), 0, absTol);
        Assert.assertEquals(expectedAngular.getRotationRate(), actualAngular.getRotationRate());
        Assert.assertEquals(expectedPV.getPosition(), actualPV.getPosition());
        Assert.assertEquals(expectedPV.getVelocity(), actualPV.getVelocity());
    }

    @Before
    public void setUp() {
        Utils.setDataRoot("compressed-data");
    }

    private void checkPV(PVCoordinates reference, PVCoordinates result, double expectedPositionError,
            double expectedVelocityError) {

        Vector3D dP = result.getPosition().subtract(reference.getPosition());
        Vector3D dV = result.getVelocity().subtract(reference.getVelocity());
        Assert.assertEquals(expectedPositionError, dP.getNorm(), 0.01 * expectedPositionError);
        Assert.assertEquals(expectedVelocityError, dV.getNorm(), 0.01 * expectedVelocityError);
    }

}