Skip to content

Commit

Permalink
Merge branch 'issue-534' into release-9.3
Browse files Browse the repository at this point in the history
  • Loading branch information
maisonobe committed Mar 16, 2019
2 parents eb60014 + b86ca50 commit 6eeb8d8
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 19 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<groupId>org.orekit</groupId>
<artifactId>orekit</artifactId>
<packaging>jar</packaging>
<version>9.3</version>
<version>9.3.1</version>
<name>ORbit Extrapolation KIT</name>
<url>http://www.orekit.org/</url>

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/orekit/frames/EOPHistory.java
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ protected boolean hasDataFor(final AbsoluteDate date) {
/** Get a 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();
}

Expand Down
111 changes: 97 additions & 14 deletions src/main/java/org/orekit/time/GPSDate.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@
package org.orekit.time;

import java.io.Serializable;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import org.hipparchus.util.FastMath;
import org.orekit.frames.EOPEntry;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;

/** Container for date in GPS form.
* @author Luc Maisonobe
Expand All @@ -31,12 +35,26 @@ public class GPSDate implements Serializable, TimeStamped {
/** Serializable UID. */
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. */
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;

/** 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}. */
private final int weekNumber;

Expand All @@ -47,22 +65,52 @@ public class GPSDate implements Serializable, TimeStamped {
private final transient AbsoluteDate date;

/** Build an instance corresponding to a GPS date.
* <p>GPS dates are provided as a week number starting at
* {@link AbsoluteDate#GPS_EPOCH GPS epoch} and as a number of milliseconds
* since week start.</p>
* @param weekNumber week number since {@link AbsoluteDate#GPS_EPOCH GPS epoch}
* <p>
* GPS dates are provided as a week number starting at {@link AbsoluteDate#GPS_EPOCH GPS epoch}
* and as a number of milliseconds since week start.
* </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
*/
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 double secondsInDay = milliInWeek / S_TO_MS - day * Constants.JULIAN_DAY;
date = new AbsoluteDate(new DateComponents(DateComponents.GPS_EPOCH, weekNumber * 7 + day),
new TimeComponents(secondsInDay),
TimeScalesFactory.getGPS());

int w = weekNumber;
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());

}

Expand All @@ -71,14 +119,49 @@ public GPSDate(final int weekNumber, final double milliInWeek) {
*/
public GPSDate(final AbsoluteDate date) {

this.weekNumber = (int) FastMath.floor(date.durationFrom(AbsoluteDate.GPS_EPOCH) / WEEK);
final AbsoluteDate weekStart = new AbsoluteDate(AbsoluteDate.GPS_EPOCH, WEEK * weekNumber);
this.weekNumber = (int) FastMath.floor(date.durationFrom(AbsoluteDate.GPS_EPOCH) / WEEK_S);
final AbsoluteDate weekStart = new AbsoluteDate(AbsoluteDate.GPS_EPOCH, WEEK_S * weekNumber);
this.milliInWeek = date.durationFrom(weekStart) * S_TO_MS;
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}.
* <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}
*/
public int getWeekNumber() {
Expand Down
11 changes: 8 additions & 3 deletions src/site/markdown/downloads.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,14 @@ as required.

| package | link |
|----------|---------------------------------------------------------------------------------------------------------------------------------------|
| source | orekit-9.3-sources.zip (URL to be defined after official release) |
| binary | orekit-9.3.jar (URL to be defined after official release) |
| javadoc | orekit-9.3-javadoc.jar (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.1.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)

| package | link |
Expand Down
6 changes: 6 additions & 0 deletions src/site/xdoc/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
<title>Orekit Changes</title>
</properties>
<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.
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
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/org/orekit/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.orekit.propagation.semianalytical.dsst.utilities.NewcombOperators;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.GPSDate;
import org.orekit.time.TimeScale;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
Expand Down Expand Up @@ -85,6 +86,7 @@ public static void clearFactories() {
FramesFactory.clearEOPHistoryLoaders();
FramesFactory.setEOPContinuityThreshold(5 * Constants.JULIAN_DAY);
TimeScalesFactory.clearUTCTAIOffsetsLoaders();
GPSDate.setRolloverReference(null);
GravityFieldFactory.clearPotentialCoefficientsReaders();
GravityFieldFactory.clearOceanTidesReaders();
DataProvidersManager.getInstance().clearProviders();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.orekit.propagation.analytical.tle.TLE;
import org.orekit.propagation.analytical.tle.TLEPropagator;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.GPSDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.CartesianDerivativesFilter;
Expand All @@ -51,6 +52,7 @@ public class GPSPropagatorTest {
@BeforeClass
public static void setUpBeforeClass() {
Utils.setDataRoot("gnss");
GPSDate.setRolloverReference(new DateComponents(DateComponents.GPS_EPOCH, 7 * 512));
// Get the parser to read a SEM file
SEMParser reader = new SEMParser(null);
// Reads the SEM file
Expand Down
29 changes: 29 additions & 0 deletions src/test/java/org/orekit/time/GPSDateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public void testFromWeekAndMilli() {
Assert.assertEquals(1387, date.getWeekNumber());
Assert.assertEquals(318677000.0, date.getMilliInWeek(), 1.0e-15);
Assert.assertEquals(0, date.getDate().durationFrom(ref), 1.0e-15);
Assert.assertNull(GPSDate.getRolloverReference());
}

@Test
Expand All @@ -56,6 +57,34 @@ public void testZero() {
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
public void testSerialization() throws IOException, ClassNotFoundException {
GPSDate date = new GPSDate(1387, 318677000.0);
Expand Down

0 comments on commit 6eeb8d8

Please sign in to comment.