From 225bb703318e62088c10967e6b2a2c31b3810d93 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe <luc@orekit.org> Date: Thu, 17 Jan 2019 17:19:55 +0100 Subject: [PATCH] Added a way to manage clock corrections from GPSPropagator. --- src/main/java/org/orekit/gnss/GPSAlmanac.java | 12 +- .../gnss/ClockCorrectionsProvider.java | 115 ++++++++++++++++++ .../analytical/gnss/GPSOrbitalElements.java | 82 +++++++++++++ src/site/xdoc/changes.xml | 15 ++- .../gnss/GPSOrbitalElementsTest.java | 60 +++++++++ .../analytical/gnss/GPSPropagatorTest.java | 23 ++++ 6 files changed, 296 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/orekit/propagation/analytical/gnss/ClockCorrectionsProvider.java create mode 100644 src/test/java/org/orekit/propagation/analytical/gnss/GPSOrbitalElementsTest.java diff --git a/src/main/java/org/orekit/gnss/GPSAlmanac.java b/src/main/java/org/orekit/gnss/GPSAlmanac.java index b9b17f799..601421121 100644 --- a/src/main/java/org/orekit/gnss/GPSAlmanac.java +++ b/src/main/java/org/orekit/gnss/GPSAlmanac.java @@ -232,20 +232,12 @@ public class GPSAlmanac implements GPSOrbitalElements { return 0; } - /** - * Gets the Zeroth Order Clock Correction. - * - * @return the Zeroth Order Clock Correction (s) - */ + @Override public double getAf0() { return af0; } - /** - * Gets the First Order Clock Correction. - * - * @return the First Order Clock Correction (s/s) - */ + @Override public double getAf1() { return af1; } diff --git a/src/main/java/org/orekit/propagation/analytical/gnss/ClockCorrectionsProvider.java b/src/main/java/org/orekit/propagation/analytical/gnss/ClockCorrectionsProvider.java new file mode 100644 index 000000000..f92325a3c --- /dev/null +++ b/src/main/java/org/orekit/propagation/analytical/gnss/ClockCorrectionsProvider.java @@ -0,0 +1,115 @@ +/* Copyright 2002-2019 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 org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.orekit.propagation.AdditionalStateProvider; +import org.orekit.propagation.SpacecraftState; +import org.orekit.time.AbsoluteDate; +import org.orekit.time.GPSDate; +import org.orekit.utils.Constants; +import org.orekit.utils.PVCoordinates; + +/** Provider for clock corrections as additional states. + * <p> + * The value of this additional state is a three elements array containing + * </p> + * <ul> + * <li>at index 0, the polynomial satellite clock model + * Δtₛₐₜ = {@link GPSOrbitalElements#getAf0() a₀} + + * {@link GPSOrbitalElements#getAf1() a₁} (t - {@link GPSOrbitalElements#getToc() toc}) + + * {@link GPSOrbitalElements#getAf1() a₂} (t - {@link GPSOrbitalElements#getToc() toc})² + * </li> + * <li>at index 1 the relativistic clock correction due to eccentricity</li> + * <li>at index 2 the estimated group delay differential {@link GPSOrbitalElements#getTGD() TGD} for L1-L2 correction</li> + * </ul> + * @author Luc Maisonobe + * @since 9.3 + */ +public class ClockCorrectionsProvider implements AdditionalStateProvider { + + /** Name of the additional state for satellite clock corrections. + * @since 9.3 + */ + public static final String CLOCK_CORRECTIONS = ""; + + /** Duration of the GPS cycle in seconds. */ + private static final double GPS_CYCLE_DURATION = GPSOrbitalElements.GPS_WEEK_IN_SECONDS * + GPSOrbitalElements.GPS_WEEK_NB; + /** The GPS orbital elements. */ + private final GPSOrbitalElements gpsOrbit; + + /** Clock reference epoch. */ + private final AbsoluteDate clockRef; + + /** Simple constructor. + * @param gpsOrbit GPS orbital elements + */ + public ClockCorrectionsProvider(final GPSOrbitalElements gpsOrbit) { + this.gpsOrbit = gpsOrbit; + this.clockRef = new GPSDate(gpsOrbit.getWeek(), gpsOrbit.getToc() * 1000.0).getDate(); + } + + /** {@inheritDoc} */ + @Override + public String getName() { + return CLOCK_CORRECTIONS; + } + + /** + * Get the duration from clock Reference epoch. + * <p>This takes the GPS week roll-over into account.</p> + * + * @param date the considered date + * @return the duration from clock Reference epoch (s) + */ + private double getDT(final AbsoluteDate date) { + // Time from ephemeris reference epoch + double dt = date.durationFrom(clockRef); + // Adjusts the time to take roll over week into account + while (dt > 0.5 * GPS_CYCLE_DURATION) { + dt -= GPS_CYCLE_DURATION; + } + while (dt < -0.5 * GPS_CYCLE_DURATION) { + dt += GPS_CYCLE_DURATION; + } + // Returns the time from ephemeris reference epoch + return dt; + } + + /** {@inheritDoc} */ + @Override + public double[] getAdditionalState(final SpacecraftState state) { + + // polynomial clock model + final double dt = getDT(state.getDate()); + final double dtSat = gpsOrbit.getAf0() + dt * (gpsOrbit.getAf1() + dt * gpsOrbit.getAf2()); + + // relativistic effect due to eccentricity + final PVCoordinates pv = state.getPVCoordinates(); + final double dtRel = -2 * Vector3D.dotProduct(pv.getPosition(), pv.getVelocity()) / + (Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT); + + // estimated group delay differential + final double tg = gpsOrbit.getTGD(); + + return new double[] { + dtSat, dtRel, tg + }; + } + +} diff --git a/src/main/java/org/orekit/propagation/analytical/gnss/GPSOrbitalElements.java b/src/main/java/org/orekit/propagation/analytical/gnss/GPSOrbitalElements.java index 65c5484f7..ff6e1807f 100644 --- a/src/main/java/org/orekit/propagation/analytical/gnss/GPSOrbitalElements.java +++ b/src/main/java/org/orekit/propagation/analytical/gnss/GPSOrbitalElements.java @@ -167,4 +167,86 @@ public interface GPSOrbitalElements extends TimeStamped { */ double getCis(); + /** + * Gets the Issue Of Data Clock (IODC). + * + * @return the Issue Of Data Clock (IODC) + * @since 9.3 + */ + default int getIODC() { + return 0; + } + + /** + * Gets the Issue Of Data Ephemeris (IODE). + * + * @return the Issue Of Data Ephemeris (IODE) + * @since 9.3 + */ + default int getIODE() { + return 0; + } + + /** + * Gets the Zeroth Order Clock Correction. + * + * @return the Zeroth Order Clock Correction (s) + * @see #getAf1() + * @see #getAf2() + * @see #getToc() + * @since 9.3 + */ + default double getAf0() { + return 0.0; + } + + /** + * Gets the First Order Clock Correction. + * + * @return the First Order Clock Correction (s/s) + * @see #getAf0() + * @see #getAf2() + * @see #getToc() + * @since 9.3 + */ + default double getAf1() { + return 0.0; + } + + /** + * Gets the Second Order Clock Correction. + * + * @return the Second Order Clock Correction (s/s²) + * @see #getAf0() + * @see #getAf1() + * @see #getToc() + * @since 9.3 + */ + default double getAf2() { + return 0.0; + } + + /** + * Gets the clock correction reference time toc. + * + * @return the clock correction reference time (s) + * @see #getAf0() + * @see #getAf1() + * @see #getAf2() + * @since 9.3 + */ + default double getToc() { + return 0.0; + } + + /** + * Gets the estimated group delay differential TGD for L1-L2 correction. + * + * @return the estimated group delay differential TGD for L1-L2 correction (s) + * @since 9.3 + */ + default double getTGD() { + return 0.0; + } + } diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml index 7f6c5d4ef..bc40741a9 100644 --- a/src/site/xdoc/changes.xml +++ b/src/site/xdoc/changes.xml @@ -20,7 +20,20 @@ <title>Orekit Changes</title> </properties> <body> - <release version="TBD" date="TBD" description="TBD"> + <release version="9.3" date="2019-01-21" description="Version 9.3 is a minor version of Orekit. + It includes both new features and bug fixes. New features introduced in 9.3 are: a new GPSDate class, + changed OrekitException from checked to unchecked exceptions, parameter drivers scales and reference + value can be changed, access to Kalman filter internal matrices, position-only measurements in orbit determination, + support for unofficial versions 2.12 and 2.20 of Rinex files (mainly for spaceborne receivers), + direct building of appropriate attitude law with eclipses for all GNSS satellite types, nter-satellites + view detector, measurement generation feature, possibility fo use Marshall Solar Activity Future Estimation + to feed NRL MSISE 2000 atmosphere model, new tropospheric models: Mendes-Pavlis, Vienna 1, Vienna 3, estimated model, + new mapping functions for tropospheric effect: Global Mapping Function, Niell Mapping Function, Global + Pression Temperature Models GPT and GPT2, possibility to estimate tropospheric zenith delay, + clock offset that can be estimated (both for ground station and satellite clocks)."> + <action dev="luc" type="add" issue="516"> + Added a way to manage clock corrections from GPSPropagator. + </action> <action dev="bryan" type="add" issue="498"> Added several tropospheric models: Mendes-Pavlis, Vienna 1, Vienna 3, estimated model where the total zenith delay can be estimated during Orbit Determination. diff --git a/src/test/java/org/orekit/propagation/analytical/gnss/GPSOrbitalElementsTest.java b/src/test/java/org/orekit/propagation/analytical/gnss/GPSOrbitalElementsTest.java new file mode 100644 index 000000000..cd76abfaf --- /dev/null +++ b/src/test/java/org/orekit/propagation/analytical/gnss/GPSOrbitalElementsTest.java @@ -0,0 +1,60 @@ +/* Copyright 2002-2019 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 org.hipparchus.util.Precision; +import org.junit.Assert; +import org.junit.Test; +import org.orekit.time.AbsoluteDate; + +public class GPSOrbitalElementsTest { + + @Test + public void testDefaultMethods() { + GPSOrbitalElements goe = new GPSOrbitalElements() { + public AbsoluteDate getDate() { return null; } + public int getWeek() { return 0; } + public double getTime() { return 0; } + public double getSma() { return 0; } + public double getPa() { return 0; } + public int getPRN() { return 0; } + public double getOmegaDot() { return 0; } + public double getOmega0() { return 0; } + public double getMeanMotion() { return 0; } + public double getM0() { return 0; } + public double getIDot() { return 0; } + public double getI0() { return 0; } + public double getE() { return 0; } + public double getCus() { return 0; } + public double getCuc() { return 0; } + public double getCrs() { return 0; } + public double getCrc() { return 0; } + public double getCis() { return 0; } + public double getCic() { return 0; } + }; + Assert.assertEquals(0, goe.getIODC()); + Assert.assertEquals(0, goe.getIODE()); + Assert.assertEquals(0.0, goe.getAf0(), Precision.SAFE_MIN); + Assert.assertEquals(0.0, goe.getAf1(), Precision.SAFE_MIN); + Assert.assertEquals(0.0, goe.getAf2(), Precision.SAFE_MIN); + Assert.assertEquals(0.0, goe.getToc(), Precision.SAFE_MIN); + Assert.assertEquals(0.0, goe.getTGD(), Precision.SAFE_MIN); + + } + +} diff --git a/src/test/java/org/orekit/propagation/analytical/gnss/GPSPropagatorTest.java b/src/test/java/org/orekit/propagation/analytical/gnss/GPSPropagatorTest.java index 626fe9af1..bfdf3db6c 100644 --- a/src/test/java/org/orekit/propagation/analytical/gnss/GPSPropagatorTest.java +++ b/src/test/java/org/orekit/propagation/analytical/gnss/GPSPropagatorTest.java @@ -23,6 +23,7 @@ import java.util.Map; import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.hipparchus.util.FastMath; +import org.hipparchus.util.Precision; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -31,6 +32,7 @@ import org.orekit.frames.Frame; import org.orekit.frames.FramesFactory; import org.orekit.gnss.GPSAlmanac; import org.orekit.gnss.SEMParser; +import org.orekit.propagation.SpacecraftState; import org.orekit.propagation.analytical.tle.TLE; import org.orekit.propagation.analytical.tle.TLEPropagator; import org.orekit.time.AbsoluteDate; @@ -57,6 +59,27 @@ public class GPSPropagatorTest { almanacs = reader.getAlmanacs(); } + @Test + public void testClockCorrections() { + final GPSPropagator propagator = new GPSPropagator.Builder(almanacs.get(0)).build(); + propagator.addAdditionalStateProvider(new ClockCorrectionsProvider(almanacs.get(0))); + // Propagate at the GPS date and one GPS cycle later + final AbsoluteDate date0 = almanacs.get(0).getDate(); + double dtRelMin = 0; + double dtRelMax = 0; + for (double dt = 0; dt < 0.5 * Constants.JULIAN_DAY; dt += 1.0) { + SpacecraftState state = propagator.propagate(date0.shiftedBy(dt)); + double[] corrections = state.getAdditionalState(ClockCorrectionsProvider.CLOCK_CORRECTIONS); + Assert.assertEquals(3, corrections.length); + Assert.assertEquals(1.33514404296875E-05, corrections[0], 1.0e-19); + dtRelMin = FastMath.min(dtRelMin, corrections[1]); + dtRelMax = FastMath.max(dtRelMax, corrections[1]); + Assert.assertEquals(0.0, corrections[2], Precision.SAFE_MIN); + } + Assert.assertEquals(-1.1679e-8, dtRelMin, 1.0e-12); + Assert.assertEquals(+1.1679e-8, dtRelMax, 1.0e-12); + } + @Test public void testGPSCycle() { // Builds the GPSPropagator from the almanac -- GitLab