From b61d7eadbf497dc6ac40a0e6c51774dcfbeb232a Mon Sep 17 00:00:00 2001 From: Luc Maisonobe <luc@orekit.org> Date: Mon, 18 May 2015 13:51:28 +0200 Subject: [PATCH] Use exceptions rather than null for inverse location errors. This helps caller to set fix the min/max lines as we can provide information about where the point is expected. --- .../java/org/orekit/rugged/api/Rugged.java | 138 +++++++++--------- .../java/org/orekit/rugged/errors/Dump.java | 13 ++ .../org/orekit/rugged/errors/DumpManager.java | 9 ++ .../orekit/rugged/errors/DumpReplayer.java | 46 +++++- .../InverseLocOutOfColumnRangeException.java | 45 ++++++ .../InverseLocOutOfLineRangeException.java | 45 ++++++ .../orekit/rugged/errors/RuggedMessages.java | 2 + .../linesensor/SensorMeanPlaneCrossing.java | 57 ++++---- .../linesensor/SensorPixelCrossing.java | 43 +++--- .../org/orekit/rugged/RuggedMessages_de.utf8 | 6 + .../org/orekit/rugged/RuggedMessages_en.utf8 | 6 + .../org/orekit/rugged/RuggedMessages_es.utf8 | 6 + .../org/orekit/rugged/RuggedMessages_fr.utf8 | 6 + .../org/orekit/rugged/RuggedMessages_gl.utf8 | 6 + .../org/orekit/rugged/RuggedMessages_it.utf8 | 6 + .../org/orekit/rugged/RuggedMessages_no.utf8 | 6 + .../org/orekit/rugged/RuggedMessages_ro.utf8 | 6 + src/site/xdoc/changes.xml | 5 + .../org/orekit/rugged/api/RuggedTest.java | 76 +++++++--- .../rugged/errors/DumpReplayerTest.java | 25 ++++ .../rugged/errors/RuggedMessagesTest.java | 2 +- .../replay/replay-inverse-loc-03.txt | 15 ++ 22 files changed, 432 insertions(+), 137 deletions(-) create mode 100644 src/main/java/org/orekit/rugged/errors/InverseLocOutOfColumnRangeException.java create mode 100644 src/main/java/org/orekit/rugged/errors/InverseLocOutOfLineRangeException.java create mode 100644 src/test/resources/replay/replay-inverse-loc-03.txt diff --git a/src/main/java/org/orekit/rugged/api/Rugged.java b/src/main/java/org/orekit/rugged/api/Rugged.java index fe9b8dcf..b0d8c876 100644 --- a/src/main/java/org/orekit/rugged/api/Rugged.java +++ b/src/main/java/org/orekit/rugged/api/Rugged.java @@ -27,6 +27,8 @@ import org.apache.commons.math3.util.FastMath; import org.orekit.bodies.GeodeticPoint; import org.orekit.frames.Transform; import org.orekit.rugged.errors.DumpManager; +import org.orekit.rugged.errors.InverseLocOutOfColumnRangeException; +import org.orekit.rugged.errors.InverseLocOutOfLineRangeException; import org.orekit.rugged.errors.RuggedException; import org.orekit.rugged.errors.RuggedMessages; import org.orekit.rugged.intersection.IntersectionAlgorithm; @@ -376,25 +378,20 @@ public class Rugged { * @param minLine minimum line number * @param maxLine maximum line number * @return date at which ground point is seen by line sensor + * @exception InverseLocOutOfLineRangeException if the ground point is out of line range * @exception RuggedException if line cannot be localized, or sensor is unknown * @see #inverseLocation(String, GeodeticPoint, int, int) */ public AbsoluteDate dateLocation(final String sensorName, final GeodeticPoint point, final int minLine, final int maxLine) - throws RuggedException { + throws InverseLocOutOfLineRangeException, RuggedException { final LineSensor sensor = getLineSensor(sensorName); final SensorMeanPlaneCrossing planeCrossing = getPlaneCrossing(sensorName, minLine, maxLine); // find approximately the sensor line at which ground point crosses sensor mean plane final Vector3D target = ellipsoid.transform(point); - final SensorMeanPlaneCrossing.CrossingResult crossingResult = planeCrossing.find(target); - if (crossingResult == null) { - // target is out of search interval - return null; - } else { - return sensor.getDate(crossingResult.getLine()); - } + return sensor.getDate(planeCrossing.find(target).getLine()); } @@ -408,14 +405,15 @@ public class Rugged { * @param longitude ground point longitude * @param minLine minimum line number * @param maxLine maximum line number - * @return sensor pixel seeing ground point, or null if ground point cannot - * be seen between the prescribed line numbers + * @return sensor pixel seeing ground point + * @exception InverseLocOutOfLineRangeException if the ground point is out of line range + * @exception InverseLocOutOfColumnRangeException if the ground point is out of column range * @exception RuggedException if line cannot be localized, or sensor is unknown */ public SensorPixel inverseLocation(final String sensorName, final double latitude, final double longitude, final int minLine, final int maxLine) - throws RuggedException { + throws InverseLocOutOfLineRangeException, InverseLocOutOfColumnRangeException, RuggedException { final GeodeticPoint groundPoint = new GeodeticPoint(latitude, longitude, algorithm.getElevation(latitude, longitude)); return inverseLocation(sensorName, groundPoint, minLine, maxLine); @@ -426,72 +424,74 @@ public class Rugged { * @param point point to localize * @param minLine minimum line number * @param maxLine maximum line number - * @return sensor pixel seeing point, or null if point cannot be seen between the - * prescribed line numbers + * @return sensor pixel seeing point + * @exception InverseLocOutOfLineRangeException if the ground point is out of line range + * @exception InverseLocOutOfColumnRangeException if the ground point is out of column range * @exception RuggedException if line cannot be localized, or sensor is unknown * @see #dateLocation(String, GeodeticPoint, int, int) */ public SensorPixel inverseLocation(final String sensorName, final GeodeticPoint point, final int minLine, final int maxLine) - throws RuggedException { - - final LineSensor sensor = getLineSensor(sensorName); - DumpManager.dumpInverseLocation(sensor, point, minLine, maxLine, - lightTimeCorrection, aberrationOfLightCorrection); - - final SensorMeanPlaneCrossing planeCrossing = getPlaneCrossing(sensorName, minLine, maxLine); - - DumpManager.dumpSensorMeanPlane(planeCrossing); - - // find approximately the sensor line at which ground point crosses sensor mean plane - final Vector3D target = ellipsoid.transform(point); - final SensorMeanPlaneCrossing.CrossingResult crossingResult = planeCrossing.find(target); - if (crossingResult == null) { - // target is out of search interval - return null; - } + throws InverseLocOutOfLineRangeException, InverseLocOutOfColumnRangeException, RuggedException { + + try { + final LineSensor sensor = getLineSensor(sensorName); + DumpManager.dumpInverseLocation(sensor, point, minLine, maxLine, + lightTimeCorrection, aberrationOfLightCorrection); + + final SensorMeanPlaneCrossing planeCrossing = getPlaneCrossing(sensorName, minLine, maxLine); + + DumpManager.dumpSensorMeanPlane(planeCrossing); + + // find approximately the sensor line at which ground point crosses sensor mean plane + final Vector3D target = ellipsoid.transform(point); + final SensorMeanPlaneCrossing.CrossingResult crossingResult = planeCrossing.find(target); + + // find approximately the pixel along this sensor line + final SensorPixelCrossing pixelCrossing = + new SensorPixelCrossing(sensor, planeCrossing.getMeanPlaneNormal(), + crossingResult.getTargetDirection().toVector3D(), + MAX_EVAL, COARSE_INVERSE_LOCATION_ACCURACY); + final double coarsePixel = pixelCrossing.locatePixel(crossingResult.getDate()); + if (Double.isNaN(coarsePixel)) { + // target is out of search interval + return null; + } - // find approximately the pixel along this sensor line - final SensorPixelCrossing pixelCrossing = - new SensorPixelCrossing(sensor, planeCrossing.getMeanPlaneNormal(), - crossingResult.getTargetDirection().toVector3D(), - MAX_EVAL, COARSE_INVERSE_LOCATION_ACCURACY); - final double coarsePixel = pixelCrossing.locatePixel(crossingResult.getDate()); - if (Double.isNaN(coarsePixel)) { - // target is out of search interval - return null; + // fix line by considering the closest pixel exact position and line-of-sight + // (this pixel might point towards a direction slightly above or below the mean sensor plane) + final int lowIndex = FastMath.max(0, FastMath.min(sensor.getNbPixels() - 2, (int) FastMath.floor(coarsePixel))); + final Vector3D lowLOS = sensor.getLos(crossingResult.getDate(), lowIndex); + final Vector3D highLOS = sensor.getLos(crossingResult.getDate(), lowIndex + 1); + final Vector3D localZ = Vector3D.crossProduct(lowLOS, highLOS); + final DerivativeStructure beta = FieldVector3D.angle(crossingResult.getTargetDirection(), localZ); + final double deltaL = (0.5 * FastMath.PI - beta.getValue()) / beta.getPartialDerivative(1); + final double fixedLine = crossingResult.getLine() + deltaL; + final Vector3D fixedDirection = new Vector3D(crossingResult.getTargetDirection().getX().taylor(deltaL), + crossingResult.getTargetDirection().getY().taylor(deltaL), + crossingResult.getTargetDirection().getZ().taylor(deltaL)).normalize(); + + // fix neighbouring pixels + final AbsoluteDate fixedDate = sensor.getDate(fixedLine); + final Vector3D fixedX = sensor.getLos(fixedDate, lowIndex); + final Vector3D fixedZ = Vector3D.crossProduct(fixedX, sensor.getLos(fixedDate, lowIndex + 1)); + final Vector3D fixedY = Vector3D.crossProduct(fixedZ, fixedX); + + // fix pixel + final double pixelWidth = FastMath.atan2(Vector3D.dotProduct(highLOS, fixedY), + Vector3D.dotProduct(highLOS, fixedX)); + final double alpha = FastMath.atan2(Vector3D.dotProduct(fixedDirection, fixedY), + Vector3D.dotProduct(fixedDirection, fixedX)); + final double fixedPixel = lowIndex + alpha / pixelWidth; + + final SensorPixel result = new SensorPixel(fixedLine, fixedPixel); + DumpManager.dumpInverseLocationResult(result); + return result; + } catch (RuggedException re) { + DumpManager.dumpException(re); + throw(re); } - // fix line by considering the closest pixel exact position and line-of-sight - // (this pixel might point towards a direction slightly above or below the mean sensor plane) - final int lowIndex = FastMath.max(0, FastMath.min(sensor.getNbPixels() - 2, (int) FastMath.floor(coarsePixel))); - final Vector3D lowLOS = sensor.getLos(crossingResult.getDate(), lowIndex); - final Vector3D highLOS = sensor.getLos(crossingResult.getDate(), lowIndex + 1); - final Vector3D localZ = Vector3D.crossProduct(lowLOS, highLOS); - final DerivativeStructure beta = FieldVector3D.angle(crossingResult.getTargetDirection(), localZ); - final double deltaL = (0.5 * FastMath.PI - beta.getValue()) / beta.getPartialDerivative(1); - final double fixedLine = crossingResult.getLine() + deltaL; - final Vector3D fixedDirection = new Vector3D(crossingResult.getTargetDirection().getX().taylor(deltaL), - crossingResult.getTargetDirection().getY().taylor(deltaL), - crossingResult.getTargetDirection().getZ().taylor(deltaL)).normalize(); - - // fix neighbouring pixels - final AbsoluteDate fixedDate = sensor.getDate(fixedLine); - final Vector3D fixedX = sensor.getLos(fixedDate, lowIndex); - final Vector3D fixedZ = Vector3D.crossProduct(fixedX, sensor.getLos(fixedDate, lowIndex + 1)); - final Vector3D fixedY = Vector3D.crossProduct(fixedZ, fixedX); - - // fix pixel - final double pixelWidth = FastMath.atan2(Vector3D.dotProduct(highLOS, fixedY), - Vector3D.dotProduct(highLOS, fixedX)); - final double alpha = FastMath.atan2(Vector3D.dotProduct(fixedDirection, fixedY), - Vector3D.dotProduct(fixedDirection, fixedX)); - final double fixedPixel = lowIndex + alpha / pixelWidth; - - final SensorPixel result = new SensorPixel(fixedLine, fixedPixel); - DumpManager.dumpInverseLocationResult(result); - return result; - } /** Get the mean plane crossing finder for a sensor. diff --git a/src/main/java/org/orekit/rugged/errors/Dump.java b/src/main/java/org/orekit/rugged/errors/Dump.java index 3b581aa1..c60c7374 100644 --- a/src/main/java/org/orekit/rugged/errors/Dump.java +++ b/src/main/java/org/orekit/rugged/errors/Dump.java @@ -207,6 +207,19 @@ class Dump { } } + /** Dump an exception. + * @param e exception to dump + */ + public void dumpException(final RuggedException e) { + writer.format(Locale.US, + "Rugged exception: specifier %s parts", + e.getSpecifier().toString()); + for (final Object part : e.getParts()) { + writer.format(Locale.US, " %s", part); + } + writer.format(" %n"); + } + /** Dump an observation transform transform. * @param scToBody provider for observation * @param index index of the transform diff --git a/src/main/java/org/orekit/rugged/errors/DumpManager.java b/src/main/java/org/orekit/rugged/errors/DumpManager.java index 713beb5f..0dc11e04 100644 --- a/src/main/java/org/orekit/rugged/errors/DumpManager.java +++ b/src/main/java/org/orekit/rugged/errors/DumpManager.java @@ -186,6 +186,15 @@ public class DumpManager { } } + /** Dump an exception. + * @param e exception to dump + */ + public static void dumpException(final RuggedException e) { + if (isActive()) { + DUMP.get().dumpException(e); + } + } + /** Dump an observation transform transform. * @param scToBody provider for observation * @param index index of the transform diff --git a/src/main/java/org/orekit/rugged/errors/DumpReplayer.java b/src/main/java/org/orekit/rugged/errors/DumpReplayer.java index 6fdec225..4f5f8c00 100644 --- a/src/main/java/org/orekit/rugged/errors/DumpReplayer.java +++ b/src/main/java/org/orekit/rugged/errors/DumpReplayer.java @@ -34,6 +34,7 @@ import java.util.NavigableMap; import java.util.TreeMap; import org.apache.commons.math3.analysis.differentiation.DerivativeStructure; +import org.apache.commons.math3.exception.util.Localizable; import org.apache.commons.math3.exception.util.LocalizedFormats; import org.apache.commons.math3.geometry.euclidean.threed.FieldVector3D; import org.apache.commons.math3.geometry.euclidean.threed.Rotation; @@ -44,6 +45,7 @@ import org.apache.commons.math3.util.Pair; import org.orekit.bodies.GeodeticPoint; import org.orekit.bodies.OneAxisEllipsoid; import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; import org.orekit.frames.Frame; import org.orekit.frames.FramesFactory; import org.orekit.frames.Predefined; @@ -211,6 +213,12 @@ public class DumpReplayer { /** Keyword for target direction. */ private static final String TARGET_DIRECTION = "targetDirection"; + /** Keyword for exception specifier. */ + private static final String SPECIFIER = "specifier"; + + /** Keyword for exception parts. */ + private static final String PARTS = "parts"; + /** Constant elevation for constant elevation algorithm. */ private double constantElevation; @@ -436,8 +444,13 @@ public class DumpReplayer { public Result[] execute(final Rugged rugged) throws RuggedException { final Result[] results = new Result[calls.size()]; for (int i = 0; i < calls.size(); ++i) { - results[i] = new Result(calls.get(i).expected, - calls.get(i).execute(rugged)); + Object result = null; + try { + result = calls.get(i).execute(rugged); + } catch (RuggedException re) { + result = re; + } + results[i] = new Result(calls.get(i).expected, result); } return results; } @@ -963,6 +976,35 @@ public class DumpReplayer { } + }, + + /** Parser for exception dump lines. */ + RUGGED_EXCEPTION() { + + /** {@inheritDoc} */ + @Override + public void parse(final int l, final File file, final String line, final String[] fields, final DumpReplayer global) + throws RuggedException { + if (fields.length < 3 || !fields[0].equals(SPECIFIER) || !fields[2].equals(PARTS)) { + throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); + } + Localizable specifier = null; + try { + specifier = RuggedMessages.valueOf(fields[1]); + } catch (IllegalArgumentException e1) { + try { + specifier = OrekitMessages.valueOf(fields[1]); + } catch (IllegalArgumentException e2) { + specifier = LocalizedFormats.valueOf(fields[1]); + } + } + final Object[] parts = new Object[fields.length - 3]; + System.arraycopy(fields, 3, parts, 0, parts.length); + final RuggedException re = new RuggedException(specifier, parts); + final DumpedCall last = global.calls.get(global.calls.size() - 1); + last.expected = re; + } + }; /** Parse a line. diff --git a/src/main/java/org/orekit/rugged/errors/InverseLocOutOfColumnRangeException.java b/src/main/java/org/orekit/rugged/errors/InverseLocOutOfColumnRangeException.java new file mode 100644 index 00000000..a6fad865 --- /dev/null +++ b/src/main/java/org/orekit/rugged/errors/InverseLocOutOfColumnRangeException.java @@ -0,0 +1,45 @@ +/* Copyright 2013-2015 CS Systèmes d'Information + * Licensed to CS Systèmes d'Information (CS) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * CS licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.orekit.rugged.errors; + + +/** This class is a specialized exception for inverse location errors. + * @author Luc Maisonobe + */ + +public class InverseLocOutOfColumnRangeException extends RuggedException { + + /** Serializable UID. */ + private static final long serialVersionUID = 20150518L; + + /** Simple constructor. + * @param expectedColumn expected column number for the ground point + * @param minColumn minimum column number + * @param maxColumn maximum column number + */ + public InverseLocOutOfColumnRangeException(final double expectedColumn, final int minColumn, final int maxColumn) { + super(RuggedMessages.GROUND_POINT_OUT_OF_COLUMN_RANGE, expectedColumn, minColumn, maxColumn); + } + + /** Get the expected column number for the ground point. + * @return expected column number for the ground point + */ + public double getExpectedColumn() { + return ((Double) getParts()[0]).doubleValue(); + } + +} diff --git a/src/main/java/org/orekit/rugged/errors/InverseLocOutOfLineRangeException.java b/src/main/java/org/orekit/rugged/errors/InverseLocOutOfLineRangeException.java new file mode 100644 index 00000000..833e09a8 --- /dev/null +++ b/src/main/java/org/orekit/rugged/errors/InverseLocOutOfLineRangeException.java @@ -0,0 +1,45 @@ +/* Copyright 2013-2015 CS Systèmes d'Information + * Licensed to CS Systèmes d'Information (CS) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * CS licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.orekit.rugged.errors; + + +/** This class is a specialized exception for inverse location errors. + * @author Luc Maisonobe + */ + +public class InverseLocOutOfLineRangeException extends RuggedException { + + /** Serializable UID. */ + private static final long serialVersionUID = 20150518L; + + /** Simple constructor. + * @param expectedLine expected line number for the ground point + * @param minLine minimum line number + * @param maxLine maximum line number + */ + public InverseLocOutOfLineRangeException(final double expectedLine, final int minLine, final int maxLine) { + super(RuggedMessages.GROUND_POINT_OUT_OF_LINE_RANGE, expectedLine, minLine, maxLine); + } + + /** Get the expected line number for the ground point. + * @return expected line number for the ground point + */ + public double getExpectedLine() { + return ((Double) getParts()[0]).doubleValue(); + } + +} diff --git a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java index e657479f..f3cb9741 100644 --- a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java +++ b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java @@ -63,6 +63,8 @@ public enum RuggedMessages implements Localizable { LINE_OF_SIGHT_NEVER_CROSSES_LATITUDE("line-of-sight never crosses latitude {0}"), LINE_OF_SIGHT_NEVER_CROSSES_LONGITUDE("line-of-sight never crosses longitude {0}"), LINE_OF_SIGHT_NEVER_CROSSES_ALTITUDE("line-of-sight never crosses altitude {0}"), + GROUND_POINT_OUT_OF_LINE_RANGE("ground point is around line {0}, out of the [{1}, {2}] range"), + GROUND_POINT_OUT_OF_COLUMN_RANGE("ground point is around column {0}, out of the [{1}, {2}] range"), DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT("line-of-sight enters the Digital Elevation Model behind spacecraft!"), FRAMES_MISMATCH_WITH_INTERPOLATOR_DUMP("frame {0} does not match frame {1} from interpolator dump"), NOT_INTERPOLATOR_DUMP_DATA("data is not an interpolator dump"), diff --git a/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java b/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java index 4f7bcce0..5ca1b0cb 100644 --- a/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java +++ b/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java @@ -21,6 +21,7 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure; import org.apache.commons.math3.analysis.solvers.BracketingNthOrderBrentSolver; import org.apache.commons.math3.analysis.solvers.UnivariateSolver; import org.apache.commons.math3.exception.NoBracketingException; +import org.apache.commons.math3.exception.util.LocalizedFormats; import org.apache.commons.math3.geometry.euclidean.threed.FieldVector3D; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.linear.Array2DRowRealMatrix; @@ -35,6 +36,7 @@ import org.apache.commons.math3.linear.SingularValueDecomposition; import org.apache.commons.math3.util.FastMath; import org.apache.commons.math3.util.Precision; import org.orekit.frames.Transform; +import org.orekit.rugged.errors.InverseLocOutOfLineRangeException; import org.orekit.rugged.errors.RuggedException; import org.orekit.rugged.errors.RuggedExceptionWrapper; import org.orekit.rugged.utils.SpacecraftToObservedBody; @@ -331,13 +333,13 @@ public class SensorMeanPlaneCrossing { /** Find mean plane crossing. * @param target target ground point - * @return line number and target direction at mean plane crossing, - * or null if search interval does not bracket a solution + * @return line number and target direction at mean plane crossing + * @exception InverseLocOutOfLineRangeException if the ground point is out of line range * @exception RuggedException if geometry cannot be computed for some line or * if the maximum number of evaluations is exceeded */ public CrossingResult find(final Vector3D target) - throws RuggedException { + throws InverseLocOutOfLineRangeException, RuggedException { double crossingLine = midLine; Transform bodyToInert = midBodyToInert; @@ -410,9 +412,6 @@ public class SensorMeanPlaneCrossing { // rare case: we are stuck in a loop! // switch to a more robust (but slower) algorithm in this case final CrossingResult slowResult = slowFind(targetPV, crossingLine); - if (slowResult == null) { - return null; - } for (int k = cachedResults.length - 1; k > 0; --k) { cachedResults[k] = cachedResults[k - 1]; } @@ -425,7 +424,7 @@ public class SensorMeanPlaneCrossing { 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; + throw new InverseLocOutOfLineRangeException(crossingLine, minLine, maxLine); } atMin = true; crossingLine = minLine; @@ -433,7 +432,7 @@ public class SensorMeanPlaneCrossing { 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; + throw new InverseLocOutOfLineRangeException(crossingLine, minLine, maxLine); } atMax = true; crossingLine = maxLine; @@ -448,7 +447,7 @@ public class SensorMeanPlaneCrossing { scToInert = scToBody.getScToInertial(date); } - return null; + throw new RuggedException(LocalizedFormats.MAX_COUNT_EXCEEDED, maxEval); } @@ -496,6 +495,24 @@ public class SensorMeanPlaneCrossing { */ public CrossingResult slowFind(final PVCoordinates targetPV, final double initialGuess) throws RuggedException { + + // set up function evaluating to 0.0 where target matches line + final UnivariateFunction f = new UnivariateFunction() { + /** {@inheritDoc} */ + @Override + public double value(final double x) throws RuggedExceptionWrapper { + try { + final AbsoluteDate date = sensor.getDate(x); + final FieldVector3D<DerivativeStructure> targetDirection = + evaluateLine(x, targetPV, scToBody.getBodyToInertial(date), scToBody.getScToInertial(date)); + final DerivativeStructure beta = FieldVector3D.angle(targetDirection, meanPlaneNormal); + return 0.5 * FastMath.PI - beta.getValue(); + } catch (RuggedException re) { + throw new RuggedExceptionWrapper(re); + } + } + }; + try { // safety check @@ -507,21 +524,7 @@ public class SensorMeanPlaneCrossing { } final UnivariateSolver solver = new BracketingNthOrderBrentSolver(accuracy, 5); - double crossingLine = solver.solve(maxEval, new UnivariateFunction() { - /** {@inheritDoc} */ - @Override - public double value(final double x) throws RuggedExceptionWrapper { - try { - final AbsoluteDate date = sensor.getDate(x); - final FieldVector3D<DerivativeStructure> targetDirection = - evaluateLine(x, targetPV, scToBody.getBodyToInertial(date), scToBody.getScToInertial(date)); - final DerivativeStructure beta = FieldVector3D.angle(targetDirection, meanPlaneNormal); - return 0.5 * FastMath.PI - beta.getValue(); - } catch (RuggedException re) { - throw new RuggedExceptionWrapper(re); - } - } - }, minLine, maxLine, startValue); + double crossingLine = solver.solve(maxEval, f, minLine, maxLine, startValue); final AbsoluteDate date = sensor.getDate(crossingLine); final FieldVector3D<DerivativeStructure> targetDirection = @@ -529,10 +532,14 @@ public class SensorMeanPlaneCrossing { return new CrossingResult(sensor.getDate(crossingLine), crossingLine, targetPV.getPosition(), targetDirection); } catch (NoBracketingException nbe) { - return null; + final double fMinLine = f.value(minLine); + final double fMaxLine = f.value(maxLine); + final double expectedLine = (fMaxLine * minLine - fMinLine * maxLine) / (fMaxLine - fMinLine); + throw new InverseLocOutOfLineRangeException(expectedLine, minLine, maxLine); } catch (RuggedExceptionWrapper rew) { throw rew.getException(); } + } /** Evaluate geometry for a given line number. diff --git a/src/main/java/org/orekit/rugged/linesensor/SensorPixelCrossing.java b/src/main/java/org/orekit/rugged/linesensor/SensorPixelCrossing.java index 0e972175..d3e04c8e 100644 --- a/src/main/java/org/orekit/rugged/linesensor/SensorPixelCrossing.java +++ b/src/main/java/org/orekit/rugged/linesensor/SensorPixelCrossing.java @@ -23,6 +23,7 @@ import org.apache.commons.math3.exception.NoBracketingException; import org.apache.commons.math3.exception.TooManyEvaluationsException; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.util.FastMath; +import org.orekit.rugged.errors.InverseLocOutOfColumnRangeException; import org.orekit.rugged.errors.RuggedException; import org.orekit.rugged.errors.RuggedExceptionWrapper; import org.orekit.time.AbsoluteDate; @@ -68,25 +69,27 @@ public class SensorPixelCrossing { /** Locate pixel along sensor line. * @param date current date - * @return pixel location ({@code Double.NaN} if the first and last - * pixels of the line do not bracket a location) + * @return pixel location + * @exception InverseLocOutOfColumnRangeException if the ground point is out of column range * @exception RuggedException if the maximum number of evaluations is exceeded */ - public double locatePixel(final AbsoluteDate date) throws RuggedException { - try { - - // set up function evaluating to 0.0 where target matches pixel - final UnivariateFunction f = new UnivariateFunction() { - /** {@inheritDoc} */ - @Override - public double value(final double x) throws RuggedExceptionWrapper { - try { - return Vector3D.angle(cross, getLOS(date, x)) - 0.5 * FastMath.PI; - } catch (RuggedException re) { - throw new RuggedExceptionWrapper(re); - } + public double locatePixel(final AbsoluteDate date) + throws InverseLocOutOfColumnRangeException, RuggedException { + + // set up function evaluating to 0.0 where target matches pixel + final UnivariateFunction f = new UnivariateFunction() { + /** {@inheritDoc} */ + @Override + public double value(final double x) throws RuggedExceptionWrapper { + try { + return Vector3D.angle(cross, getLOS(date, x)) - 0.5 * FastMath.PI; + } catch (RuggedException re) { + throw new RuggedExceptionWrapper(re); } - }; + } + }; + + try { // find the root final UnivariateSolver solver = @@ -94,8 +97,12 @@ public class SensorPixelCrossing { return solver.solve(maxEval, f, -MARGIN, sensor.getNbPixels() - 1 + MARGIN); } catch (NoBracketingException nbe) { - // there are no solutions in the search interval - return Double.NaN; + final int minPixel = 0; + final int maxPixel = sensor.getNbPixels() - 1; + final double fMinPixel = f.value(minPixel); + final double fMaxPixel = f.value(maxPixel); + final double expectedPixel = (fMaxPixel * minPixel - fMinPixel * maxPixel) / (fMaxPixel - fMinPixel); + throw new InverseLocOutOfColumnRangeException(expectedPixel, minPixel, maxPixel); } catch (TooManyEvaluationsException tmee) { throw new RuggedException(tmee); } catch (RuggedExceptionWrapper rew) { diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 index c65fd1b2..13a0465a 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 @@ -37,6 +37,12 @@ LINE_OF_SIGHT_NEVER_CROSSES_LONGITUDE = die Sichtverbindung kreuzt nie die Läng # line never crosses altitude {0} LINE_OF_SIGHT_NEVER_CROSSES_ALTITUDE = die Linie kreuzt nie die Höhe {0} +# ground point is around line {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_LINE_RANGE = <MISSING TRANSLATION> + +# ground point is around column {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_COLUMN_RANGE = <MISSING TRANSLATION> + # line-of-sight enters the Digital Elevation Model behind spacecraft! DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT = die Sichtverbindung tritt in das digitale Höhenlinienmodell ein, hinter dem Satellite! diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 index 7d5f68fa..63908662 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 @@ -37,6 +37,12 @@ LINE_OF_SIGHT_NEVER_CROSSES_LONGITUDE = line-of-sight never crosses longitude {0 # line never crosses altitude {0} LINE_OF_SIGHT_NEVER_CROSSES_ALTITUDE = line-of-sight never crosses altitude {0} +# ground point is around line {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_LINE_RANGE = ground point is around line {0}, out of the [{1}, {2}] range + +# ground point is around column {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_COLUMN_RANGE = ground point is around column {0}, out of the [{1}, {2}] range + # line-of-sight enters the Digital Elevation Model behind spacecraft! DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT = line-of-sight enters the Digital Elevation Model behind spacecraft! diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 index 44b53843..8490d5b7 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 @@ -37,6 +37,12 @@ LINE_OF_SIGHT_NEVER_CROSSES_LONGITUDE = la lÃnea de visión nunca atraviesa la # line never crosses altitude {0} LINE_OF_SIGHT_NEVER_CROSSES_ALTITUDE = la lÃnea de visión nunca atraviesa la altitud {0} +# ground point is around line {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_LINE_RANGE = <MISSING TRANSLATION> + +# ground point is around column {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_COLUMN_RANGE = <MISSING TRANSLATION> + # line-of-sight enters the Digital Elevation Model behind spacecraft! DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT = ¡ la lÃnea de visión entra en el Modelo Digital del Terreno por detrás del satélite ! diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 index b3e5c040..94d159f7 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 @@ -37,6 +37,12 @@ LINE_OF_SIGHT_NEVER_CROSSES_LONGITUDE = la ligne de visée ne franchit jamais la # line never crosses altitude {0} LINE_OF_SIGHT_NEVER_CROSSES_ALTITUDE = la ligne de visée ne franchit jamais l''altitude {0} +# ground point is around line {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_LINE_RANGE = le point au sol est aux alentours de la ligne {0}, hors du domaine [{1}, {2}] + +# ground point is around column {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_COLUMN_RANGE = le point au sol est aux alentours de la colonne {0}, hors du domaine [{1}, {2}] + # line-of-sight enters the Digital Elevation Model behind spacecraft! DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT = la ligne de visée entre dans le Modèle Numérique de Terrain derrière le satellite ! diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 index b927d20a..bb21a777 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 @@ -37,6 +37,12 @@ LINE_OF_SIGHT_NEVER_CROSSES_LONGITUDE = a liña de visión xamais atravesa a lon # line never crosses altitude {0} LINE_OF_SIGHT_NEVER_CROSSES_ALTITUDE = a liña de visión xamais atravesa a altitude {0} +# ground point is around line {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_LINE_RANGE = <MISSING TRANSLATION> + +# ground point is around column {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_COLUMN_RANGE = <MISSING TRANSLATION> + # line-of-sight enters the Digital Elevation Model behind spacecraft! DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT = ¡ a liña de visión entra no Modelo Dixital do Terren por detrás do satélite ! diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 index 35ae3343..12b41ac2 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 @@ -37,6 +37,12 @@ LINE_OF_SIGHT_NEVER_CROSSES_LONGITUDE = la linea di visibilità non attraversa m # line never crosses altitude {0} LINE_OF_SIGHT_NEVER_CROSSES_ALTITUDE = la linea di visibilità non attraversa mai la altitudine {0} +# ground point is around line {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_LINE_RANGE = <MISSING TRANSLATION> + +# ground point is around column {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_COLUMN_RANGE = <MISSING TRANSLATION> + # line-of-sight enters the Digital Elevation Model behind spacecraft! DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT = la linea di visibilità entra nel Modello Digitale di Suolo dietro il satellite! diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8 index 90280718..db88653a 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8 @@ -37,6 +37,12 @@ LINE_OF_SIGHT_NEVER_CROSSES_LONGITUDE = synslinjen krysser aldri lengdegrad {0} # line never crosses altitude {0} LINE_OF_SIGHT_NEVER_CROSSES_ALTITUDE = linjen krysser aldri høyden {0} +# ground point is around line {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_LINE_RANGE = <MISSING TRANSLATION> + +# ground point is around column {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_COLUMN_RANGE = <MISSING TRANSLATION> + # line-of-sight enters the Digital Elevation Model behind spacecraft! DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT = synslinjen gÃ¥r inn i den digital terrengmodellen bak romfartøyet diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8 index 900187a7..0dff443c 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8 @@ -37,6 +37,12 @@ LINE_OF_SIGHT_NEVER_CROSSES_LONGITUDE = linia de vizare nu intersectează longit # line never crosses altitude {0} LINE_OF_SIGHT_NEVER_CROSSES_ALTITUDE = linia de vizare nu intersectează altitudinea {0} +# ground point is around line {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_LINE_RANGE = <MISSING TRANSLATION> + +# ground point is around column {0}, out of the [{1}, {2}] range +GROUND_POINT_OUT_OF_COLUMN_RANGE = <MISSING TRANSLATION> + # line-of-sight enters the Digital Elevation Model behind spacecraft! DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT = linia de vizare intră în Modelul Digital de ElevaÈ›ie în spatele navei spaÈ›iale! diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml index 8f9d7f45..81c2eb35 100644 --- a/src/site/xdoc/changes.xml +++ b/src/site/xdoc/changes.xml @@ -22,6 +22,11 @@ <body> <release version="1.0" date="TBD" description="TBD"> + <action dev="luc" type="update" > + Use specific exceptions rather than returning null when inverse location identifies + out of range errors along lines or columns. This helps caller to set fix the + min/max lines as we can provide information about where the point is expected. + </action> <action dev="luc" type="add" > Added a CONSTANT_ELEVATION_OVER_ELLIPSOID algorithm, similar in spirit to the IGNORE_DEM_USE_ELLIPSOID, but with a user-specified elevation diff --git a/src/test/java/org/orekit/rugged/api/RuggedTest.java b/src/test/java/org/orekit/rugged/api/RuggedTest.java index 00252890..b82e2310 100644 --- a/src/test/java/org/orekit/rugged/api/RuggedTest.java +++ b/src/test/java/org/orekit/rugged/api/RuggedTest.java @@ -48,6 +48,8 @@ import org.orekit.frames.FramesFactory; import org.orekit.orbits.Orbit; import org.orekit.propagation.Propagator; import org.orekit.rugged.TestUtils; +import org.orekit.rugged.errors.InverseLocOutOfColumnRangeException; +import org.orekit.rugged.errors.InverseLocOutOfLineRangeException; import org.orekit.rugged.errors.RuggedException; import org.orekit.rugged.errors.RuggedMessages; import org.orekit.rugged.linesensor.LineDatation; @@ -990,32 +992,52 @@ public class RuggedTest { } // point out of line (20 pixels before first pixel) - Assert.assertNull(rugged.inverseLocation("line", + try { + rugged.inverseLocation("line", 21 * gp[0].getLatitude() - 20 * gp[1].getLatitude(), 21 * gp[0].getLongitude() - 20 * gp[1].getLongitude(), - 0, dimension)); + 0, dimension); + Assert.fail("an exception should have been thrown"); + } catch (InverseLocOutOfColumnRangeException e) { + Assert.assertEquals(-20, e.getExpectedColumn(), 1.0); + } // point out of line (20 pixels after last pixel) - Assert.assertNull(rugged.inverseLocation("line", - -20 * gp[gp.length - 2].getLatitude() + 21 * gp[gp.length - 1].getLatitude(), - -20 * gp[gp.length - 2].getLongitude() + 21 * gp[gp.length - 1].getLongitude(), - 0, dimension)); + try { + rugged.inverseLocation("line", + -20 * gp[gp.length - 2].getLatitude() + 21 * gp[gp.length - 1].getLatitude(), + -20 * gp[gp.length - 2].getLongitude() + 21 * gp[gp.length - 1].getLongitude(), + 0, dimension); + Assert.fail("an exception should have been thrown"); + } catch (InverseLocOutOfColumnRangeException e) { + Assert.assertEquals(2019.0, e.getExpectedColumn(), 1.0); + } // point out of line (20 lines before first line) GeodeticPoint[] gp0 = rugged.directLocation("line", 0); GeodeticPoint[] gp1 = rugged.directLocation("line", 1); - Assert.assertNull(rugged.inverseLocation("line", - 21 * gp0[dimension / 2].getLatitude() - 20 * gp1[dimension / 2].getLatitude(), - 21 * gp0[dimension / 2].getLongitude() - 20 * gp1[dimension / 2].getLongitude(), - 0, dimension)); + try { + rugged.inverseLocation("line", + 21 * gp0[dimension / 2].getLatitude() - 20 * gp1[dimension / 2].getLatitude(), + 21 * gp0[dimension / 2].getLongitude() - 20 * gp1[dimension / 2].getLongitude(), + 0, dimension); + Assert.fail("an exception should have been thrown"); + } catch (InverseLocOutOfLineRangeException e) { + Assert.assertEquals(-20, e.getExpectedLine(), 1.0); + } // point out of line (20 lines after last line) GeodeticPoint[] gp2 = rugged.directLocation("line", dimension - 2); GeodeticPoint[] gp3 = rugged.directLocation("line", dimension - 1); - Assert.assertNull(rugged.inverseLocation("line", - -20 * gp2[dimension / 2].getLatitude() + 21 * gp3[dimension / 2].getLatitude(), - -20 * gp2[dimension / 2].getLongitude() + 21 * gp3[dimension / 2].getLongitude(), - 0, dimension)); + try { + rugged.inverseLocation("line", + -20 * gp2[dimension / 2].getLatitude() + 21 * gp3[dimension / 2].getLatitude(), + -20 * gp2[dimension / 2].getLongitude() + 21 * gp3[dimension / 2].getLongitude(), + 0, dimension); + Assert.fail("an exception should have been thrown"); + } catch (InverseLocOutOfLineRangeException e) { + Assert.assertEquals(2019.0, e.getExpectedLine(), 1.0); + } } @@ -1082,18 +1104,28 @@ public class RuggedTest { // point out of line (20 lines before first line) GeodeticPoint[] gp0 = rugged.directLocation("line", 0); GeodeticPoint[] gp1 = rugged.directLocation("line", 1); - Assert.assertNull(rugged.dateLocation("line", - 21 * gp0[dimension / 2].getLatitude() - 20 * gp1[dimension / 2].getLatitude(), - 21 * gp0[dimension / 2].getLongitude() - 20 * gp1[dimension / 2].getLongitude(), - 0, dimension)); + try { + rugged.dateLocation("line", + 21 * gp0[dimension / 2].getLatitude() - 20 * gp1[dimension / 2].getLatitude(), + 21 * gp0[dimension / 2].getLongitude() - 20 * gp1[dimension / 2].getLongitude(), + 0, dimension); + Assert.fail("an exception should have been thrown"); + } catch (InverseLocOutOfLineRangeException e) { + Assert.assertEquals(-20.0, e.getExpectedLine(), 1.0); + } // point out of line (20 lines after last line) GeodeticPoint[] gp2 = rugged.directLocation("line", dimension - 2); GeodeticPoint[] gp3 = rugged.directLocation("line", dimension - 1); - Assert.assertNull(rugged.dateLocation("line", - -20 * gp2[dimension / 2].getLatitude() + 21 * gp3[dimension / 2].getLatitude(), - -20 * gp2[dimension / 2].getLongitude() + 21 * gp3[dimension / 2].getLongitude(), - 0, dimension)); + try { + rugged.dateLocation("line", + -20 * gp2[dimension / 2].getLatitude() + 21 * gp3[dimension / 2].getLatitude(), + -20 * gp2[dimension / 2].getLongitude() + 21 * gp3[dimension / 2].getLongitude(), + 0, dimension); + Assert.fail("an exception should have been thrown"); + } catch (InverseLocOutOfLineRangeException e) { + Assert.assertEquals(2019.0, e.getExpectedLine(), 1.0); + } } diff --git a/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java b/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java index 572a74f2..b4fa3fa0 100644 --- a/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java +++ b/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java @@ -123,4 +123,29 @@ public class DumpReplayerTest { } + @Test + public void testInverseLoc03() throws URISyntaxException, IOException, OrekitException, RuggedException { + + String orekitPath = getClass().getClassLoader().getResource("orekit-data").toURI().getPath(); + DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(new File(orekitPath))); + + String dumpPath = getClass().getClassLoader().getResource("replay/replay-inverse-loc-03.txt").toURI().getPath(); + DumpReplayer replayer = new DumpReplayer(); + replayer.parse(new File(dumpPath)); + Rugged rugged = replayer.createRugged(); + DumpReplayer.Result[] results = replayer.execute(rugged); + + Assert.assertEquals(1, results.length); + for (final DumpReplayer.Result result : results) { + RuggedException expectedSP = (RuggedException) result.getExpected(); + RuggedException replayedSP = (RuggedException) result.getReplayed(); + Assert.assertEquals(expectedSP.getSpecifier(), replayedSP.getSpecifier()); + Assert.assertEquals(expectedSP.getParts().length, replayedSP.getParts().length); + for (int i = 0; i < expectedSP.getParts().length; ++i) { + Assert.assertEquals(expectedSP.getParts()[i].toString(), replayedSP.getParts()[i].toString()); + } + } + + } + } diff --git a/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java b/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java index fa07bcf5..90afd4c3 100644 --- a/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java +++ b/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java @@ -30,7 +30,7 @@ public class RuggedMessagesTest { @Test public void testMessageNumber() { - Assert.assertEquals(25, RuggedMessages.values().length); + Assert.assertEquals(27, RuggedMessages.values().length); } @Test diff --git a/src/test/resources/replay/replay-inverse-loc-03.txt b/src/test/resources/replay/replay-inverse-loc-03.txt new file mode 100644 index 00000000..d02d1a47 --- /dev/null +++ b/src/test/resources/replay/replay-inverse-loc-03.txt @@ -0,0 +1,15 @@ +# Rugged library dump file, created on 2015-05-13T10:02:15Z +# all units are SI units (m, m/s, rad ...) +sensor: sensorName s0 nbPixels 2548 position 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 +sensor datation: sensorName s0 lineNumber 2.534400000000000e+05 date 2009-12-11T10:56:08.87816069400002Z +sensor datation: sensorName s0 lineNumber 3.456000000000000e+05 date 2009-12-11T10:58:33.19814021399996Z +inverse location: sensorName s0 latitude 8.744540902932477e-01 longitude 8.223965816103829e-02 elevation 1.932387539216973e+02 minLine 253440 maxLine 345600 lightTime false aberration false +sensor mean plane: sensorName s0 minLine 253440 maxLine 345600 maxEval 50 accuracy 1.000000000000000e-02 normal 9.992992685324403e-01 3.581342262283560e-02 1.087982860931817e-02 cachedResults 0 +sensor datation: sensorName s0 lineNumber 2.995200000000000e+05 date 2009-12-11T10:57:21.03815045399999Z +span: minDate 2009-12-11T10:49:31.00000000000000Z maxDate 2009-12-11T11:03:30.00000000000000Z tStep 1.000000000000000e-01 tolerance 1.000000000000000e+01 inertialFrame EME2000 +transform: index 4700 body r 5.336117270046078e-01 4.251589590898946e-04 -2.597710250850116e-04 8.457294346078028e-01 Ω -7.257892947630780e-08 -1.030887896243645e-09 -7.292111453494791e-05 ΩDot -1.960038458846624e-16 2.118427550826115e-16 1.921009249184302e-19 spacecraft p -2.053168038837612e-01 -4.479465554468334e-01 -7.157555881515884e+06 v -6.899290198987784e-02 -3.025941225892836e-02 -5.079406124814291e+00 a 3.805095952731160e-01 5.497720860602762e-01 -8.918837042129590e-03 r -2.219560290614089e-01 -4.227878241169732e-01 8.530519262360150e-01 2.104480650582249e-01 Ω -8.821450598425838e-04 5.190249503929784e-04 2.032835938889824e-04 ΩDot -4.852855703503804e-08 -1.727683064915104e-07 -5.843961481065110e-09 +ellipsoid: ae 6.378137000000000e+06 f 3.352810664747481e-03 frame ITRF_CIO_CONV_2010_SIMPLE_EOP +sensor rate: sensorName s0 lineNumber 2.995200000000000e+05 rate 6.385810218828944e+02 +transform: index 5422 body r 5.358362189638148e-01 4.244746734277517e-04 -2.608866680050883e-04 8.443217977797100e-01 Ω -7.257894362971709e-08 -1.030872599745237e-09 -7.292111453507905e-05 ΩDot -1.960533569532405e-16 2.118830189595701e-16 1.921497489163665e-19 spacecraft p -2.077100353781134e-01 -5.937387477606535e-01 -7.157941245109990e+06 v -2.079879880167868e-02 6.790481151207040e-02 -5.590344257542220e+00 a 2.559067822717660e-01 1.523619888721470e+00 -6.690495582427680e-03 r -2.527575739550456e-01 -4.131723819265151e-01 8.446513348497744e-01 2.279612119594559e-01 Ω -8.835025599828953e-04 5.181159787201125e-04 1.981184601497435e-04 ΩDot -4.833822353095120e-08 -2.339809966148790e-08 -3.757527734431237e-07 +sensor rate: sensorName s0 lineNumber 3.456000000000000e+05 rate 6.385810218828944e+02 +Rugged exception: specifier GROUND_POINT_OUT_OF_LINE_RANGE parts 345933.8595532291 253440 345600 -- GitLab