/* Copyright 2002-2017 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.propagation.analytical.tle; import org.hipparchus.geometry.euclidean.threed.Line; import org.hipparchus.geometry.euclidean.threed.Rotation; import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.hipparchus.util.FastMath; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.orekit.Utils; import org.orekit.attitudes.BodyCenterPointing; import org.orekit.bodies.OneAxisEllipsoid; import org.orekit.errors.OrekitException; import org.orekit.frames.Frame; import org.orekit.frames.FramesFactory; import org.orekit.frames.Transform; import org.orekit.propagation.BoundedPropagator; import org.orekit.propagation.Propagator; import org.orekit.propagation.SpacecraftState; import org.orekit.propagation.sampling.OrekitFixedStepHandler; import org.orekit.time.AbsoluteDate; import org.orekit.utils.Constants; import org.orekit.utils.IERSConventions; import org.orekit.utils.PVCoordinates; public class TLEPropagatorTest { private TLE tle; private double period; @Test public void testSlaveMode() throws OrekitException { TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle); AbsoluteDate initDate = tle.getDate(); SpacecraftState initialState = propagator.getInitialState(); // Simulate a full period of a GPS satellite // ----------------------------------------- SpacecraftState finalState = propagator.propagate(initDate.shiftedBy(period)); // Check results Assert.assertEquals(initialState.getA(), finalState.getA(), 1e-1); Assert.assertEquals(initialState.getEquinoctialEx(), finalState.getEquinoctialEx(), 1e-1); Assert.assertEquals(initialState.getEquinoctialEy(), finalState.getEquinoctialEy(), 1e-1); Assert.assertEquals(initialState.getHx(), finalState.getHx(), 1e-3); Assert.assertEquals(initialState.getHy(), finalState.getHy(), 1e-3); Assert.assertEquals(initialState.getLM(), finalState.getLM(), 1e-3); } @Test public void testEphemerisMode() throws OrekitException { TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle); propagator.setEphemerisMode(); AbsoluteDate initDate = tle.getDate(); SpacecraftState initialState = propagator.getInitialState(); // Simulate a full period of a GPS satellite // ----------------------------------------- AbsoluteDate endDate = initDate.shiftedBy(period); propagator.propagate(endDate); // get the ephemeris BoundedPropagator boundedProp = propagator.getGeneratedEphemeris(); // get the initial state from the ephemeris and check if it is the same as // the initial state from the TLE SpacecraftState boundedState = boundedProp.propagate(initDate); // Check results Assert.assertEquals(initialState.getA(), boundedState.getA(), 0.); Assert.assertEquals(initialState.getEquinoctialEx(), boundedState.getEquinoctialEx(), 0.); Assert.assertEquals(initialState.getEquinoctialEy(), boundedState.getEquinoctialEy(), 0.); Assert.assertEquals(initialState.getHx(), boundedState.getHx(), 0.); Assert.assertEquals(initialState.getHy(), boundedState.getHy(), 0.); Assert.assertEquals(initialState.getLM(), boundedState.getLM(), 1e-14); SpacecraftState finalState = boundedProp.propagate(endDate); // Check results Assert.assertEquals(initialState.getA(), finalState.getA(), 1e-1); Assert.assertEquals(initialState.getEquinoctialEx(), finalState.getEquinoctialEx(), 1e-1); Assert.assertEquals(initialState.getEquinoctialEy(), finalState.getEquinoctialEy(), 1e-1); Assert.assertEquals(initialState.getHx(), finalState.getHx(), 1e-3); Assert.assertEquals(initialState.getHy(), finalState.getHy(), 1e-3); Assert.assertEquals(initialState.getLM(), finalState.getLM(), 1e-3); } /** Test if body center belongs to the direction pointed by the satellite */ @Test public void testBodyCenterInPointingDirection() throws OrekitException { final Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true); final OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, Constants.WGS84_EARTH_FLATTENING, itrf); DistanceChecker checker = new DistanceChecker(itrf); // with Earth pointing attitude, distance should be small TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle, new BodyCenterPointing(FramesFactory.getTEME(), earth), Propagator.DEFAULT_MASS); propagator.setMasterMode(900.0, checker); propagator.propagate(tle.getDate().shiftedBy(period)); Assert.assertEquals(0.0, checker.getMaxDistance(), 2.0e-7); // with default attitude mode, distance should be large propagator = TLEPropagator.selectExtrapolator(tle); propagator.setMasterMode(900.0, checker); propagator.propagate(tle.getDate().shiftedBy(period)); Assert.assertEquals(1.5219e7, checker.getMinDistance(), 1000.0); Assert.assertEquals(2.6572e7, checker.getMaxDistance(), 1000.0); } private static class DistanceChecker implements OrekitFixedStepHandler { private final Frame itrf; private double minDistance; private double maxDistance; public DistanceChecker(Frame itrf) { this.itrf = itrf; } public double getMinDistance() { return minDistance; } public double getMaxDistance() { return maxDistance; } public void init(SpacecraftState s0, AbsoluteDate t, double step) { minDistance = Double.POSITIVE_INFINITY; maxDistance = Double.NEGATIVE_INFINITY; } public void handleStep(SpacecraftState currentState, boolean isLast) throws OrekitException { // Get satellite attitude rotation, i.e rotation from inertial frame to satellite frame Rotation rotSat = currentState.getAttitude().getRotation(); // Transform Z axis from satellite frame to inertial frame Vector3D zSat = rotSat.applyInverseTo(Vector3D.PLUS_K); // Transform Z axis from inertial frame to ITRF Transform transform = currentState.getFrame().getTransformTo(itrf, currentState.getDate()); Vector3D zSatITRF = transform.transformVector(zSat); // Transform satellite position/velocity from inertial frame to ITRF PVCoordinates pvSatITRF = transform.transformPVCoordinates(currentState.getPVCoordinates()); // Line containing satellite point and following pointing direction Line pointingLine = new Line(pvSatITRF.getPosition(), pvSatITRF.getPosition().add(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, zSatITRF), 1.0e-10); double distance = pointingLine.distance(Vector3D.ZERO); minDistance = FastMath.min(minDistance, distance); maxDistance = FastMath.max(maxDistance, distance); } } @Before public void setUp() throws OrekitException { Utils.setDataRoot("regular-data"); // setup a TLE for a GPS satellite String line1 = "1 37753U 11036A 12090.13205652 -.00000006 00000-0 00000+0 0 2272"; String line2 = "2 37753 55.0032 176.5796 0004733 13.2285 346.8266 2.00565440 5153"; tle = new TLE(line1, line2); // the period of the GPS satellite period = 717.97 * 60.0; } }