/* 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.gnss;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.errors.OrekitException;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.gnss.GPSAlmanac;
import org.orekit.gnss.SEMParser;
import org.orekit.propagation.analytical.tle.TLE;
import org.orekit.propagation.analytical.tle.TLEPropagator;
import org.orekit.propagation.analytical.tle.TLESeries;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.CartesianDerivativesFilter;
import org.orekit.utils.Constants;
import org.orekit.utils.PVCoordinates;
import org.orekit.utils.TimeStampedPVCoordinates;
public class GPSPropagatorTest {
private static List<GPSAlmanac> almanacs;
@BeforeClass
public static void setUpBeforeClass() throws OrekitException {
Utils.setDataRoot("gnss");
// Get the parser to read a SEM file
SEMParser reader = new SEMParser(null);
// Reads the SEM file
reader.loadData();
// Gets the first SEM almanac
almanacs = reader.getAlmanacs();
}
@Test
public void testGPSCycle() throws OrekitException {
// Builds the GPSPropagator from the almanac
final GPSPropagator propagator = new GPSPropagator.Builder(almanacs.get(0)).build();
// Propagate at the GPS date and one GPS cycle later
final AbsoluteDate date0 = almanacs.get(0).getDate();
final Vector3D p0 = propagator.propagateInEcef(date0).getPosition();
final double gpsCycleDuration = GPSOrbitalElements.GPS_WEEK_IN_SECONDS * GPSOrbitalElements.GPS_WEEK_NB;
final AbsoluteDate date1 = date0.shiftedBy(gpsCycleDuration);
final Vector3D p1 = propagator.propagateInEcef(date1).getPosition();
// Checks
Assert.assertEquals(0., p0.distance(p1), 0.);
}
@Test
public void testFrames() throws OrekitException {
// Builds the GPSPropagator from the almanac
final GPSPropagator propagator = new GPSPropagator.Builder(almanacs.get(0)).build();
// Defines some date
final AbsoluteDate date = new AbsoluteDate(2016, 3, 3, 12, 0, 0., TimeScalesFactory.getUTC());
// Get PVCoordinates at the date in the ECEF
final PVCoordinates pv0 = propagator.propagateInEcef(date);
// Get PVCoordinates at the date in the ECEF
final PVCoordinates pv1 = propagator.getPVCoordinates(date, propagator.getECEF());
// Checks
Assert.assertEquals(0., pv0.getPosition().distance(pv1.getPosition()), 3.3e-8);
Assert.assertEquals(0., pv0.getVelocity().distance(pv1.getVelocity()), 3.9e-12);
}
@Test
public void testTLE() throws OrekitException {
List<GPSPropagator> gpsPropagators = new ArrayList<GPSPropagator>();
for (final GPSAlmanac almanac : almanacs) {
gpsPropagators.add(new GPSPropagator.Builder(almanac).build());
}
// the following map corresponds to the constellation status
// in early 2016, compliant with the gps-week-862.txt TLE file
final Map<Integer, Integer> prnToSatNumber = new HashMap<Integer, Integer>();
prnToSatNumber.put( 1, 37753);
prnToSatNumber.put( 2, 28474);
prnToSatNumber.put( 3, 40294);
prnToSatNumber.put( 4, 34661);
prnToSatNumber.put( 5, 35752);
prnToSatNumber.put( 6, 39741);
prnToSatNumber.put( 7, 32711);
prnToSatNumber.put( 8, 40730);
prnToSatNumber.put( 9, 40105);
prnToSatNumber.put(10, 41019);
prnToSatNumber.put(11, 25933);
prnToSatNumber.put(12, 29601);
prnToSatNumber.put(13, 24876);
prnToSatNumber.put(14, 26605);
prnToSatNumber.put(15, 32260);
prnToSatNumber.put(16, 27663);
prnToSatNumber.put(17, 28874);
prnToSatNumber.put(18, 26690);
prnToSatNumber.put(19, 28190);
prnToSatNumber.put(20, 26360);
prnToSatNumber.put(21, 27704);
prnToSatNumber.put(22, 28129);
prnToSatNumber.put(23, 28361);
prnToSatNumber.put(24, 38833);
prnToSatNumber.put(25, 36585);
prnToSatNumber.put(26, 40534);
prnToSatNumber.put(27, 39166);
prnToSatNumber.put(28, 26407);
prnToSatNumber.put(29, 32384);
prnToSatNumber.put(30, 39533);
prnToSatNumber.put(31, 29486);
prnToSatNumber.put(32, 41328);
TLESeries series = new TLESeries("^gps-week-862\\.txt$", true);
for (final GPSPropagator gpsPropagator : gpsPropagators) {
final int prn = gpsPropagator.getGPSOrbitalElements().getPRN();
final int satNumber = prnToSatNumber.get(prn);
series.loadTLEData(satNumber);
TLE tle = series.getFirst();
TLEPropagator tlePropagator = TLEPropagator.selectExtrapolator(tle);
for (double dt = 0; dt < Constants.JULIAN_DAY; dt += 600) {
final AbsoluteDate date = tlePropagator.getInitialState().getDate().shiftedBy(dt);
final PVCoordinates gpsPV = gpsPropagator.getPVCoordinates(date, gpsPropagator.getECI());
final PVCoordinates tlePV = tlePropagator.getPVCoordinates(date, gpsPropagator.getECI());
Assert.assertEquals(0.0,
Vector3D.distance(gpsPV.getPosition(), tlePV.getPosition()),
8400.0);
}
}
}
@Test
public void testDerivativesConsistency() throws OrekitException {
final Frame eme2000 = FramesFactory.getEME2000();
double errorP = 0;
double errorV = 0;
double errorA = 0;
for (final GPSAlmanac almanac : almanacs) {
GPSPropagator propagator = new GPSPropagator.Builder(almanac).build();
GPSOrbitalElements elements = propagator.getGPSOrbitalElements();
AbsoluteDate t0 = AbsoluteDate.createGPSDate(elements.getWeek(),
0.001 * elements.getTime());
for (double dt = 0; dt < Constants.JULIAN_DAY; dt += 600) {
final AbsoluteDate central = t0.shiftedBy(dt);
final PVCoordinates pv = propagator.getPVCoordinates(central, eme2000);
final double h = 10.0;
List<TimeStampedPVCoordinates> sample = new ArrayList<TimeStampedPVCoordinates>();
for (int i = -3; i <= 3; ++i) {
sample.add(propagator.getPVCoordinates(central.shiftedBy(i * h), eme2000));
}
final PVCoordinates interpolated =
TimeStampedPVCoordinates.interpolate(central,
CartesianDerivativesFilter.USE_P,
sample);
errorP = FastMath.max(errorP, Vector3D.distance(pv.getPosition(), interpolated.getPosition()));
errorV = FastMath.max(errorV, Vector3D.distance(pv.getVelocity(), interpolated.getVelocity()));
errorA = FastMath.max(errorA, Vector3D.distance(pv.getAcceleration(), interpolated.getAcceleration()));
}
}
Assert.assertEquals(0.0, errorP, 3.8e-9);
Assert.assertEquals(0.0, errorV, 3.5e-8);
Assert.assertEquals(0.0, errorA, 1.1e-8);
}
}