Commit a2c176a8 authored by LUGAN's avatar LUGAN
Browse files

Help user to know which and when a detector fails

parent c6546859
......@@ -323,7 +323,8 @@ public enum OrekitMessages implements Localizable {
UNKNOWN_UNIT("unknown unit {0}"),
INCOMPATIBLE_UNITS("units {0} and {1} are not compatible"),
MISSING_VELOCITY("missing velocity data"),
ATTEMPT_TO_GENERATE_MALFORMED_FILE("attempt to generate file {0} with a formatting error");
ATTEMPT_TO_GENERATE_MALFORMED_FILE("attempt to generate file {0} with a formatting error"),
FIND_ROOT("{0} failed to find root between {1} (g={2}) and {3} (g={4}) : {5}\nLast iteration at {6} (g={7})");
// CHECKSTYLE: resume JavadocVariable check
......
......@@ -24,7 +24,9 @@ import org.hipparchus.exception.MathRuntimeException;
import org.hipparchus.ode.events.Action;
import org.hipparchus.util.FastMath;
import org.hipparchus.util.Precision;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitInternalError;
import org.orekit.errors.OrekitMessages;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.sampling.OrekitStepInterpolator;
import org.orekit.time.AbsoluteDate;
......@@ -299,50 +301,55 @@ public class EventState<T extends EventDetector> {
double loopG = ga;
while ((afterRootG == 0.0 || afterRootG > 0.0 == g0Positive) &&
strictlyAfter(afterRootT, tb)) {
if (loopG == 0.0) {
// ga == 0.0 and gb may or may not be 0.0
// handle the root at ta first
beforeRootT = loopT;
beforeRootG = loopG;
afterRootT = minTime(shiftedBy(beforeRootT, convergence), tb);
afterRootG = g(interpolator.getInterpolatedState(afterRootT));
} else {
// both non-zero, the usual case, use a root finder.
// time zero for evaluating the function f. Needs to be final
final AbsoluteDate fT0 = loopT;
final UnivariateFunction f = dt -> {
return g(interpolator.getInterpolatedState(fT0.shiftedBy(dt)));
};
// tb as a double for use in f
final double tbDouble = tb.durationFrom(fT0);
if (forward) {
final Interval interval =
solver.solveInterval(maxIterationCount, f, 0, tbDouble);
beforeRootT = fT0.shiftedBy(interval.getLeftAbscissa());
beforeRootG = interval.getLeftValue();
afterRootT = fT0.shiftedBy(interval.getRightAbscissa());
afterRootG = interval.getRightValue();
try {
if (loopG == 0.0) {
// ga == 0.0 and gb may or may not be 0.0
// handle the root at ta first
beforeRootT = loopT;
beforeRootG = loopG;
afterRootT = minTime(shiftedBy(beforeRootT, convergence), tb);
afterRootG = g(interpolator.getInterpolatedState(afterRootT));
} else {
final Interval interval =
solver.solveInterval(maxIterationCount, f, tbDouble, 0);
beforeRootT = fT0.shiftedBy(interval.getRightAbscissa());
beforeRootG = interval.getRightValue();
afterRootT = fT0.shiftedBy(interval.getLeftAbscissa());
afterRootG = interval.getLeftValue();
// both non-zero, the usual case, use a root finder.
// time zero for evaluating the function f. Needs to be final
final AbsoluteDate fT0 = loopT;
final UnivariateFunction f = dt -> {
return g(interpolator.getInterpolatedState(fT0.shiftedBy(dt)));
};
// tb as a double for use in f
final double tbDouble = tb.durationFrom(fT0);
if (forward) {
final Interval interval =
solver.solveInterval(maxIterationCount, f, 0, tbDouble);
beforeRootT = fT0.shiftedBy(interval.getLeftAbscissa());
beforeRootG = interval.getLeftValue();
afterRootT = fT0.shiftedBy(interval.getRightAbscissa());
afterRootG = interval.getRightValue();
} else {
final Interval interval =
solver.solveInterval(maxIterationCount, f, tbDouble, 0);
beforeRootT = fT0.shiftedBy(interval.getRightAbscissa());
beforeRootG = interval.getRightValue();
afterRootT = fT0.shiftedBy(interval.getLeftAbscissa());
afterRootG = interval.getLeftValue();
}
}
// tolerance is set to less than 1 ulp
// assume tolerance is 1 ulp
if (beforeRootT.equals(afterRootT)) {
afterRootT = nextAfter(afterRootT);
afterRootG = g(interpolator.getInterpolatedState(afterRootT));
}
// check loop is making some progress
check(forward && afterRootT.compareTo(beforeRootT) > 0 ||
!forward && afterRootT.compareTo(beforeRootT) < 0);
// setup next iteration
loopT = afterRootT;
loopG = afterRootG;
}
// tolerance is set to less than 1 ulp
// assume tolerance is 1 ulp
if (beforeRootT.equals(afterRootT)) {
afterRootT = nextAfter(afterRootT);
afterRootG = g(interpolator.getInterpolatedState(afterRootT));
catch (Exception e) {
throw new OrekitException(e, OrekitMessages.FIND_ROOT, detector, ta, ga, tb, gb, e.getMessage(), loopT, loopG);
}
// check loop is making some progress
check(forward && afterRootT.compareTo(beforeRootT) > 0 ||
!forward && afterRootT.compareTo(beforeRootT) < 0);
// setup next iteration
loopT = afterRootT;
loopG = afterRootG;
}
// figure out the result of root finding, and return accordingly
......
......@@ -17,6 +17,7 @@
package org.orekit.propagation.events;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.hipparchus.exception.MathIllegalStateException;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.ode.events.Action;
import org.hipparchus.ode.nonstiff.ClassicalRungeKuttaIntegrator;
......@@ -296,7 +297,39 @@ public class EventDetectorTest {
k.propagate(initialDate.shiftedBy(Constants.JULIAN_YEAR));
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertSame(dummyCause, oe.getCause());
Assert.assertSame(dummyCause, oe.getCause().getCause());
}
}
@Test
public void testMathRuntimeException() {
try {
// initial conditions
Frame eme2000 = FramesFactory.getEME2000();
TimeScale utc = TimeScalesFactory.getUTC();
final AbsoluteDate initialDate = new AbsoluteDate(2011, 5, 11, utc);
EquinoctialOrbit initialOrbit = new EquinoctialOrbit(new PVCoordinates(new Vector3D(4008462.4706055815, -3155502.5373837613, -5044275.9880020910),
new Vector3D(-5012.9298276860990, 1920.3567095973078, -5172.7403501801580)), eme2000,
initialDate, Constants.WGS84_EARTH_MU);
KeplerianPropagator k = new KeplerianPropagator(initialOrbit);
k.addEventDetector(new AbstractDetector(100, 1e-6, 5, new ContinueOnEvent()) {
double lastValue = -1;
@Override
public double g(final SpacecraftState s) {
lastValue = lastValue * -1;
return lastValue;
}
@Override
protected AbstractDetector create(double newMaxCheck, double newThreshold, int newMaxIter, EventHandler newHandler) {
throw new UnsupportedOperationException("this class to be used locally");
}
});
k.propagate(initialDate.shiftedBy(initialOrbit.getKeplerianPeriod()));
Assert.fail("an exception should have been thrown");
}
catch (RuntimeException oe) {
Assert.assertSame(MathIllegalStateException.class, oe.getCause().getClass());
}
}
......
Supports Markdown
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