diff --git a/src/main/java/org/orekit/rugged/api/Rugged.java b/src/main/java/org/orekit/rugged/api/Rugged.java index 0f17428c2802d3a77c895d947b7964c4d0a9d0f1..3d20e823fdc2e33d244355e4aeb58d1ea6c37ea9 100644 --- a/src/main/java/org/orekit/rugged/api/Rugged.java +++ b/src/main/java/org/orekit/rugged/api/Rugged.java @@ -384,21 +384,7 @@ public class Rugged { throws RuggedException { final LineSensor sensor = getLineSensor(sensorName); - SensorMeanPlaneCrossing planeCrossing = finders.get(sensorName); - if (planeCrossing == null || - planeCrossing.getMinLine() != minLine || - planeCrossing.getMaxLine() != maxLine) { - - // create a new finder for the specified sensor and range - planeCrossing = new SensorMeanPlaneCrossing(sensor, scToBody, minLine, maxLine, - lightTimeCorrection, aberrationOfLightCorrection, - MAX_EVAL, COARSE_INVERSE_LOCATION_ACCURACY); - - // store the finder, in order to reuse it - // (and save some computation done in its constructor) - finders.put(sensorName, planeCrossing); - - } + 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); @@ -449,22 +435,14 @@ public class Rugged { final int minLine, final int maxLine) throws RuggedException { - final LineSensor sensor = getLineSensor(sensorName); - SensorMeanPlaneCrossing planeCrossing = finders.get(sensorName); - if (planeCrossing == null || - planeCrossing.getMinLine() != minLine || - planeCrossing.getMaxLine() != maxLine) { - - // create a new finder for the specified sensor and range - planeCrossing = new SensorMeanPlaneCrossing(sensor, scToBody, minLine, maxLine, - lightTimeCorrection, aberrationOfLightCorrection, - MAX_EVAL, COARSE_INVERSE_LOCATION_ACCURACY); + DumpManager.dumpInverseLocation(sensorName, point, minLine, maxLine, + lightTimeCorrection, aberrationOfLightCorrection); - // store the finder, in order to reuse it - // (and save some computation done in its constructor) - finders.put(sensorName, planeCrossing); + final LineSensor sensor = getLineSensor(sensorName); + final SensorMeanPlaneCrossing planeCrossing = getPlaneCrossing(sensorName, minLine, maxLine); - } + DumpManager.dumpSensor(sensor); + DumpManager.dumpSensorMeanPlane(planeCrossing); // find approximately the sensor line at which ground point crosses sensor mean plane final Vector3D target = ellipsoid.transform(point); @@ -511,8 +489,51 @@ public class Rugged { Vector3D.dotProduct(fixedDirection, fixedX)); final double fixedPixel = lowIndex + alpha / pixelWidth; - return new SensorPixel(fixedLine, fixedPixel); + final SensorPixel result = new SensorPixel(fixedLine, fixedPixel); + DumpManager.dumpInverseLocationResult(result); + return result; + + } + + /** Get the mean plane crossing finder for a sensor. + * @param sensorName name of the line sensor + * @param minLine minimum line number + * @param maxLine maximum line number + * @return mean plane crossing finder + * @exception RuggedException if sensor is unknown + */ + private SensorMeanPlaneCrossing getPlaneCrossing(final String sensorName, + final int minLine, final int maxLine) + throws RuggedException { + final LineSensor sensor = getLineSensor(sensorName); + SensorMeanPlaneCrossing planeCrossing = finders.get(sensorName); + if (planeCrossing == null || + planeCrossing.getMinLine() != minLine || + planeCrossing.getMaxLine() != maxLine) { + + // create a new finder for the specified sensor and range + planeCrossing = new SensorMeanPlaneCrossing(sensor, scToBody, minLine, maxLine, + lightTimeCorrection, aberrationOfLightCorrection, + MAX_EVAL, COARSE_INVERSE_LOCATION_ACCURACY); + + // store the finder, in order to reuse it + // (and save some computation done in its constructor) + setPlaneCrossing(planeCrossing); + + } + + return planeCrossing; + + } + + /** Set the mean plane crossing finder for a sensor. + * @param planeCrossing plane crossing finder + * @exception RuggedException if sensor is unknown + */ + private void setPlaneCrossing(final SensorMeanPlaneCrossing planeCrossing) + throws RuggedException { + finders.put(planeCrossing.getSensor().getName(), planeCrossing); } /** Get transform from spacecraft to inertial frame. diff --git a/src/main/java/org/orekit/rugged/errors/Dump.java b/src/main/java/org/orekit/rugged/errors/Dump.java index a24e5ed40928728932976df23d7f2227bd98e786..003018fe84f5ce138c6320e8138b9326648782e6 100644 --- a/src/main/java/org/orekit/rugged/errors/Dump.java +++ b/src/main/java/org/orekit/rugged/errors/Dump.java @@ -33,6 +33,9 @@ import org.orekit.frames.FactoryManagedFrame; import org.orekit.frames.Frame; import org.orekit.frames.Transform; import org.orekit.rugged.api.AlgorithmId; +import org.orekit.rugged.linesensor.LineSensor; +import org.orekit.rugged.linesensor.SensorMeanPlaneCrossing; +import org.orekit.rugged.linesensor.SensorPixel; import org.orekit.rugged.raster.Tile; import org.orekit.rugged.utils.ExtendedEllipsoid; import org.orekit.rugged.utils.SpacecraftToObservedBody; @@ -49,9 +52,15 @@ class Dump { /** Dump file. */ private final PrintWriter writer; - /** Tiles map. */ + /** Tiles list. */ private final List<DumpedTileData> tiles; + /** Already dumped sensors. */ + private final List<String> sensors; + + /** Already dumped sensors mean planes. */ + private final List<String> meanPlanes; + /** Flag for dumped algorithm. */ private boolean algorithmDumped; @@ -67,6 +76,8 @@ class Dump { public Dump(final PrintWriter writer) { this.writer = writer; this.tiles = new ArrayList<DumpedTileData>(); + this.sensors = new ArrayList<String>(); + this.meanPlanes = new ArrayList<String>(); this.algorithmDumped = false; this.ellipsoidDumped = false; this.tranformsDumped = null; @@ -165,6 +176,36 @@ class Dump { } } + /** Dump an inverse location computation. + * @param sensorName name of the line sensor + * @param point point to localize + * @param minLine minimum line number + * @param maxLine maximum line number + * @param lightTimeCorrection flag for light time correction + * @param aberrationOfLightCorrection flag for aberration of light correction + */ + public void dumpInverseLocation(final String sensorName, final GeodeticPoint point, + final int minLine, final int maxLine, + final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection) { + writer.format(Locale.US, + "inverse location: sensorName %s latitude %22.15e longitude %22.15e elevation %22.15e minLine %d maxLine %d lightTime %b aberration %b%n", + sensorName, + point.getLatitude(), point.getLongitude(), point.getAltitude(), + minLine, maxLine, + lightTimeCorrection, aberrationOfLightCorrection); + } + + /** Dump an inverse location result. + * @param pixel resulting sensor pixel + */ + public void dumpInverseLocationResult(final SensorPixel pixel) { + if (pixel != null) { + writer.format(Locale.US, + "inverse location result: lineNumber %22.15e pixelNumber %22.15e%n", + pixel.getLineNumber(), pixel.getPixelNumber()); + } + } + /** Dump an observation transform transform. * @param scToBody provider for observation * @param index index of the transform @@ -198,6 +239,94 @@ class Dump { } } + /** Dump a sensor. + * @param sensor sensor to dump + */ + public void dumpSensor(final LineSensor sensor) { + if (!sensors.contains(sensor.getName())) { + writer.format(Locale.US, + "sensor: sensorName %s nbPixels %d position %22.15e %22.15e %22.15e%n", + sensor.getName(), sensor.getNbPixels(), + sensor.getPosition().getX(), sensor.getPosition().getY(), sensor.getPosition().getZ()); + sensors.add(sensor.getName()); + } + } + + /** Dump a sensor mean plane. + * @param meanPlane mean plane associated with sensor + * @exception RuggedException if some frames cannot be computed at mid date + */ + public void dumpSensorMeanPlane(final SensorMeanPlaneCrossing meanPlane) + throws RuggedException { + if (!meanPlanes.contains(meanPlane.getSensor().getName())) { + writer.format(Locale.US, + "sensor mean plane: sensorName %s minLine %d maxLine %d maxEval %d accuracy %22.15e normal %22.15e %22.15e %22.15e%n", + meanPlane.getSensor().getName(), + meanPlane.getMinLine(), meanPlane.getMaxLine(), + meanPlane.getMaxEval(), meanPlane.getAccuracy(), + meanPlane.getMeanPlaneNormal().getX(), meanPlane.getMeanPlaneNormal().getY(), meanPlane.getMeanPlaneNormal().getZ()); + + // ensure the transforms for mid date are dumped + final AbsoluteDate midDate = meanPlane.getSensor().getDate(0.5 * (meanPlane.getMinLine() + meanPlane.getMaxLine())); + meanPlane.getScToBody().getBodyToInertial(midDate); + meanPlane.getScToBody().getScToInertial(midDate); + + meanPlanes.add(meanPlane.getSensor().getName()); + + } + } + + /** Dump a sensor LOS. + * @param name sensor name + * @param date date + * @param i pixel index + * @param los pixel normalized line-of-sight + * @exception RuggedException if date cannot be converted to UTC + */ + public void dumpSensorLOS(final String name, final AbsoluteDate date, final int i, final Vector3D los) + throws RuggedException { + writer.format(Locale.US, + "sensor LOS: sensorName %s date %s pixelNumber %d => %22.15e %22.15e %22.15e%n", + name, convertDate(date), i, los.getX(), los.getY(), los.getZ()); + } + + /** Dump a sensor date. + * @param name sensor name + * @param lineNumber line number + * @param date date + * @exception RuggedException if date cannot be converted to UTC + */ + public void dumpSensorDate(final String name, final double lineNumber, final AbsoluteDate date) + throws RuggedException { + writer.format(Locale.US, + "sensor date: sensorName %s lineNumber %22.15e => %s%n", + name, lineNumber, convertDate(date)); + } + + /** Dump a sensor line. + * @param name sensor name + * @param date date + * @param lineNumber line number + * @exception RuggedException if date cannot be converted to UTC + */ + public void dumpSensorLine(final String name, final AbsoluteDate date, final double lineNumber) + throws RuggedException { + writer.format(Locale.US, + "sensor line: sensorName %s date => %22.15e%n", + name, convertDate(date), lineNumber); + } + + /** Dump a sensor rate. + * @param name sensor name + * @param lineNumber line number + * @param rate lines rate + */ + public void dumpSensorRate(final String name, final double lineNumber, final double rate) { + writer.format(Locale.US, + "sensor rate: sensorName %s lineNumber %s => %22.15e%n", + name, lineNumber, rate); + } + /** Get a frame key or name. * @param frame frame to convert * @return frame key or name diff --git a/src/main/java/org/orekit/rugged/errors/DumpManager.java b/src/main/java/org/orekit/rugged/errors/DumpManager.java index 1d5afe652b5936f600e14b2ce5a40977a9829a0a..b49e7a88d83afad29073a6e10c3b33bad639eb64 100644 --- a/src/main/java/org/orekit/rugged/errors/DumpManager.java +++ b/src/main/java/org/orekit/rugged/errors/DumpManager.java @@ -24,6 +24,9 @@ import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.orekit.bodies.GeodeticPoint; import org.orekit.frames.Transform; import org.orekit.rugged.api.AlgorithmId; +import org.orekit.rugged.linesensor.LineSensor; +import org.orekit.rugged.linesensor.SensorMeanPlaneCrossing; +import org.orekit.rugged.linesensor.SensorPixel; import org.orekit.rugged.raster.Tile; import org.orekit.rugged.utils.ExtendedEllipsoid; import org.orekit.rugged.utils.SpacecraftToObservedBody; @@ -157,6 +160,32 @@ public class DumpManager { } } + /** Dump an inverse location computation. + * @param sensorName name of the line sensor + * @param point point to localize + * @param minLine minimum line number + * @param maxLine maximum line number + * @param lightTimeCorrection flag for light time correction + * @param aberrationOfLightCorrection flag for aberration of light correction + */ + public static void dumpInverseLocation(final String sensorName, final GeodeticPoint point, + final int minLine, final int maxLine, + final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection) { + if (isActive()) { + DUMP.get().dumpInverseLocation(sensorName, point, minLine, maxLine, + lightTimeCorrection, aberrationOfLightCorrection); + } + } + + /** Dump an inverse location result. + * @param pixel resulting sensor pixel + */ + public static void dumpInverseLocationResult(final SensorPixel pixel) { + if (isActive()) { + DUMP.get().dumpInverseLocationResult(pixel); + } + } + /** Dump an observation transform transform. * @param scToBody provider for observation * @param index index of the transform @@ -172,4 +201,75 @@ public class DumpManager { } } + /** Dump a sensor. + * @param sensor sensor to dump + */ + public static void dumpSensor(final LineSensor sensor) { + if (isActive()) { + DUMP.get().dumpSensor(sensor); + } + } + + /** Dump a sensor mean plane. + * @param meanPlane mean plane associated with sensor + * @exception RuggedException if some frames cannot be computed at mid date + */ + public static void dumpSensorMeanPlane(final SensorMeanPlaneCrossing meanPlane) + throws RuggedException { + if (isActive()) { + DUMP.get().dumpSensorMeanPlane(meanPlane); + } + } + + /** Dump a sensor LOS. + * @param name sensor name + * @param date date + * @param i pixel index + * @param los pixel normalized line-of-sight + * @exception RuggedException if date cannot be converted to UTC + */ + public static void dumpSensorLOS(final String name, final AbsoluteDate date, final int i, final Vector3D los) + throws RuggedException { + if (isActive()) { + DUMP.get().dumpSensorLOS(name, date, i, los); + } + } + + /** Dump a sensor date. + * @param name sensor name + * @param lineNumber line number + * @param date date + * @exception RuggedException if date cannot be converted to UTC + */ + public static void dumpSensorDate(final String name, final double lineNumber, final AbsoluteDate date) + throws RuggedException { + if (isActive()) { + DUMP.get().dumpSensorDate(name, lineNumber, date); + } + } + + /** Dump a sensor line. + * @param name sensor name + * @param date date + * @param lineNumber line number + * @exception RuggedException if date cannot be converted to UTC + */ + public static void dumpSensorLine(final String name, final AbsoluteDate date, final double lineNumber) + throws RuggedException { + if (isActive()) { + DUMP.get().dumpSensorLine(name, date, lineNumber); + } + } + + /** Dump a sensor rate. + * @param name sensor name + * @param lineNumber line number + * @param rate lines rate + */ + public static void dumpSensorRate(final String name, final double lineNumber, final double rate) { + if (isActive()) { + DUMP.get().dumpSensorRate(name, lineNumber, rate); + } + } + } diff --git a/src/main/java/org/orekit/rugged/errors/DumpReplayer.java b/src/main/java/org/orekit/rugged/errors/DumpReplayer.java index 589a63f69c208cd0dbe5b200a2ac2aea4594517c..f38f9545a67455d3cf7f46b3250a24d7a9f5afd0 100644 --- a/src/main/java/org/orekit/rugged/errors/DumpReplayer.java +++ b/src/main/java/org/orekit/rugged/errors/DumpReplayer.java @@ -24,17 +24,23 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectOutputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NavigableMap; import java.util.TreeMap; +import org.apache.commons.math3.analysis.differentiation.DerivativeStructure; 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; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.util.FastMath; import org.apache.commons.math3.util.OpenIntToDoubleHashMap; +import org.apache.commons.math3.util.Pair; import org.orekit.bodies.GeodeticPoint; import org.orekit.bodies.OneAxisEllipsoid; import org.orekit.errors.OrekitException; @@ -45,6 +51,11 @@ import org.orekit.frames.Transform; import org.orekit.rugged.api.AlgorithmId; import org.orekit.rugged.api.Rugged; import org.orekit.rugged.api.RuggedBuilder; +import org.orekit.rugged.linesensor.LineDatation; +import org.orekit.rugged.linesensor.LineSensor; +import org.orekit.rugged.linesensor.SensorMeanPlaneCrossing; +import org.orekit.rugged.linesensor.SensorPixel; +import org.orekit.rugged.los.TimeDependentLOS; import org.orekit.rugged.raster.TileUpdater; import org.orekit.rugged.raster.UpdatableTile; import org.orekit.rugged.utils.SpacecraftToObservedBody; @@ -160,6 +171,36 @@ public class DumpReplayer { /** Keyword for longitude index fields. */ private static final String LON_INDEX = "lonIndex"; + /** Keyword for sensor name. */ + private static final String SENSOR_NAME = "sensorName"; + + /** Keyword for min line. */ + private static final String MIN_LINE = "minLine"; + + /** Keyword for max line. */ + private static final String MAX_LINE = "maxLine"; + + /** Keyword for line number. */ + private static final String LINE_NUMBER = "lineNumber"; + + /** Keyword for number of pixels. */ + private static final String NB_PIXELS = "nbPixels"; + + /** Keyword for pixel number. */ + private static final String PIXEL_NUMBER = "pixelNumber"; + + /** Keyword for max number of evaluations. */ + private static final String MAX_EVAL = "maxEval"; + + /** Keyword for accuracy. */ + private static final String ACCURACY = "accuracy"; + + /** Keyword for normal. */ + private static final String NORMAL = "normal"; + + /** Keyword for return arrow. */ + private static final String RETURN_ARROW = "=>"; + /** Constant elevation for constant elevation algorithm. */ private double constantElevation; @@ -169,9 +210,12 @@ public class DumpReplayer { /** Ellipsoid. */ private OneAxisEllipsoid ellipsoid; - /** Tiles map. */ + /** Tiles list. */ private final List<ParsedTile> tiles; + /** Sensors list. */ + private final List<ParsedSensor> sensors; + /** Interpolator min date. */ private AbsoluteDate minDate; @@ -205,8 +249,9 @@ public class DumpReplayer { /** Simple constructor. */ public DumpReplayer() { - tiles = new ArrayList<ParsedTile>(); - calls = new ArrayList<DumpedCall>(); + tiles = new ArrayList<ParsedTile>(); + sensors = new ArrayList<ParsedSensor>(); + calls = new ArrayList<DumpedCall>(); } /** Parse a dump file. @@ -235,6 +280,9 @@ public class DumpReplayer { try { final RuggedBuilder builder = new RuggedBuilder(); + if (algorithmId == null) { + algorithmId = AlgorithmId.IGNORE_DEM_USE_ELLIPSOID; + } builder.setAlgorithm(algorithmId); if (algorithmId == AlgorithmId.CONSTANT_ELEVATION_OVER_ELLIPSOID) { builder.setConstantElevation(constantElevation); @@ -291,20 +339,63 @@ public class DumpReplayer { // we use Rugged transforms reloading mechanism to ensure the spacecraft // to body transforms will be the same as the ones dumped - final SpacecraftToObservedBody sc2Body = + final SpacecraftToObservedBody scToBody = new SpacecraftToObservedBody(inertialFrame, ellipsoid.getBodyFrame(), minDate, maxDate, tStep, tolerance, b2iList, s2iList); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - new ObjectOutputStream(bos).writeObject(sc2Body); + new ObjectOutputStream(bos).writeObject(scToBody); final ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); builder.setTrajectoryAndTimeSpan(bis); - return builder.build(); + final List<SensorMeanPlaneCrossing> planeCrossings = new ArrayList<SensorMeanPlaneCrossing>(); + for (final ParsedSensor parsedSensor : sensors) { + final LineSensor sensor = new LineSensor(parsedSensor.name, + parsedSensor, + parsedSensor.position, + parsedSensor); + if (parsedSensor.meanPlane != null) { + planeCrossings.add(new SensorMeanPlaneCrossing(sensor, scToBody, + parsedSensor.meanPlane.minLine, + parsedSensor.meanPlane.maxLine, + lightTimeCorrection, aberrationOfLightCorrection, + parsedSensor.meanPlane.maxEval, + parsedSensor.meanPlane.accuracy, + parsedSensor.meanPlane.normal)); + } + builder.addLineSensor(sensor); + } + + final Rugged rugged = builder.build(); + + final Method setPlaneCrossing = Rugged.class.getDeclaredMethod("setPlaneCrossing", + SensorMeanPlaneCrossing.class); + setPlaneCrossing.setAccessible(true); + for (final SensorMeanPlaneCrossing planeCrossing : planeCrossings) { + setPlaneCrossing.invoke(rugged, planeCrossing); + } + + return rugged; } catch (IOException ioe) { throw new RuggedException(ioe, LocalizedFormats.SIMPLE_MESSAGE, ioe.getLocalizedMessage()); + } catch (SecurityException e) { + // this should never happen + throw RuggedException.createInternalError(e); + } catch (NoSuchMethodException e) { + // this should never happen + throw RuggedException.createInternalError(e); + } catch (IllegalArgumentException e) { + // this should never happen + throw RuggedException.createInternalError(e); + } catch (IllegalAccessException e) { + // this should never happen + throw RuggedException.createInternalError(e); + } catch (InvocationTargetException e) { + // this should never happen + throw RuggedException.createInternalError(e); } + } /** Execute all dumped calls. @@ -630,6 +721,254 @@ public class DumpReplayer { name, l, file.getAbsolutePath(), line); } + }, + + /** Parser for inverse location calls dump lines. */ + INVERSE_LOCATION() { + + /** {@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 < 16 || + !fields[0].equals(SENSOR_NAME) || + !fields[2].equals(LATITUDE) || !fields[4].equals(LONGITUDE) || !fields[6].equals(ELEVATION) || + !fields[8].equals(MIN_LINE) || !fields[10].equals(MAX_LINE) || + !fields[12].equals(LIGHT_TIME) || !fields[14].equals(ABERRATION)) { + throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); + } + final String sensorName = fields[1]; + final GeodeticPoint point = new GeodeticPoint(Double.parseDouble(fields[3]), + Double.parseDouble(fields[5]), + Double.parseDouble(fields[7])); + final int minLine = Integer.parseInt(fields[9]); + final int maxLine = Integer.parseInt(fields[11]); + if (global.calls.isEmpty()) { + global.lightTimeCorrection = Boolean.parseBoolean(fields[11]); + global.aberrationOfLightCorrection = Boolean.parseBoolean(fields[13]); + } else { + if (global.lightTimeCorrection != Boolean.parseBoolean(fields[11])) { + throw new RuggedException(RuggedMessages.LIGHT_TIME_CORRECTION_REDEFINED, + l, file.getAbsolutePath(), line); + } + if (global.aberrationOfLightCorrection != Boolean.parseBoolean(fields[13])) { + throw new RuggedException(RuggedMessages.ABERRATION_OF_LIGHT_CORRECTION_REDEFINED, + l, file.getAbsolutePath(), line); + } + } + global.calls.add(new DumpedCall() { + + /** {@inheritDoc} */ + @Override + public Object execute(final Rugged rugged) throws RuggedException { + return rugged.inverseLocation(sensorName, point, minLine, maxLine); + } + + }); + } + + }, + + /** Parser for inverse location result dump lines. */ + INVERSE_LOCATION_RESULT() { + + /** {@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 < 4 || !fields[0].equals(LINE_NUMBER) || !fields[2].equals(PIXEL_NUMBER)) { + throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); + } + final SensorPixel sp = new SensorPixel(Double.parseDouble(fields[1]), + Double.parseDouble(fields[3])); + final DumpedCall last = global.calls.get(global.calls.size() - 1); + last.expected = sp; + } + + }, + + /** Parser for sensor dump lines. */ + SENSOR() { + + /** {@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 < 8 || !fields[0].equals(SENSOR_NAME) || + !fields[2].equals(NB_PIXELS) || !fields[4].equals(POSITION)) { + throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); + } + final String sensorName = fields[1]; + final int nbPixels = Integer.parseInt(fields[3]); + final Vector3D position = new Vector3D(Double.parseDouble(fields[5]), + Double.parseDouble(fields[6]), + Double.parseDouble(fields[7])); + for (final ParsedSensor sensor : global.sensors) { + if (sensor.name.equals(sensorName)) { + throw new RuggedException(RuggedMessages.SENSOR_ALREADY_DEFINED, + sensorName, l, file.getAbsolutePath(), line); + } + } + global.sensors.add(new ParsedSensor(sensorName, nbPixels, position)); + } + + }, + + /** Parser for sensor mean plane dump lines. */ + SENSOR_MEAN_PLANE() { + + /** {@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 < 14 || !fields[0].equals(SENSOR_NAME) || + !fields[2].equals(MIN_LINE) || !fields[4].equals(MAX_LINE) || + !fields[6].equals(MAX_EVAL) || !fields[8].equals(ACCURACY) || + !fields[10].equals(NORMAL)) { + throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); + } + final String sensorName = fields[1]; + final int minLine = Integer.parseInt(fields[3]); + final int maxLine = Integer.parseInt(fields[5]); + final int maxEval = Integer.parseInt(fields[7]); + final double accuracy = Double.parseDouble(fields[9]); + final Vector3D normal = new Vector3D(Double.parseDouble(fields[11]), + Double.parseDouble(fields[12]), + Double.parseDouble(fields[13])); + for (final ParsedSensor sensor : global.sensors) { + if (sensor.name.equals(sensorName)) { + sensor.meanPlane = new ParsedMeanPlane(minLine, maxLine, maxEval, accuracy, normal); + return; + } + } + + throw new RuggedException(RuggedMessages.UNKNOWN_SENSOR, sensorName); + + } + + }, + + /** Parser for sensor LOS dump lines. */ + SENSOR_LOS() { + + /** {@inheritDoc} */ + @Override + public void parse(final int l, final File file, final String line, final String[] fields, final DumpReplayer global) + throws RuggedException { + try { + if (fields.length < 10 || !fields[0].equals(SENSOR_NAME) || + !fields[2].equals(DATE) || !fields[4].equals(PIXEL_NUMBER) || + !fields[6].equals(RETURN_ARROW)) { + throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); + } + final String sensorName = fields[1]; + final AbsoluteDate date = new AbsoluteDate(fields[3], TimeScalesFactory.getUTC()); + final int pixelNumber = Integer.parseInt(fields[5]); + final Vector3D los = new Vector3D(Double.parseDouble(fields[7]), + Double.parseDouble(fields[8]), + Double.parseDouble(fields[9])); + for (final ParsedSensor sensor : global.sensors) { + if (sensor.name.equals(sensorName)) { + sensor.setLOS(date, pixelNumber, los); + return; + } + } + + throw new RuggedException(RuggedMessages.UNKNOWN_SENSOR, sensorName); + } catch (OrekitException oe) { + throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); + } + } + + }, + + /** Parser for sensor date dump lines. */ + SENSOR_DATE() { + + /** {@inheritDoc} */ + @Override + public void parse(final int l, final File file, final String line, final String[] fields, final DumpReplayer global) + throws RuggedException { + try { + if (fields.length < 5 || !fields[0].equals(SENSOR_NAME) || + !fields[2].equals(LINE_NUMBER) || !fields[4].equals(RETURN_ARROW)) { + throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); + } + final String sensorName = fields[1]; + final double lineNumber = Double.parseDouble(fields[3]); + final AbsoluteDate date = new AbsoluteDate(fields[5], TimeScalesFactory.getUTC()); + for (final ParsedSensor sensor : global.sensors) { + if (sensor.name.equals(sensorName)) { + sensor.setDatation(lineNumber, date); + return; + } + } + + throw new RuggedException(RuggedMessages.UNKNOWN_SENSOR, sensorName); + } catch (OrekitException oe) { + throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); + } + + } + + }, + + /** Parser for sensor line dump lines. */ + SENSOR_LINE() { + + /** {@inheritDoc} */ + @Override + public void parse(final int l, final File file, final String line, final String[] fields, final DumpReplayer global) + throws RuggedException { + try { + if (fields.length < 10 || !fields[0].equals(SENSOR_NAME) || + !fields[2].equals(LINE_NUMBER) || !fields[4].equals(RETURN_ARROW)) { + throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); + } + final String sensorName = fields[1]; + final AbsoluteDate date = new AbsoluteDate(fields[3], TimeScalesFactory.getUTC()); + final double lineNumber = Double.parseDouble(fields[5]); + for (final ParsedSensor sensor : global.sensors) { + if (sensor.name.equals(sensorName)) { + sensor.setDatation(lineNumber, date); + return; + } + } + + throw new RuggedException(RuggedMessages.UNKNOWN_SENSOR, sensorName); + } catch (OrekitException oe) { + throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); + } + + } + + }, + + /** Parser for sensor rate dump lines. */ + SENSOR_RATE() { + + /** {@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 < 5 || !fields[0].equals(SENSOR_NAME) || + !fields[2].equals(LINE_NUMBER) || !fields[4].equals(RETURN_ARROW)) { + throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); + } + final String sensorName = fields[1]; + final double lineNumber = Double.parseDouble(fields[3]); + final double rate = Double.parseDouble(fields[5]); + for (final ParsedSensor sensor : global.sensors) { + if (sensor.name.equals(sensorName)) { + sensor.setRate(lineNumber, rate); + return; + } + } + + throw new RuggedException(RuggedMessages.UNKNOWN_SENSOR, sensorName); + + } + }; /** Parse a line. @@ -652,7 +991,7 @@ public class DumpReplayer { final String parsedKey = line.substring(0, colon).trim().replaceAll(" ", "_").toUpperCase(); try { final LineParser parser = LineParser.valueOf(parsedKey); - parser.parse(colon, file, line, line.substring(colon + 1).trim().split("\\s+"), global); + parser.parse(l, file, line, line.substring(colon + 1).trim().split("\\s+"), global); } catch (IllegalArgumentException iae) { throw new RuggedException(RuggedMessages.CANNOT_PARSE_LINE, l, file, line); } @@ -761,6 +1100,201 @@ public class DumpReplayer { } + /** Local class for handling already parsed sensor data. */ + private static class ParsedSensor implements LineDatation, TimeDependentLOS { + + /** Name of the sensor. */ + private final String name; + + /** Number of pixels. */ + private final int nbPixels; + + /** Position. */ + private final Vector3D position; + + /** Mean plane crossing finder. */ + private ParsedMeanPlane meanPlane; + + /** LOS map. */ + private final Map<Integer, List<Pair<AbsoluteDate, Vector3D>>> losMap; + + /** Datation. */ + private final List<Pair<Double, AbsoluteDate>> datation; + + /** Rate. */ + private final List<Pair<Double, Double>> rates; + + /** simple constructor. + * @param name name of the sensor + * @param nbPixels number of pixels + * @param position position + */ + public ParsedSensor(final String name, final int nbPixels, final Vector3D position) { + this.name = name; + this.nbPixels = nbPixels; + this.position = position; + this.losMap = new HashMap<Integer, List<Pair<AbsoluteDate, Vector3D>>>(); + this.datation = new ArrayList<Pair<Double, AbsoluteDate>>(); + this.rates = new ArrayList<Pair<Double, Double>>(); + } + + /** {@inheritDoc} */ + @Override + public int getNbEstimatedParameters() { + return 0; + } + + /** {@inheritDoc} */ + @Override + public void getEstimatedParameters(final double[] parameters, final int start, final int length) + throws RuggedException { + } + + /** {@inheritDoc} */ + @Override + public void setEstimatedParameters(final double[] parameters, final int start, final int length) + throws RuggedException { + } + + /** {@inheritDoc} */ + @Override + public int getNbPixels() { + return nbPixels; + } + + /** Set a los direction. + * @param date date + * @param pixelNumber number of the pixel + * @param los los direction + */ + public void setLOS(final AbsoluteDate date, final int pixelNumber, final Vector3D los) { + List<Pair<AbsoluteDate, Vector3D>> list = losMap.get(pixelNumber); + if (list == null) { + list = new ArrayList<Pair<AbsoluteDate, Vector3D>>(); + losMap.put(pixelNumber, list); + } + list.add(new Pair<AbsoluteDate, Vector3D>(date, los)); + } + + /** {@inheritDoc} */ + @Override + public Vector3D getLOS(final int index, final AbsoluteDate date) { + final List<Pair<AbsoluteDate, Vector3D>> list = losMap.get(index); + if (list == null) { + throw RuggedException.createInternalError(null); + } + int selected = 0; + for (int i = 0; i < list.size(); ++i) { + if (FastMath.abs(list.get(i).getFirst().durationFrom(date)) < + FastMath.abs(list.get(selected).getFirst().durationFrom(date))) { + selected = i; + } + } + return list.get(selected).getSecond(); + } + + /** {@inheritDoc} */ + @Override + public FieldVector3D<DerivativeStructure> getLOS(final int index, final AbsoluteDate date, final double[] parameters) { + final Vector3D los = getLOS(index, date); + return new FieldVector3D<DerivativeStructure>(new DerivativeStructure(parameters.length, 1, los.getX()), + new DerivativeStructure(parameters.length, 1, los.getY()), + new DerivativeStructure(parameters.length, 1, los.getZ())); + } + + /** Set a datation pair. + * @param lineNumber line number + * @param date date + */ + public void setDatation(final double lineNumber, final AbsoluteDate date) { + datation.add(new Pair<Double, AbsoluteDate>(lineNumber, date)); + } + + /** {@inheritDoc} */ + @Override + public AbsoluteDate getDate(final double lineNumber) { + int selected = 0; + for (int i = 0; i < datation.size(); ++i) { + if (FastMath.abs(datation.get(i).getFirst() - lineNumber) < + FastMath.abs(datation.get(selected).getFirst() - lineNumber)) { + selected = i; + } + } + return datation.get(selected).getSecond(); + } + + /** {@inheritDoc} */ + @Override + public double getLine(final AbsoluteDate date) { + int selected = 0; + for (int i = 0; i < datation.size(); ++i) { + if (FastMath.abs(datation.get(i).getSecond().durationFrom(date)) < + FastMath.abs(datation.get(selected).getSecond().durationFrom(date))) { + selected = i; + } + } + return datation.get(selected).getFirst(); + } + + /** Set a rate. + * @param lineNumber line number + * @param rate lines rate + */ + public void setRate(final double lineNumber, final double rate) { + rates.add(new Pair<Double, Double>(lineNumber, rate)); + } + + /** {@inheritDoc} */ + @Override + public double getRate(final double lineNumber) { + int selected = 0; + for (int i = 0; i < rates.size(); ++i) { + if (FastMath.abs(rates.get(i).getFirst() - lineNumber) < + FastMath.abs(rates.get(selected).getFirst() - lineNumber)) { + selected = i; + } + } + return rates.get(selected).getSecond(); + } + + } + + /** Local class for handling already parsed mean plane data. */ + private static class ParsedMeanPlane { + + /** Min line. */ + private final int minLine; + + /** Max line. */ + private final int maxLine; + + /** Maximum number of evaluations. */ + private final int maxEval; + + /** Accuracy to use for finding crossing line number. */ + private final double accuracy; + + /** Mean plane normal. */ + private final Vector3D normal; + + /** simple constructor. + * @param minLine min line + * @param maxLine max line + * @param maxEval maximum number of evaluations + * @param accuracy accuracy to use for finding crossing line number + * @param normal mean plane normal + */ + public ParsedMeanPlane(final int minLine, final int maxLine, + final int maxEval, final double accuracy, final Vector3D normal) { + this.minLine = minLine; + this.maxLine = maxLine; + this.maxEval = maxEval; + this.accuracy = accuracy; + this.normal = normal; + } + + } + /** Local interface for dumped calls. */ private abstract static class DumpedCall { diff --git a/src/main/java/org/orekit/rugged/errors/RuggedExceptionWrapper.java b/src/main/java/org/orekit/rugged/errors/RuggedExceptionWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..6d006135f7d095e2d3972a4f152d8de554a8de41 --- /dev/null +++ b/src/main/java/org/orekit/rugged/errors/RuggedExceptionWrapper.java @@ -0,0 +1,53 @@ +/* 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 allows to wrap {@link RuggedException} instances in {@code RuntimeException}. + * <p>Wrapping {@link RuggedException} instances is useful when a low level method throws + * one such exception and this method must be called from another one which does not allow + * this exception. Typical examples are propagation methods that are used inside Apache + * Commons optimizers, integrators or solvers.</p> + * <p> + * This class is heavily based on Orekit {@link org.orekit.errors.OrekitException}, + * which is distributed under the terms of the Apache License V2. + * </p> + * @author Luc Maisonobe + */ +public class RuggedExceptionWrapper extends RuntimeException { + + /** serializable UID. */ + private static final long serialVersionUID = 20150224L; + + /** Underlying Orekit exception. */ + private final RuggedException wrappedException; + + /** Simple constructor. + * @param wrappedException Orekit exception to wrap + */ + public RuggedExceptionWrapper(final RuggedException wrappedException) { + super(wrappedException); + this.wrappedException = wrappedException; + } + + /** Get the wrapped exception. + * @return wrapped exception + */ + public RuggedException getException() { + return wrappedException; + } + +} diff --git a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java index e657479f34b7395dac153d422e033f6ef1eb2356..e336fdf758dfeddebc19c1c4961a60d71c175aed 100644 --- a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java +++ b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java @@ -74,7 +74,8 @@ public enum RuggedMessages implements Localizable { LIGHT_TIME_CORRECTION_REDEFINED("light time correction redefined, line {0}, file {1}: {2}"), ABERRATION_OF_LIGHT_CORRECTION_REDEFINED("aberration of light correction redefined, line {0}, file {1}: {2}"), TILE_ALREADY_DEFINED("tile {0} already defined, line {1}, file {2}: {3}"), - UNKNOWN_TILE("unknown tile {0}, line {1}, file {2}: {3}"); + UNKNOWN_TILE("unknown tile {0}, line {1}, file {2}: {3}"), + SENSOR_ALREADY_DEFINED("sensor {0} already defined, line {1}, file {2}: {3}"); // CHECKSTYLE: resume JavadocVariable check diff --git a/src/main/java/org/orekit/rugged/linesensor/LineSensor.java b/src/main/java/org/orekit/rugged/linesensor/LineSensor.java index abcd16ec827c69df7fe86665c9d99577e64534e4..bcdb4c9d6bd06d0d0b4d43f938ca1f1a011615b9 100644 --- a/src/main/java/org/orekit/rugged/linesensor/LineSensor.java +++ b/src/main/java/org/orekit/rugged/linesensor/LineSensor.java @@ -17,6 +17,8 @@ package org.orekit.rugged.linesensor; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; +import org.orekit.rugged.errors.DumpManager; +import org.orekit.rugged.errors.RuggedException; import org.orekit.rugged.los.TimeDependentLOS; import org.orekit.time.AbsoluteDate; @@ -72,25 +74,37 @@ public class LineSensor { * @param date current date * @param i pixel index (must be between 0 and {@link #getNbPixels()} - 1 * @return pixel normalized line-of-sight + * @exception RuggedException if date cannot be handled */ - public Vector3D getLos(final AbsoluteDate date, final int i) { - return los.getLOS(i, date); + public Vector3D getLos(final AbsoluteDate date, final int i) + throws RuggedException { + final Vector3D l = los.getLOS(i, date); + DumpManager.dumpSensorLOS(name, date, i, l); + return l; } /** Get the date. * @param lineNumber line number * @return date corresponding to line number + * @exception RuggedException if date cannot be handled */ - public AbsoluteDate getDate(final double lineNumber) { - return datationModel.getDate(lineNumber); + public AbsoluteDate getDate(final double lineNumber) + throws RuggedException { + final AbsoluteDate date = datationModel.getDate(lineNumber); + DumpManager.dumpSensorDate(name, lineNumber, date); + return date; } /** Get the line number. * @param date date * @return line number corresponding to date + * @exception RuggedException if date cannot be handled */ - public double getLine(final AbsoluteDate date) { - return datationModel.getLine(date); + public double getLine(final AbsoluteDate date) + throws RuggedException { + final double lineNumber = datationModel.getLine(date); + DumpManager.dumpSensorLine(name, date, lineNumber); + return lineNumber; } /** Get the rate of lines scanning. @@ -98,7 +112,9 @@ public class LineSensor { * @return rate of lines scanning (lines / seconds) */ public double getRate(final double lineNumber) { - return datationModel.getRate(lineNumber); + final double rate = datationModel.getRate(lineNumber); + DumpManager.dumpSensorRate(name, lineNumber, rate); + return rate; } /** Get the sensor position. diff --git a/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java b/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java index e4f8cfb1b54760348fd5756dfc950fe0fd5d8350..ce2d0659dd0bda4f73986feaf092e782a61fb6d3 100644 --- a/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java +++ b/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java @@ -92,6 +92,30 @@ public class SensorMeanPlaneCrossing { final boolean aberrationOfLightCorrection, final int maxEval, final double accuracy) throws RuggedException { + this(sensor, scToBody, minLine, maxLine, lightTimeCorrection, aberrationOfLightCorrection, + maxEval, accuracy, computeMeanPlaneNormal(sensor, minLine, maxLine)); + } + + /** Simple constructor. + * @param sensor sensor to consider + * @param scToBody converter between spacecraft and body + * @param minLine minimum line number + * @param maxLine maximum line number + * @param lightTimeCorrection flag for light time correction + * @param aberrationOfLightCorrection flag for aberration of light correction. + * @param maxEval maximum number of evaluations + * @param accuracy accuracy to use for finding crossing line number + * @param meanPlaneNormal mean plane normal + * @exception RuggedException if some frame conversion fails + */ + public SensorMeanPlaneCrossing(final LineSensor sensor, + final SpacecraftToObservedBody scToBody, + final int minLine, final int maxLine, + final boolean lightTimeCorrection, + final boolean aberrationOfLightCorrection, + final int maxEval, final double accuracy, + final Vector3D meanPlaneNormal) + throws RuggedException { this.sensor = sensor; this.minLine = minLine; @@ -107,19 +131,25 @@ public class SensorMeanPlaneCrossing { this.midBodyToInert = scToBody.getBodyToInertial(midDate); this.midScToInert = scToBody.getScToInertial(midDate); - this.meanPlaneNormal = computeMeanPlaneNormal(midDate); + this.meanPlaneNormal = meanPlaneNormal; } /** Compute the plane containing origin that best fits viewing directions point cloud. - * @param midDate middle date + * @param sensor line sensor + * @param minLine minimum line number + * @param maxLine maximum line number * <p> * The normal is oriented such that traversing pixels in increasing indices * order corresponds to trigonometric order (i.e. counterclockwise). * </p> * @return normal of the mean plane + * @exception RuggedException if mid date cannot be handled */ - private Vector3D computeMeanPlaneNormal(final AbsoluteDate midDate) { + private static Vector3D computeMeanPlaneNormal(final LineSensor sensor, final int minLine, final int maxLine) + throws RuggedException { + + final AbsoluteDate midDate = sensor.getDate(0.5 * (minLine + maxLine)); // build a centered data matrix // (for each viewing direction, we add both the direction and its @@ -154,6 +184,20 @@ public class SensorMeanPlaneCrossing { } + /** Get the underlying sensor. + * @return underlying sensor + */ + public LineSensor getSensor() { + return sensor; + } + + /** Get converter between spacecraft and body. + * @return converter between spacecraft and body + */ + public SpacecraftToObservedBody getScToBody() { + return scToBody; + } + /** Get the minimum line number in the search interval. * @return minimum line number in the search interval */ @@ -168,6 +212,20 @@ public class SensorMeanPlaneCrossing { return maxLine; } + /** Get the maximum number of evaluations. + * @return maximum number of evaluations + */ + public int getMaxEval() { + return maxEval; + } + + /** Get the accuracy to use for finding crossing line number. + * @return accuracy to use for finding crossing line number + */ + public double getAccuracy() { + return accuracy; + } + /** Get the mean plane normal. * <p> * The normal is oriented such traversing pixels in increasing indices diff --git a/src/main/java/org/orekit/rugged/linesensor/SensorPixelCrossing.java b/src/main/java/org/orekit/rugged/linesensor/SensorPixelCrossing.java index ca95673d5106b69871ffb7a7643e4db495d2371d..0e972175d6a342c1d7aceed783217a5823df741f 100644 --- a/src/main/java/org/orekit/rugged/linesensor/SensorPixelCrossing.java +++ b/src/main/java/org/orekit/rugged/linesensor/SensorPixelCrossing.java @@ -23,8 +23,8 @@ 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.errors.OrekitExceptionWrapper; import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.errors.RuggedExceptionWrapper; import org.orekit.time.AbsoluteDate; /** Class devoted to locate where ground point crosses a sensor line. @@ -79,8 +79,12 @@ public class SensorPixelCrossing { final UnivariateFunction f = new UnivariateFunction() { /** {@inheritDoc} */ @Override - public double value(final double x) throws OrekitExceptionWrapper { - return Vector3D.angle(cross, getLOS(date, x)) - 0.5 * FastMath.PI; + 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); + } } }; @@ -94,6 +98,8 @@ public class SensorPixelCrossing { return Double.NaN; } catch (TooManyEvaluationsException tmee) { throw new RuggedException(tmee); + } catch (RuggedExceptionWrapper rew) { + throw rew.getException(); } } @@ -101,8 +107,10 @@ public class SensorPixelCrossing { * @param date current date * @param x pixel index * @return interpolated direction for specified index + * @exception RuggedException if date cannot be handled */ - private Vector3D getLOS(final AbsoluteDate date, final double x) { + private Vector3D getLOS(final AbsoluteDate date, final double x) + throws RuggedException { // find surrounding pixels final int iInf = FastMath.max(0, FastMath.min(sensor.getNbPixels() - 2, (int) FastMath.floor(x))); diff --git a/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java b/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java index 3ead84ed71b421ff9193652721e710e201ae6802..af7906f27865a1a6d89c9e2aab12de3e48e398d6 100644 --- a/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java +++ b/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java @@ -58,6 +58,21 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid { b2 = b * b; } + /** {@inheritDoc} */ + @Override + public Vector3D transform(final GeodeticPoint point) { + DumpManager.dumpEllipsoid(this); + return super.transform(point); + } + + /** {@inheritDoc} */ + @Override + public GeodeticPoint transform(final Vector3D point, final Frame frame, final AbsoluteDate date) + throws OrekitException { + DumpManager.dumpEllipsoid(this); + return super.transform(point, frame, date); + } + /** Get point at some latitude along a pixel line of sight. * @param position cell position (in body frame) * @param los pixel line-of-sight, not necessarily normalized (in body frame) @@ -247,8 +262,6 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid { */ public Vector3D convertLos(final GeodeticPoint point, final Vector3D los) { - DumpManager.dumpEllipsoid(this); - // Cartesian coordinates of the topocentric frame origin final Vector3D p3D = transform(point); @@ -282,8 +295,6 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid { throws RuggedException { try { - DumpManager.dumpEllipsoid(this); - // switch to geodetic coordinates using primary point as reference final GeodeticPoint point = transform(primary, getBodyFrame(), null); final Vector3D los = secondary.subtract(primary); @@ -308,7 +319,6 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid { public NormalizedGeodeticPoint transform(final Vector3D point, final Frame frame, final AbsoluteDate date, final double centralLongitude) throws OrekitException { - DumpManager.dumpEllipsoid(this); final GeodeticPoint gp = transform(point, frame, date); return new NormalizedGeodeticPoint(gp.getLatitude(), gp.getLongitude(), gp.getAltitude(), centralLongitude); 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 c65fd1b2371f9235c7f658925aa77bcfb9f6647e..ef8328b8a3441df5496ea0bf5376e99d77eb74e4 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 @@ -72,3 +72,6 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION> # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = <MISSING TRANSLATION> + +# sensor {0} already defined, line {1}, file {2}: {3} +SENSOR_ALREADY_DEFINED = <MISSING TRANSLATION> 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 c7925f9cb3a5f311cc0d62eccc3ea3922e00268d..6d0c8e35933336b295e97f8a361605117598af0a 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 @@ -72,3 +72,6 @@ TILE_ALREADY_DEFINED = tile {0} already defined, line {1}, file {2}: {3} # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = unknown tile {0}, line {1}, file {2}: {3} + +# sensor {0} already defined, line {1}, file {2}: {3} +SENSOR_ALREADY_DEFINED = sensor {0} already defined, line {1}, file {2}: {3} 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 44b538430d2af4605ef34c71863208528ac7bc29..0ee86683bea24520b2f7ad7846f90255c548fbb8 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 @@ -72,3 +72,6 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION> # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = <MISSING TRANSLATION> + +# sensor {0} already defined, line {1}, file {2}: {3} +SENSOR_ALREADY_DEFINED = <MISSING TRANSLATION> 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 f86ddc6403d497c790006d52cc005b87503fefce..a96ec9daccb97b8261beb2d8d323ba6cfbf4ecf3 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 @@ -72,3 +72,6 @@ TILE_ALREADY_DEFINED = tuile {0} déjà définie ligne {1} du fichier {2}: {3} # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = tuile {0} inconnue ligne {1} du fichier {2}: {3} + +# sensor {0} already defined, line {1}, file {2}: {3} +SENSOR_ALREADY_DEFINED = capteur {0} déjà défini ligne {1} du fichier {2}: {3} 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 fc9f5b237c52cf30d3b7121dcb13cfae7625540e..8a18f04fffedcce9b6c9155d248075f574b915f9 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 @@ -72,3 +72,6 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION> # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = <MISSING TRANSLATION> + +# sensor {0} already defined, line {1}, file {2}: {3} +SENSOR_ALREADY_DEFINED = <MISSING TRANSLATION> 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 73426284fe2a0f4ad101ef1247c77fa035da7993..7da881a06112197b10025aa6bf0a53690d49ae46 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 @@ -72,3 +72,6 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION> # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = <MISSING TRANSLATION> + +# sensor {0} already defined, line {1}, file {2}: {3} +SENSOR_ALREADY_DEFINED = <MISSING TRANSLATION> 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 90280718842ca66ec803b808c3786fa2b2293f4e..8a97c80f7faca1b079c1c6f411cf7036b28cb38c 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8 @@ -72,3 +72,6 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION> # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = <MISSING TRANSLATION> + +# sensor {0} already defined, line {1}, file {2}: {3} +SENSOR_ALREADY_DEFINED = <MISSING TRANSLATION> 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 900187a721af177d906e4c800cb9b2fa15a4ba76..0aaf852d29bf21161090cd2882904fae01119131 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8 @@ -72,3 +72,6 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION> # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = <MISSING TRANSLATION> + +# sensor {0} already defined, line {1}, file {2}: {3} +SENSOR_ALREADY_DEFINED = <MISSING TRANSLATION> diff --git a/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java b/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java index c628d18052a0a319967020f5076d0e2779c10f82..8a87d185682a0b152c5a27d3e818c9d3b2cc1f46 100644 --- a/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java +++ b/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java @@ -29,6 +29,7 @@ import org.orekit.data.DataProvidersManager; import org.orekit.data.DirectoryCrawler; import org.orekit.errors.OrekitException; import org.orekit.rugged.api.Rugged; +import org.orekit.rugged.linesensor.SensorPixel; public class DumpReplayerTest { @@ -55,4 +56,26 @@ public class DumpReplayerTest { } + @Test + public void testInverseLoc01() 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-01.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) { + SensorPixel expectedSP = (SensorPixel) result.getExpected(); + SensorPixel replayedSP = (SensorPixel) result.getReplayed(); + Assert.assertEquals(expectedSP.getLineNumber(), replayedSP.getLineNumber(), 1.0e-6); + Assert.assertEquals(expectedSP.getPixelNumber(), replayedSP.getPixelNumber(), 1.0e-6); + } + + } + } diff --git a/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java b/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java index fa07bcf5d9d120436e25b35bfa860c8844e95ad4..47291ceb469f427b48260d7d36230305b603bb25 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(26, RuggedMessages.values().length); } @Test diff --git a/src/test/resources/replay/replay-inverse-loc-01.txt b/src/test/resources/replay/replay-inverse-loc-01.txt new file mode 100644 index 0000000000000000000000000000000000000000..51981332641f61410a42e4f3ab026925d2e2abb5 --- /dev/null +++ b/src/test/resources/replay/replay-inverse-loc-01.txt @@ -0,0 +1,37 @@ +# Rugged library dump file, created on 2015-02-24T16:50:12Z +# all units are SI units (m, m/s, rad ...) +DEM tile: t0 latMin -4.014257279586958e-01 latStep 6.817692390602850e-05 latRows 257 lonMin 2.495820830351891e+00 lonStep 6.817692390602850e-05 lonCols 257 +DEM cell: t0 latIndex 192 lonIndex 0 elevation -6.124011631478857e+02 +DEM cell: t0 latIndex 128 lonIndex 128 elevation 3.151327114467009e+03 +DEM cell: t0 latIndex 122 lonIndex 99 elevation 1.778606495649060e+03 +DEM cell: t0 latIndex 122 lonIndex 100 elevation 1.809481571226391e+03 +DEM cell: t0 latIndex 123 lonIndex 99 elevation 1.772149770526270e+03 +DEM cell: t0 latIndex 123 lonIndex 100 elevation 1.804520334312959e+03 +inverse location: sensorName line latitude -3.930524233859007e-01 longitude 2.502596047891660e+00 elevation 1.785429914217195e+03 minLine 0 maxLine 2000 lightTime true aberration true +sensor: sensorName line nbPixels 2000 position 1.500000000000000e+00 0.000000000000000e+00 -2.000000000000000e-01 +sensor mean plane: sensorName line minLine 0 maxLine 2000 maxEval 50 accuracy 1.000000000000000e-02 normal 1.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 +sensor date: sensorName line lineNumber 1.000000000000000e+03 => 2012-01-01T12:30:00.00000000000000Z +span: minDate 2012-01-01T12:29:57.50000000000000Z maxDate 2012-01-01T12:30:02.50000000000000Z tStep 1.000000000000000e-03 tolerance 5.000000000000000e+00 inertialFrame EME2000 +transform: index 2500 body r -8.085963389171905e-01 -3.465415132416125e-04 4.896468952533137e-04 -5.883634938068593e-01 Ω -8.740475534355122e-08 1.215132763920864e-09 -7.292109805268457e-05 ΩDot -1.642299174832679e-16 8.973031065665686e-17 1.983408395824453e-19 spacecraft p 1.384770770635060e+04 3.157810312896036e+03 -7.179504513258174e+06 v -3.180198832979256e+01 -6.779040795561070e+00 8.276861119339028e+00 a -9.324121873999545e-01 -8.319728238691058e+00 1.345786832372742e-03 r -6.828948903548651e-01 4.142451171315383e-01 -3.878489660867486e-01 4.600312284675194e-01 Ω -1.009782076972198e-03 1.982726233227751e-04 1.647740165426390e-04 ΩDot -3.649972672343429e-07 2.007836645730816e-07 -1.257082123046451e-06 +ellipsoid: ae 6.378137000000000e+06 f 3.352810664747481e-03 frame ITRF_CIO_CONV_2010_SIMPLE_EOP +sensor rate: sensorName line lineNumber 1000.0 => 6.666666666666666e+02 +sensor date: sensorName line lineNumber 1.753125119831697e+03 => 2012-01-01T12:30:01.12968767974755Z +transform: index 3630 body r -8.086205790715331e-01 -3.465213511527127e-04 4.896611176157392e-04 -5.883301787746077e-01 Ω -8.740475552913246e-08 1.215132865316382e-09 -7.292109805268537e-05 ΩDot -1.642303315278223e-16 8.973086775113133e-17 1.983413459365331e-19 spacecraft p 1.381161686138390e+04 3.149035127746873e+03 -7.179495156850004e+06 v -3.198309695268937e+01 -7.869713919215563e+00 8.283718407079078e+00 a -9.313885738644379e-01 -8.324782304826440e+00 1.354189237138481e-03 r -6.826577475060918e-01 4.145470548488056e-01 -3.882264160785311e-01 4.597927673908209e-01 Ω -1.009835304084986e-03 1.983572786405474e-04 1.645625945551068e-04 ΩDot -3.648903522451360e-07 2.009701619867746e-07 -1.257044812963575e-06 +sensor rate: sensorName line lineNumber 1753.125119831697 => 6.666666666666666e+02 +sensor date: sensorName line lineNumber 1.753079999999987e+03 => 2012-01-01T12:30:01.12961999999998Z +sensor rate: sensorName line lineNumber 1753.0799999999872 => 6.666666666666666e+02 +sensor date: sensorName line lineNumber 1.753079999999987e+03 => 2012-01-01T12:30:01.12961999999998Z +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 999 => 0.000000000000000e+00 -7.660363365669057e-01 6.427972705753770e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 1000 => 0.000000000000000e+00 -7.660525495492120e-01 6.427779486954669e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 0 => 0.000000000000000e+00 -7.495978631423039e-01 6.618935288794506e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 1 => 0.000000000000000e+00 -7.496145577932898e-01 6.618746216198131e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 16 => 0.000000000000000e+00 -7.498649203239307e-01 6.615909622021642e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 17 => 0.000000000000000e+00 -7.498816073432156e-01 6.615720482066600e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 17 => 0.000000000000000e+00 -7.498816073432156e-01 6.615720482066600e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 18 => 0.000000000000000e+00 -7.498982938854290e-01 6.615531337902669e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 17 => 0.000000000000000e+00 -7.498816073432156e-01 6.615720482066600e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12961999999998Z pixelNumber 18 => 0.000000000000000e+00 -7.498982938854290e-01 6.615531337902669e-01 +sensor date: sensorName line lineNumber 1.753080000000047e+03 => 2012-01-01T12:30:01.12962000000007Z +sensor LOS: sensorName line date 2012-01-01T12:30:01.12962000000007Z pixelNumber 17 => 0.000000000000000e+00 -7.498816073432156e-01 6.615720482066600e-01 +sensor LOS: sensorName line date 2012-01-01T12:30:01.12962000000007Z pixelNumber 18 => 0.000000000000000e+00 -7.498982938854290e-01 6.615531337902669e-01 +inverse location result: lineNumber 1.753080000000047e+03 pixelNumber 1.700000000063574e+01