diff --git a/core/src/main/java/org/orekit/rugged/api/SensorMeanPlaneCrossing.java b/core/src/main/java/org/orekit/rugged/api/SensorMeanPlaneCrossing.java index 7899b8fa8d0f53464d515bdb043d1a5ce6ef703c..8452d2249b81e574aeeedc3852bfd4f8b23c5bb0 100644 --- a/core/src/main/java/org/orekit/rugged/api/SensorMeanPlaneCrossing.java +++ b/core/src/main/java/org/orekit/rugged/api/SensorMeanPlaneCrossing.java @@ -20,7 +20,6 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure; import org.apache.commons.math3.geometry.euclidean.threed.FieldVector3D; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.util.FastMath; -import org.orekit.errors.OrekitException; import org.orekit.frames.Transform; import org.orekit.rugged.utils.SpacecraftToObservedBody; import org.orekit.time.AbsoluteDate; @@ -86,25 +85,21 @@ class SensorMeanPlaneCrossing { final boolean aberrationOfLightCorrection, final int maxEval, final double accuracy) throws RuggedException { - try { - - this.sensor = sensor; - this.minLine = minLine; - this.maxLine = maxLine; - this.lightTimeCorrection = lightTimeCorrection; - this.aberrationOfLightCorrection = aberrationOfLightCorrection; - this.maxEval = maxEval; - this.accuracy = accuracy; - this.scToBody = scToBody; - - this.midLine = 0.5 * (minLine + maxLine); - final AbsoluteDate midDate = sensor.getDate(midLine); - this.midBodyToInert = scToBody.getBodyToInertial(midDate); - this.midScToInert = scToBody.getScToInertial(midDate); - - } catch (OrekitException oe) { - throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); - } + + this.sensor = sensor; + this.minLine = minLine; + this.maxLine = maxLine; + this.lightTimeCorrection = lightTimeCorrection; + this.aberrationOfLightCorrection = aberrationOfLightCorrection; + this.maxEval = maxEval; + this.accuracy = accuracy; + this.scToBody = scToBody; + + this.midLine = 0.5 * (minLine + maxLine); + final AbsoluteDate midDate = sensor.getDate(midLine); + this.midBodyToInert = scToBody.getBodyToInertial(midDate); + this.midScToInert = scToBody.getScToInertial(midDate); + } /** Get the minimum line number in the search interval. @@ -166,65 +161,61 @@ class SensorMeanPlaneCrossing { */ public CrossingResult find(final Vector3D target) throws RuggedException { - try { - - final PVCoordinates targetPV = new PVCoordinates(target, Vector3D.ZERO); - - // we don't use an Apache Commons Math solver here because we are more - // interested in reducing the number of evaluations than being accurate, - // as we know the solution is improved in the second stage of inverse localization. - // We expect two or three evaluations only. Each new evaluation shows up quickly in - // the performances as it involves frames conversions - double crossingLine = midLine; - Transform bodyToInert = midBodyToInert; - Transform scToInert = midScToInert; - boolean atMin = false; - boolean atMax = false; - for (int i = 0; i < maxEval; ++i) { - - final FieldVector3D<DerivativeStructure> targetDirection = - evaluateLine(crossingLine, targetPV, bodyToInert, scToInert); - final DerivativeStructure beta = FieldVector3D.angle(targetDirection, sensor.getMeanPlaneNormal()); - - final double deltaL = (0.5 * FastMath.PI - beta.getValue()) / beta.getPartialDerivative(1); - if (FastMath.abs(deltaL) <= accuracy) { - // return immediately, without doing any additional evaluation! - return new CrossingResult(crossingLine, targetDirection); - } - crossingLine += deltaL; - - if (crossingLine < minLine) { - if (atMin) { - // we were already trying at minLine and we need to go below that - // give up as the solution is out of search interval - return null; - } - atMin = true; - crossingLine = minLine; - } else if (crossingLine > maxLine) { - if (atMax) { - // we were already trying at maxLine and we need to go above that - // give up as the solution is out of search interval - return null; - } - atMax = true; - crossingLine = maxLine; - } else { - // the next evaluation will be a regular point - atMin = false; - atMax = false; - } - final AbsoluteDate date = sensor.getDate(crossingLine); - bodyToInert = scToBody.getBodyToInertial(date); - scToInert = scToBody.getScToInertial(date); + final PVCoordinates targetPV = new PVCoordinates(target, Vector3D.ZERO); + + // we don't use an Apache Commons Math solver here because we are more + // interested in reducing the number of evaluations than being accurate, + // as we know the solution is improved in the second stage of inverse localization. + // We expect two or three evaluations only. Each new evaluation shows up quickly in + // the performances as it involves frames conversions + double crossingLine = midLine; + Transform bodyToInert = midBodyToInert; + Transform scToInert = midScToInert; + boolean atMin = false; + boolean atMax = false; + for (int i = 0; i < maxEval; ++i) { + + final FieldVector3D<DerivativeStructure> targetDirection = + evaluateLine(crossingLine, targetPV, bodyToInert, scToInert); + final DerivativeStructure beta = FieldVector3D.angle(targetDirection, sensor.getMeanPlaneNormal()); + + final double deltaL = (0.5 * FastMath.PI - beta.getValue()) / beta.getPartialDerivative(1); + if (FastMath.abs(deltaL) <= accuracy) { + // return immediately, without doing any additional evaluation! + return new CrossingResult(crossingLine, targetDirection); } + crossingLine += deltaL; - return null; + if (crossingLine < minLine) { + if (atMin) { + // we were already trying at minLine and we need to go below that + // give up as the solution is out of search interval + return null; + } + atMin = true; + crossingLine = minLine; + } else if (crossingLine > maxLine) { + if (atMax) { + // we were already trying at maxLine and we need to go above that + // give up as the solution is out of search interval + return null; + } + atMax = true; + crossingLine = maxLine; + } else { + // the next evaluation will be a regular point + atMin = false; + atMax = false; + } - } catch (OrekitException oe) { - throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); + final AbsoluteDate date = sensor.getDate(crossingLine); + bodyToInert = scToBody.getBodyToInertial(date); + scToInert = scToBody.getScToInertial(date); } + + return null; + } /** Evaluate geometry for a given line number. 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 ac18d6752884c3bcbe31fb87c75ef4ee1c11140d..4183c4b0a0793963a18cacf9cf60c2322b111afa 100644 --- a/core/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java +++ b/core/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java @@ -36,6 +36,12 @@ import org.orekit.utils.TimeStampedPVCoordinates; */ public class SpacecraftToObservedBody { + /** Start of search time span. */ + private final AbsoluteDate minDate; + + /** End of search time span. */ + private final AbsoluteDate maxDate; + /** Step to use for inertial frame to body frame transforms cache computations. */ private final double tStep; @@ -68,6 +74,10 @@ public class SpacecraftToObservedBody { final double tStep) throws RuggedException { try { + + this.minDate = minDate; + this.maxDate = maxDate; + // safety checks final AbsoluteDate minPVDate = positionsVelocities.get(0).getDate(); final AbsoluteDate maxPVDate = positionsVelocities.get(positionsVelocities.size() - 1).getDate(); @@ -130,30 +140,30 @@ public class SpacecraftToObservedBody { /** Get transform from spacecraft to inertial frame. * @param date date of the transform * @return transform from spacecraft to inertial frame - * @exception OrekitException if spacecraft position or attitude cannot be computed at date + * @exception RuggedException if spacecraft position or attitude cannot be computed at date */ public Transform getScToInertial(final AbsoluteDate date) - throws OrekitException { + throws RuggedException { return interpolate(date, scToInertial); } /** Get transform from inertial frame to observed body frame. * @param date date of the transform * @return transform from inertial frame to observed body frame - * @exception OrekitException if frames cannot be computed at date + * @exception RuggedException if frames cannot be computed at date */ public Transform getInertialToBody(final AbsoluteDate date) - throws OrekitException { + throws RuggedException { return interpolate(date, inertialToBody); } /** Get transform from observed body frame to inertial frame. * @param date date of the transform * @return transform from observed body frame to inertial frame - * @exception OrekitException if frames cannot be computed at date + * @exception RuggedException if frames cannot be computed at date */ public Transform getBodyToInertial(final AbsoluteDate date) - throws OrekitException { + throws RuggedException { return interpolate(date, bodyToInertial); } @@ -161,14 +171,24 @@ public class SpacecraftToObservedBody { * @param date date of the transform * @param list transforms list to interpolate from * @return interpolated transform - * @exception OrekitException if frames cannot be computed at date + * @exception RuggedException if frames cannot be computed at date */ private Transform interpolate(final AbsoluteDate date, final List<Transform> list) - throws OrekitException { + throws RuggedException { + + // check date range + if (date.compareTo(minDate) < 0) { + throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, date, minDate, maxDate); + } + if (date.compareTo(maxDate) > 0) { + throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, date, minDate, maxDate); + } + final double s = date.durationFrom(list.get(0).getDate()) / tStep; final int index = FastMath.max(0, FastMath.min(list.size() - 1, (int) FastMath.rint(s))); final Transform close = list.get(index); return close.shiftedBy(date.durationFrom(close.getDate())); + } }