diff --git a/core/src/main/java/org/orekit/rugged/api/Rugged.java b/core/src/main/java/org/orekit/rugged/api/Rugged.java index 89312672c2fb1f705d9f781d0db8c9d68e69d5c3..bd3b4d9256fb1dc20861de6b7978a54f325808a9 100644 --- a/core/src/main/java/org/orekit/rugged/api/Rugged.java +++ b/core/src/main/java/org/orekit/rugged/api/Rugged.java @@ -108,6 +108,7 @@ public class Rugged { * @param bodyRotatingFrameID identifier of body rotating frame * @param minDate start of search time span * @param maxDate end of search time span + * @param overshootTolerance tolerance in seconds allowed for {@code minDate} and {@code maxDate} overshooting * @param positionsVelocities satellite position and velocity * @param pvInterpolationOrder order to use for position/velocity interpolation * @param quaternions satellite quaternions @@ -118,13 +119,13 @@ public class Rugged { public Rugged(final TileUpdater updater, final int maxCachedTiles, final AlgorithmId algorithmID, final EllipsoidId ellipsoidID, final InertialFrameId inertialFrameID, final BodyRotatingFrameId bodyRotatingFrameID, - final AbsoluteDate minDate, final AbsoluteDate maxDate, + final AbsoluteDate minDate, final AbsoluteDate maxDate, final double overshootTolerance, final List<TimeStampedPVCoordinates> positionsVelocities, final int pvInterpolationOrder, final List<TimeStampedAngularCoordinates> quaternions, final int aInterpolationOrder) throws RuggedException { this(updater, maxCachedTiles, algorithmID, selectEllipsoid(ellipsoidID, selectBodyRotatingFrame(bodyRotatingFrameID)), - selectInertialFrame(inertialFrameID), minDate, maxDate, + selectInertialFrame(inertialFrameID), minDate, maxDate, overshootTolerance, positionsVelocities, pvInterpolationOrder, quaternions, aInterpolationOrder); } @@ -144,6 +145,7 @@ public class Rugged { * @param inertialFrame inertial frame * @param minDate start of search time span * @param maxDate end of search time span + * @param overshootTolerance tolerance in seconds allowed for {@code minDate} and {@code maxDate} overshooting * @param positionsVelocities satellite position and velocity * @param pvInterpolationOrder order to use for position/velocity interpolation * @param quaternions satellite quaternions @@ -153,7 +155,7 @@ public class Rugged { */ public Rugged(final TileUpdater updater, final int maxCachedTiles, final AlgorithmId algorithmID, final OneAxisEllipsoid ellipsoid, final Frame inertialFrame, - final AbsoluteDate minDate, final AbsoluteDate maxDate, + final AbsoluteDate minDate, final AbsoluteDate maxDate, final double overshootTolerance, final List<TimeStampedPVCoordinates> positionsVelocities, final int pvInterpolationOrder, final List<TimeStampedAngularCoordinates> quaternions, final int aInterpolationOrder) throws RuggedException { @@ -163,7 +165,7 @@ public class Rugged { // orbit/attitude to body converter this.scToBody = new SpacecraftToObservedBody(inertialFrame, ellipsoid.getBodyFrame(), - minDate, maxDate, + minDate, maxDate, overshootTolerance, positionsVelocities, pvInterpolationOrder, quaternions, aInterpolationOrder, FRAMES_TRANSFORMS_INTERPOLATION_STEP); @@ -196,6 +198,7 @@ public class Rugged { * @param bodyRotatingFrameID identifier of body rotating frame * @param minDate start of search time span * @param maxDate end of search time span + * @param overshootTolerance tolerance in seconds allowed for {@code minDate} and {@code maxDate} overshooting * @param interpolationStep step to use for inertial/Earth/spacraft transforms interpolations * @param interpolationOrder order to use for inertial/Earth/spacraft transforms interpolations * @param propagator global propagator @@ -204,12 +207,12 @@ public class Rugged { public Rugged(final TileUpdater updater, final int maxCachedTiles, final AlgorithmId algorithmID, final EllipsoidId ellipsoidID, final InertialFrameId inertialFrameID, final BodyRotatingFrameId bodyRotatingFrameID, - final AbsoluteDate minDate, final AbsoluteDate maxDate, + final AbsoluteDate minDate, final AbsoluteDate maxDate, final double overshootTolerance, final double interpolationStep, final int interpolationOrder, final Propagator propagator) throws RuggedException { this(updater, maxCachedTiles, algorithmID, selectEllipsoid(ellipsoidID, selectBodyRotatingFrame(bodyRotatingFrameID)), - selectInertialFrame(inertialFrameID), minDate, maxDate, + selectInertialFrame(inertialFrameID), minDate, maxDate, overshootTolerance, interpolationStep, interpolationOrder, propagator); } @@ -229,6 +232,7 @@ public class Rugged { * @param inertialFrame inertial frame * @param minDate start of search time span * @param maxDate end of search time span + * @param overshootTolerance tolerance in seconds allowed for {@code minDate} and {@code maxDate} overshooting * @param interpolationStep step to use for inertial/Earth/spacraft transforms interpolations * @param interpolationOrder order to use for inertial/Earth/spacraft transforms interpolations * @param propagator global propagator @@ -236,7 +240,7 @@ public class Rugged { */ public Rugged(final TileUpdater updater, final int maxCachedTiles, final AlgorithmId algorithmID, final OneAxisEllipsoid ellipsoid, final Frame inertialFrame, - final AbsoluteDate minDate, final AbsoluteDate maxDate, + final AbsoluteDate minDate, final AbsoluteDate maxDate, final double overshootTolerance, final double interpolationStep, final int interpolationOrder, final Propagator propagator) throws RuggedException { try { @@ -276,7 +280,7 @@ public class Rugged { // orbit/attitude to body converter this.scToBody = new SpacecraftToObservedBody(inertialFrame, ellipsoid.getBodyFrame(), - minDate, maxDate, + minDate, maxDate, overshootTolerance, positionsVelocities, interpolationOrder, quaternions, interpolationOrder, FRAMES_TRANSFORMS_INTERPOLATION_STEP); diff --git a/core/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java b/core/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java index bad7398da486fd09b4763b35fd783835ccb46bd5..8fe52aaf90cbdb5bce62e63722431518149a3251 100644 --- a/core/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java +++ b/core/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java @@ -61,16 +61,19 @@ public class SpacecraftToObservedBody { * @param bodyFrame observed body frame * @param minDate start of search time span * @param maxDate end of search time span + * @param overshootTolerance tolerance in seconds allowed for {@code minDate} and {@code maxDate} overshooting + * slightly the position, velocity and quaternions ephemerides * @param positionsVelocities satellite position and velocity * @param pvInterpolationOrder order to use for position/velocity interpolation * @param quaternions satellite quaternions * @param aInterpolationOrder order to use for attitude interpolation * @param tStep step to use for inertial frame to body frame transforms cache computations - * @exception RuggedException if position or attitude samples do not fully cover the - * [{@code minDate}, {@code maxDate}] search time span + * @exception RuggedException if [{@code minDate}, {@code maxDate}] search time span overshoots + * position or attitude samples by more than {@code overshootTolerance} + * , */ public SpacecraftToObservedBody(final Frame inertialFrame, final Frame bodyFrame, - final AbsoluteDate minDate, final AbsoluteDate maxDate, + final AbsoluteDate minDate, final AbsoluteDate maxDate, final double overshootTolerance, final List<TimeStampedPVCoordinates> positionsVelocities, final int pvInterpolationOrder, final List<TimeStampedAngularCoordinates> quaternions, final int aInterpolationOrder, final double tStep) @@ -83,19 +86,19 @@ public class SpacecraftToObservedBody { // safety checks final AbsoluteDate minPVDate = positionsVelocities.get(0).getDate(); final AbsoluteDate maxPVDate = positionsVelocities.get(positionsVelocities.size() - 1).getDate(); - if (minDate.compareTo(minPVDate) < 0) { + if (minPVDate.durationFrom(minDate) > overshootTolerance) { throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, minDate, minPVDate, maxPVDate); } - if (maxDate.compareTo(maxPVDate) > 0) { + if (maxDate.durationFrom(maxDate) > overshootTolerance) { throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, maxDate, minPVDate, maxPVDate); } final AbsoluteDate minQDate = quaternions.get(0).getDate(); final AbsoluteDate maxQDate = quaternions.get(quaternions.size() - 1).getDate(); - if (minDate.compareTo(minQDate) < 0) { + if (minQDate.durationFrom(minDate) > overshootTolerance) { throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, minDate, minQDate, maxQDate); } - if (maxDate.compareTo(maxQDate) > 0) { + if (maxDate.durationFrom(maxQDate) > overshootTolerance) { throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, maxDate, minQDate, maxQDate); } @@ -114,13 +117,35 @@ public class SpacecraftToObservedBody { this.scToInertial = new ArrayList<Transform>(n); for (AbsoluteDate date = minDate; bodyToInertial.size() < n; date = date.shiftedBy(tStep)) { - // interpolate position-velocity - final TimeStampedPVCoordinates pv = - TimeStampedPVCoordinates.interpolate(date, CartesianDerivativesFilter.USE_PV, pvCache.getNeighbors(date)); - - // interpolate attitude - final TimeStampedAngularCoordinates quaternion = - TimeStampedAngularCoordinates.interpolate(date, AngularDerivativesFilter.USE_R, aCache.getNeighbors(date)); + // interpolate position-velocity, allowing slight extrapolation near the boundaries + final AbsoluteDate pvInterpolationDate; + if (date.compareTo(pvCache.getEarliest().getDate()) < 0) { + pvInterpolationDate = pvCache.getEarliest().getDate(); + } else if (date.compareTo(pvCache.getLatest().getDate()) > 0) { + pvInterpolationDate = pvCache.getLatest().getDate(); + } else { + pvInterpolationDate = date; + } + final TimeStampedPVCoordinates interpolatedPV = + TimeStampedPVCoordinates.interpolate(pvInterpolationDate, + CartesianDerivativesFilter.USE_PV, + pvCache.getNeighbors(pvInterpolationDate)); + final TimeStampedPVCoordinates pv = interpolatedPV.shiftedBy(date.durationFrom(pvInterpolationDate)); + + // interpolate attitude, allowing slight extrapolation near the boundaries + final AbsoluteDate aInterpolationDate; + if (date.compareTo(aCache.getEarliest().getDate()) < 0) { + aInterpolationDate = aCache.getEarliest().getDate(); + } else if (date.compareTo(aCache.getLatest().getDate()) > 0) { + aInterpolationDate = aCache.getLatest().getDate(); + } else { + aInterpolationDate = date; + } + final TimeStampedAngularCoordinates interpolatedQuaternion = + TimeStampedAngularCoordinates.interpolate(aInterpolationDate, + AngularDerivativesFilter.USE_R, + aCache.getNeighbors(aInterpolationDate)); + final TimeStampedAngularCoordinates quaternion = interpolatedQuaternion.shiftedBy(date.durationFrom(aInterpolationDate)); // store transform from spacecraft frame to inertial frame scToInertial.add(new Transform(date, diff --git a/core/src/test/java/org/orekit/rugged/api/RuggedTest.java b/core/src/test/java/org/orekit/rugged/api/RuggedTest.java index 632c3faef088061055c24d5511ff665fb341c7f7..48546ba8e5a5fee1404a61496cf532514d06b354 100644 --- a/core/src/test/java/org/orekit/rugged/api/RuggedTest.java +++ b/core/src/test/java/org/orekit/rugged/api/RuggedTest.java @@ -143,7 +143,7 @@ public class RuggedTest { Rugged rugged = new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - pv.get(0).getDate(), pv.get(pv.size() - 1).getDate(), + pv.get(0).getDate(), pv.get(pv.size() - 1).getDate(), 5.0, pv, 8, q, 8); Assert.assertTrue(rugged.isLightTimeCorrected()); @@ -173,7 +173,7 @@ public class RuggedTest { Rugged rugged = new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - orbit.getDate().shiftedBy(-10.0), orbit.getDate().shiftedBy(+10.0), + orbit.getDate().shiftedBy(-10.0), orbit.getDate().shiftedBy(+10.0), 5.0, 1.0, 8, propagator); Assert.assertTrue(rugged.isLightTimeCorrected()); @@ -220,11 +220,11 @@ public class RuggedTest { Assert.assertNotNull(new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - t0.shiftedBy(4), t0.shiftedBy(6), pv, 2, q, 2)); + t0.shiftedBy(4), t0.shiftedBy(6), 5.0, pv, 2, q, 2)); try { new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - t0.shiftedBy(-1), t0.shiftedBy(6), pv, 2, q, 2); + t0.shiftedBy(-1), t0.shiftedBy(6), 0.0001, pv, 2, q, 2); } catch (RuggedException re) { Assert.assertEquals(RuggedMessages.OUT_OF_TIME_RANGE, re.getSpecifier()); Assert.assertEquals(t0.shiftedBy(-1), re.getParts()[0]); @@ -233,7 +233,7 @@ public class RuggedTest { try { new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - t0.shiftedBy(2), t0.shiftedBy(6), pv, 2, q, 2); + t0.shiftedBy(2), t0.shiftedBy(6), 0.0001, pv, 2, q, 2); } catch (RuggedException re) { Assert.assertEquals(RuggedMessages.OUT_OF_TIME_RANGE, re.getSpecifier()); Assert.assertEquals(t0.shiftedBy(2), re.getParts()[0]); @@ -242,7 +242,7 @@ public class RuggedTest { try { new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - t0.shiftedBy(4), t0.shiftedBy(9), pv, 2, q, 2); + t0.shiftedBy(4), t0.shiftedBy(9), 0.0001, pv, 2, q, 2); } catch (RuggedException re) { Assert.assertEquals(RuggedMessages.OUT_OF_TIME_RANGE, re.getSpecifier()); Assert.assertEquals(t0.shiftedBy(9), re.getParts()[0]); @@ -251,7 +251,7 @@ public class RuggedTest { try { new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - t0.shiftedBy(4), t0.shiftedBy(12), pv, 2, q, 2); + t0.shiftedBy(4), t0.shiftedBy(12), 0.0001, pv, 2, q, 2); } catch (RuggedException re) { Assert.assertEquals(RuggedMessages.OUT_OF_TIME_RANGE, re.getSpecifier()); Assert.assertEquals(t0.shiftedBy(12), re.getParts()[0]); @@ -305,7 +305,7 @@ public class RuggedTest { Rugged rugged = new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - lineDatation.getDate(firstLine), lineDatation.getDate(lastLine), + lineDatation.getDate(firstLine), lineDatation.getDate(lastLine), 5.0, 1.0 / lineDatation.getRate(0.0), 8, ephemeris); rugged.setLightTimeCorrection(true); rugged.setAberrationOfLightCorrection(true); @@ -380,7 +380,7 @@ public class RuggedTest { Rugged rugged = new Rugged(null, -1, AlgorithmId.IGNORE_DEM_USE_ELLIPSOID, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - minDate, maxDate, + minDate, maxDate, 5.0, orbitToPV(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 8, orbitToQ(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 2); @@ -433,7 +433,7 @@ public class RuggedTest { Rugged rugged = new Rugged(null, -1, AlgorithmId.IGNORE_DEM_USE_ELLIPSOID, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - minDate, maxDate, + minDate, maxDate, 5.0, orbitToPV(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 8, orbitToQ(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 2); @@ -491,7 +491,7 @@ public class RuggedTest { Rugged ruggedFull = new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - minDate, maxDate, + minDate, maxDate, 5.0, orbitToPV(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 8, orbitToQ(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 2); ruggedFull.addLineSensor(lineSensor); @@ -499,7 +499,7 @@ public class RuggedTest { Rugged ruggedFlat = new Rugged(updater, 8, AlgorithmId.DUVENHAGE_FLAT_BODY, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - minDate, maxDate, + minDate, maxDate, 5.0, orbitToPV(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 8, orbitToQ(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 2); ruggedFlat.addLineSensor(lineSensor); @@ -562,7 +562,7 @@ public class RuggedTest { Rugged rugged = new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - minDate, maxDate, + minDate, maxDate, 5.0, orbitToPV(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 8, orbitToQ(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 2); rugged.setLightTimeCorrection(true); @@ -671,7 +671,7 @@ public class RuggedTest { TileUpdater updater = new RandomLandscapeUpdater(0.0, 9000.0, 0.5, 0xf0a401650191f9f6l, FastMath.toRadians(1.0), 257); Rugged rugged = new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - satellitePVList.get(0).getDate(), satellitePVList.get(satellitePVList.size() - 1).getDate(), + satellitePVList.get(0).getDate(), satellitePVList.get(satellitePVList.size() - 1).getDate(), 5.0, satellitePVList, 8, satelliteQList, 8); @@ -824,7 +824,7 @@ public class RuggedTest { Rugged rugged = new Rugged(updater, 8, AlgorithmId.DUVENHAGE, EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, - minDate, maxDate, + minDate, maxDate, 5.0, orbitToPV(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 8, orbitToQ(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 2); rugged.setLightTimeCorrection(lightTimeCorrection);