diff --git a/src/main/java/org/orekit/propagation/events/EclipseDetector.java b/src/main/java/org/orekit/propagation/events/EclipseDetector.java index 1ca60747f4..367e0a7162 100644 --- a/src/main/java/org/orekit/propagation/events/EclipseDetector.java +++ b/src/main/java/org/orekit/propagation/events/EclipseDetector.java @@ -19,7 +19,10 @@ import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.hipparchus.ode.events.Action; import org.hipparchus.util.FastMath; +import org.orekit.bodies.GeodeticPoint; import org.orekit.bodies.OneAxisEllipsoid; +import org.orekit.frames.Frame; +import org.orekit.frames.FramesFactory; import org.orekit.propagation.SpacecraftState; import org.orekit.propagation.events.handlers.EventHandler; import org.orekit.propagation.events.handlers.StopOnIncreasing; @@ -61,6 +64,9 @@ public class EclipseDetector extends AbstractDetector { /** Umbra, if true, or penumbra, if false, detection flag. */ private final boolean totalEclipse; + + /** Sub-satellite point, if true, or Spacecraft, if false (default), flag. */ + private boolean subSatellitePoint = false; /** Build a new eclipse detector. *

The new instance is a total eclipse (umbra) detector with default @@ -75,7 +81,7 @@ public EclipseDetector(final PVCoordinatesProvider occulted, final double occul final OneAxisEllipsoid occulting) { this(DEFAULT_MAXCHECK, DEFAULT_THRESHOLD, DEFAULT_MAX_ITER, new StopOnIncreasing(), - occulted, occultedRadius, occulting, true); + occulted, occultedRadius, occulting, true, false); } /** Private constructor with full parameters. @@ -92,17 +98,20 @@ public EclipseDetector(final PVCoordinatesProvider occulted, final double occul * @param occultedRadius the radius of the body to be occulted in meters * @param occulting the occulting body * @param totalEclipse umbra (true) or penumbra (false) detection flag + * @param subSatellitePoint Sub-satellite point (true) or Spacecraft (false) flag * @since 10.0 */ private EclipseDetector(final double maxCheck, final double threshold, final int maxIter, final EventHandler handler, final PVCoordinatesProvider occulted, final double occultedRadius, - final OneAxisEllipsoid occulting, final boolean totalEclipse) { + final OneAxisEllipsoid occulting, final boolean totalEclipse, final boolean subSatellitePoint) { super(maxCheck, threshold, maxIter, handler); this.occulted = occulted; this.occultedRadius = FastMath.abs(occultedRadius); this.occulting = occulting; this.totalEclipse = totalEclipse; + this.subSatellitePoint = subSatellitePoint; + } /** {@inheritDoc} */ @@ -110,11 +119,11 @@ private EclipseDetector(final double maxCheck, final double threshold, protected EclipseDetector create(final double newMaxCheck, final double newThreshold, final int nawMaxIter, final EventHandler newHandler) { return new EclipseDetector(newMaxCheck, newThreshold, nawMaxIter, newHandler, - occulted, occultedRadius, occulting, totalEclipse); + occulted, occultedRadius, occulting, totalEclipse, subSatellitePoint); } /** - * Setup the detector to full umbra detection. + * Setup the detector to full umbra detection for the satellite. *

* This will override a penumbra/umbra flag if it has been configured previously. *

@@ -124,21 +133,30 @@ protected EclipseDetector create(final double newMaxCheck, final double newThres */ public EclipseDetector withUmbra() { return new EclipseDetector(getMaxCheckInterval(), getThreshold(), getMaxIterationCount(), getHandler(), - occulted, occultedRadius, occulting, true); + occulted, occultedRadius, occulting, true, subSatellitePoint); } - + /** - * Setup the detector to penumbra detection. + * Setup the detector to penumbra detection for the satellite. *

* This will override a penumbra/umbra flag if it has been configured previously. *

* @return a new detector with updated configuration (the instance is not changed) - * @see #withUmbra() - * @since 6.1 + * @see #penumbraWithSSP() */ public EclipseDetector withPenumbra() { return new EclipseDetector(getMaxCheckInterval(), getThreshold(), getMaxIterationCount(), getHandler(), - occulted, occultedRadius, occulting, false); + occulted, occultedRadius, occulting, false, subSatellitePoint); + } + + /** + * Setup the detector for the sub-satellite point. + *

+ * @return a new detector with updated configuration (the instance is not changed) + */ + public EclipseDetector withSubSatellitePoint() { + return new EclipseDetector(getMaxCheckInterval(), getThreshold(), getMaxIterationCount(), getHandler(), + occulted, occultedRadius, occulting, totalEclipse, true); } /** Getter for the occulting body. @@ -169,6 +187,14 @@ public double getOccultedRadius() { public boolean getTotalEclipse() { return totalEclipse; } + + /** Get the sub-satellite point flag. + * @return the sub-satellite point flag (true for sub-satellite point, + * false for satellite) + */ + public boolean getSubSatellitePoint() { + return subSatellitePoint; + } /** Compute the value of the switching function. * This function becomes negative when entering the region of shadow @@ -178,7 +204,15 @@ public boolean getTotalEclipse() { */ public double g(final SpacecraftState s) { final Vector3D pted = occulted.getPVCoordinates(s.getDate(), occulting.getBodyFrame()).getPosition(); - final Vector3D psat = s.getPVCoordinates(occulting.getBodyFrame()).getPosition(); + Vector3D psat = null; + if (subSatellitePoint) { + Frame inertialFrame = s.getFrame(); + GeodeticPoint gp = getOcculting().transform(s.getPVCoordinates().getPosition(), inertialFrame, s.getDate()); + GeodeticPoint gpSSP = new GeodeticPoint(gp.getLatitude(), gp.getLongitude(), 1); + psat = getOcculting().transform(gpSSP); + } else { + psat = s.getPVCoordinates(occulting.getBodyFrame()).getPosition(); + } final Vector3D plimb = occulting.pointOnLimb(psat, pted); final Vector3D ps = psat.subtract(pted); final Vector3D pi = psat.subtract(plimb); diff --git a/src/test/java/org/orekit/propagation/events/EclipseDetectorTest.java b/src/test/java/org/orekit/propagation/events/EclipseDetectorTest.java index cae8a97815..0af9cbf5cf 100644 --- a/src/test/java/org/orekit/propagation/events/EclipseDetectorTest.java +++ b/src/test/java/org/orekit/propagation/events/EclipseDetectorTest.java @@ -159,6 +159,18 @@ public void testPenumbra() { final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(6000)); Assert.assertEquals(4388.155852, finalState.getDate().durationFrom(iniDate), 2.0e-6); } + + @Test + public void testSubSatellitePoint() { + EclipseDetector e = new EclipseDetector(sun, sunRadius, earth). + withMaxCheck(60.0). + withThreshold(1.0e-3). + withUmbra().withSubSatellitePoint(); + Assert.assertTrue(e.getTotalEclipse()); + propagator.addEventDetector(e); + final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(6000)); + Assert.assertEquals(4815.310605, finalState.getDate().durationFrom(iniDate), 2.0e-6); + } @Test public void testWithMethods() {