Commit 6eeb8d8b authored by Luc Maisonobe's avatar Luc Maisonobe

Merge branch 'issue-534' into release-9.3

parents eb600144 b86ca507
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<groupId>org.orekit</groupId> <groupId>org.orekit</groupId>
<artifactId>orekit</artifactId> <artifactId>orekit</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>9.3</version> <version>9.3.1</version>
<name>ORbit Extrapolation KIT</name> <name>ORbit Extrapolation KIT</name>
<url>http://www.orekit.org/</url> <url>http://www.orekit.org/</url>
......
...@@ -590,7 +590,7 @@ public class EOPHistory implements Serializable { ...@@ -590,7 +590,7 @@ public class EOPHistory implements Serializable {
/** Get a non-modifiable view of the EOP entries. /** Get a non-modifiable view of the EOP entries.
* @return non-modifiable view of the EOP entries * @return non-modifiable view of the EOP entries
*/ */
List<EOPEntry> getEntries() { public List<EOPEntry> getEntries() {
return cache.getAll(); return cache.getAll();
} }
......
...@@ -17,9 +17,13 @@ ...@@ -17,9 +17,13 @@
package org.orekit.time; package org.orekit.time;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.hipparchus.util.FastMath; import org.hipparchus.util.FastMath;
import org.orekit.frames.EOPEntry;
import org.orekit.utils.Constants; import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
/** Container for date in GPS form. /** Container for date in GPS form.
* @author Luc Maisonobe * @author Luc Maisonobe
...@@ -31,12 +35,26 @@ public class GPSDate implements Serializable, TimeStamped { ...@@ -31,12 +35,26 @@ public class GPSDate implements Serializable, TimeStamped {
/** Serializable UID. */ /** Serializable UID. */
private static final long serialVersionUID = 20180633L; private static final long serialVersionUID = 20180633L;
/** Duration of a week in days. */
private static final int WEEK_D = 7;
/** Duration of a week in seconds. */ /** Duration of a week in seconds. */
private static final double WEEK = 7 * Constants.JULIAN_DAY; private static final double WEEK_S = WEEK_D * Constants.JULIAN_DAY;
/** Number of weeks in one rollover cycle. */
private static final int CYCLE_W = 1024;
/** Number of days in one rollover cycle. */
private static final int CYCLE_D = WEEK_D * CYCLE_W;
/** conversion factor from seconds to milliseconds. */ /** Conversion factor from seconds to milliseconds. */
private static final double S_TO_MS = 1000.0; private static final double S_TO_MS = 1000.0;
/** Reference date for ensuring continuity across GPS week rollover.
* @since 9.3.1
*/
private static AtomicReference<DateComponents> rolloverReference = new AtomicReference<DateComponents>(null);
/** Week number since {@link AbsoluteDate#GPS_EPOCH GPS epoch}. */ /** Week number since {@link AbsoluteDate#GPS_EPOCH GPS epoch}. */
private final int weekNumber; private final int weekNumber;
...@@ -47,22 +65,52 @@ public class GPSDate implements Serializable, TimeStamped { ...@@ -47,22 +65,52 @@ public class GPSDate implements Serializable, TimeStamped {
private final transient AbsoluteDate date; private final transient AbsoluteDate date;
/** Build an instance corresponding to a GPS date. /** Build an instance corresponding to a GPS date.
* <p>GPS dates are provided as a week number starting at * <p>
* {@link AbsoluteDate#GPS_EPOCH GPS epoch} and as a number of milliseconds * GPS dates are provided as a week number starting at {@link AbsoluteDate#GPS_EPOCH GPS epoch}
* since week start.</p> * and as a number of milliseconds since week start.
* @param weekNumber week number since {@link AbsoluteDate#GPS_EPOCH GPS epoch} * </p>
* <p>
* Many interfaces provide only the 10 lower bits of the GPS week number, just as it comes from
* the GPS signal. In other words they use a week number modulo 1024. In order to cope with
* this, when the week number is smaller than 1024, this constructor assumes a modulo operation
* has been performed and it will fix the week number according to the reference date set up for
* handling rollover (see {@link #setRolloverReference(DateComponents) setRolloverReference(reference)}).
* If the week number is 1024 or larger, it will be used without any correction.
* </p>
* @param weekNumber week number, either absolute or modulo 1024
* @param milliInWeek number of milliseconds since week start * @param milliInWeek number of milliseconds since week start
*/ */
public GPSDate(final int weekNumber, final double milliInWeek) { public GPSDate(final int weekNumber, final double milliInWeek) {
this.weekNumber = weekNumber;
this.milliInWeek = milliInWeek;
final int day = (int) FastMath.floor(milliInWeek / (Constants.JULIAN_DAY * S_TO_MS)); final int day = (int) FastMath.floor(milliInWeek / (Constants.JULIAN_DAY * S_TO_MS));
final double secondsInDay = milliInWeek / S_TO_MS - day * Constants.JULIAN_DAY; final double secondsInDay = milliInWeek / S_TO_MS - day * Constants.JULIAN_DAY;
date = new AbsoluteDate(new DateComponents(DateComponents.GPS_EPOCH, weekNumber * 7 + day),
new TimeComponents(secondsInDay), int w = weekNumber;
TimeScalesFactory.getGPS()); DateComponents dc = new DateComponents(DateComponents.GPS_EPOCH, weekNumber * 7 + day);
if (weekNumber < 1024) {
DateComponents reference = rolloverReference.get();
if (reference == null) {
// lazy setting of a default reference, using end of EOP entries
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true);
final List<EOPEntry> eop = ut1.getEOPHistory().getEntries();
final int lastMJD = eop.get(eop.size() - 1).getMjd();
reference = new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, lastMJD);
rolloverReference.compareAndSet(null, reference);
}
// fix GPS week rollover
while (dc.getJ2000Day() < reference.getJ2000Day() - CYCLE_D / 2) {
dc = new DateComponents(dc, CYCLE_D);
w += CYCLE_W;
}
}
this.weekNumber = w;
this.milliInWeek = milliInWeek;
date = new AbsoluteDate(dc, new TimeComponents(secondsInDay), TimeScalesFactory.getGPS());
} }
...@@ -71,14 +119,49 @@ public class GPSDate implements Serializable, TimeStamped { ...@@ -71,14 +119,49 @@ public class GPSDate implements Serializable, TimeStamped {
*/ */
public GPSDate(final AbsoluteDate date) { public GPSDate(final AbsoluteDate date) {
this.weekNumber = (int) FastMath.floor(date.durationFrom(AbsoluteDate.GPS_EPOCH) / WEEK); this.weekNumber = (int) FastMath.floor(date.durationFrom(AbsoluteDate.GPS_EPOCH) / WEEK_S);
final AbsoluteDate weekStart = new AbsoluteDate(AbsoluteDate.GPS_EPOCH, WEEK * weekNumber); final AbsoluteDate weekStart = new AbsoluteDate(AbsoluteDate.GPS_EPOCH, WEEK_S * weekNumber);
this.milliInWeek = date.durationFrom(weekStart) * S_TO_MS; this.milliInWeek = date.durationFrom(weekStart) * S_TO_MS;
this.date = date; this.date = date;
} }
/** Set a reference date for ensuring continuity across GPS week rollover.
* <p>
* Instance created using the {@link #GPSDate(int, double) GPSDate(weekNumber, milliInWeek)}
* constructor and with a week number between 0 and 1024 after this method has been called will
* fix the week number to ensure they correspond to dates between {@code reference - 512 weeks}
* and {@code reference + 512 weeks}.
* </p>
* <p>
* If this method is never called, a default reference date for rollover will be set using
* the date of the last known EOP entry retrieved from {@link UT1Scale#getEOPHistory() UT1}
* time scale.
* </p>
* @param reference reference date for GPS week rollover
* @see #getRolloverReference()
* @see #GPSDate(int, double)
* @since 9.3.1
*/
public static void setRolloverReference(final DateComponents reference) {
rolloverReference.set(reference);
}
/** Get the reference date ensuring continuity across GPS week rollover.
* @return reference reference date for GPS week rollover
* @see #setRolloverReference(AbsoluteDate)
* @see #GPSDate(int, double)
* @since 9.3.1
*/
public static DateComponents getRolloverReference() {
return rolloverReference.get();
}
/** Get the week number since {@link AbsoluteDate#GPS_EPOCH GPS epoch}. /** Get the week number since {@link AbsoluteDate#GPS_EPOCH GPS epoch}.
* <p>
* The week number returned here has been fixed for GPS week rollover, i.e.
* it may be larger than 1024.
* </p>
* @return week number since {@link AbsoluteDate#GPS_EPOCH GPS epoch} * @return week number since {@link AbsoluteDate#GPS_EPOCH GPS epoch}
*/ */
public int getWeekNumber() { public int getWeekNumber() {
......
...@@ -43,9 +43,14 @@ as required. ...@@ -43,9 +43,14 @@ as required.
| package | link | | package | link |
|----------|---------------------------------------------------------------------------------------------------------------------------------------| |----------|---------------------------------------------------------------------------------------------------------------------------------------|
| source | orekit-9.3-sources.zip (URL to be defined after official release) | | source | orekit-9.3.1-sources.zip (URL to be defined after official release) |
| binary | orekit-9.3.jar (URL to be defined after official release) | | binary | orekit-9.3.1.jar (URL to be defined after official release) |
| javadoc | orekit-9.3-javadoc.jar (URL to be defined after official release) | version 9.3.1 downloads (release date: 2019-03-16)
| package | link |
|----------|---------------------------------------------------------------------------------------------------------------------------------------|
| source | [orekit-9.3-sources.zip](https://gitlab.orekit.org/orekit/orekit/uploads/e313519415d0313043587739d417abcb/orekit-9.3-sources.zip) |
| binary | [orekit-9.3.jar](https://gitlab.orekit.org/orekit/orekit/uploads/32bc68ad2f4e58d1e8de71dbc4ff3494/orekit-9.3.jar) |
version 9.3 downloads (release date: 2019-01-25) version 9.3 downloads (release date: 2019-01-25)
| package | link | | package | link |
......
...@@ -20,6 +20,12 @@ ...@@ -20,6 +20,12 @@
<title>Orekit Changes</title> <title>Orekit Changes</title>
</properties> </properties>
<body> <body>
<release version="9.3.1" date="2019-03-16" description="Version 9.3.1 is a minor version of Orekit.
It fixes an issue with GPS week rollover.">
<action dev="luc" type="add" issue="534">
Handle GPS week rollover in GPSDate.
</action>
</release>
<release version="9.3" date="2019-01-25" description="Version 9.3 is a minor version of Orekit. <release version="9.3" date="2019-01-25" 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, 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 changed OrekitException from checked to unchecked exceptions, parameter drivers scales and reference
......
...@@ -42,6 +42,7 @@ import org.orekit.propagation.semianalytical.dsst.utilities.JacobiPolynomials; ...@@ -42,6 +42,7 @@ import org.orekit.propagation.semianalytical.dsst.utilities.JacobiPolynomials;
import org.orekit.propagation.semianalytical.dsst.utilities.NewcombOperators; import org.orekit.propagation.semianalytical.dsst.utilities.NewcombOperators;
import org.orekit.time.AbsoluteDate; import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents; import org.orekit.time.DateComponents;
import org.orekit.time.GPSDate;
import org.orekit.time.TimeScale; import org.orekit.time.TimeScale;
import org.orekit.time.TimeScalesFactory; import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants; import org.orekit.utils.Constants;
...@@ -85,6 +86,7 @@ public class Utils { ...@@ -85,6 +86,7 @@ public class Utils {
FramesFactory.clearEOPHistoryLoaders(); FramesFactory.clearEOPHistoryLoaders();
FramesFactory.setEOPContinuityThreshold(5 * Constants.JULIAN_DAY); FramesFactory.setEOPContinuityThreshold(5 * Constants.JULIAN_DAY);
TimeScalesFactory.clearUTCTAIOffsetsLoaders(); TimeScalesFactory.clearUTCTAIOffsetsLoaders();
GPSDate.setRolloverReference(null);
GravityFieldFactory.clearPotentialCoefficientsReaders(); GravityFieldFactory.clearPotentialCoefficientsReaders();
GravityFieldFactory.clearOceanTidesReaders(); GravityFieldFactory.clearOceanTidesReaders();
DataProvidersManager.getInstance().clearProviders(); DataProvidersManager.getInstance().clearProviders();
......
...@@ -36,6 +36,7 @@ import org.orekit.propagation.SpacecraftState; ...@@ -36,6 +36,7 @@ import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.tle.TLE; import org.orekit.propagation.analytical.tle.TLE;
import org.orekit.propagation.analytical.tle.TLEPropagator; import org.orekit.propagation.analytical.tle.TLEPropagator;
import org.orekit.time.AbsoluteDate; import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.GPSDate; import org.orekit.time.GPSDate;
import org.orekit.time.TimeScalesFactory; import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.CartesianDerivativesFilter; import org.orekit.utils.CartesianDerivativesFilter;
...@@ -51,6 +52,7 @@ public class GPSPropagatorTest { ...@@ -51,6 +52,7 @@ public class GPSPropagatorTest {
@BeforeClass @BeforeClass
public static void setUpBeforeClass() { public static void setUpBeforeClass() {
Utils.setDataRoot("gnss"); Utils.setDataRoot("gnss");
GPSDate.setRolloverReference(new DateComponents(DateComponents.GPS_EPOCH, 7 * 512));
// Get the parser to read a SEM file // Get the parser to read a SEM file
SEMParser reader = new SEMParser(null); SEMParser reader = new SEMParser(null);
// Reads the SEM file // Reads the SEM file
......
...@@ -38,6 +38,7 @@ public class GPSDateTest { ...@@ -38,6 +38,7 @@ public class GPSDateTest {
Assert.assertEquals(1387, date.getWeekNumber()); Assert.assertEquals(1387, date.getWeekNumber());
Assert.assertEquals(318677000.0, date.getMilliInWeek(), 1.0e-15); Assert.assertEquals(318677000.0, date.getMilliInWeek(), 1.0e-15);
Assert.assertEquals(0, date.getDate().durationFrom(ref), 1.0e-15); Assert.assertEquals(0, date.getDate().durationFrom(ref), 1.0e-15);
Assert.assertNull(GPSDate.getRolloverReference());
} }
@Test @Test
...@@ -56,6 +57,34 @@ public class GPSDateTest { ...@@ -56,6 +57,34 @@ public class GPSDateTest {
Assert.assertEquals(0.0, date.getMilliInWeek(), 1.0e-15); Assert.assertEquals(0.0, date.getMilliInWeek(), 1.0e-15);
} }
@Test
public void testZeroZero() {
GPSDate.setRolloverReference(new DateComponents(DateComponents.GPS_EPOCH, 7 * 512));
GPSDate date1 = new GPSDate(0, 0.0);
Assert.assertEquals(0.0, date1.getDate().durationFrom(AbsoluteDate.GPS_EPOCH), 1.0e-15);
GPSDate.setRolloverReference(new DateComponents(GPSDate.getRolloverReference(), 1));
GPSDate date2 = new GPSDate(0, 0.0);
Assert.assertEquals(1024, date2.getWeekNumber());
}
@Test
public void testDefaultRolloverReference() {
Assert.assertNull(GPSDate.getRolloverReference());
GPSDate date = new GPSDate(305, 1.5);
// the default reference is extracted from last EOP entry
// which in this test comes from bulletin B 218, in the final values section
Assert.assertEquals("2006-03-05", GPSDate.getRolloverReference().toString());
Assert.assertEquals(305 + 1024, date.getWeekNumber());
}
@Test
public void testUserRolloverReference() {
GPSDate.setRolloverReference(new DateComponents(DateComponents.GPS_EPOCH, 7 * (3 * 1024 + 512)));
GPSDate date = new GPSDate(305, 1.5);
Assert.assertEquals("2048-09-13", GPSDate.getRolloverReference().toString());
Assert.assertEquals(305 + 3 * 1024, date.getWeekNumber());
}
@Test @Test
public void testSerialization() throws IOException, ClassNotFoundException { public void testSerialization() throws IOException, ClassNotFoundException {
GPSDate date = new GPSDate(1387, 318677000.0); GPSDate date = new GPSDate(1387, 318677000.0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment