diff --git a/src/main/java/org/orekit/rugged/api/Rugged.java b/src/main/java/org/orekit/rugged/api/Rugged.java index 31c30b2f74798b1a955a3242ae3ca97aa39ba4a7..9cae53f2c28f53e5979e0deceee6307e1a4433c2 100644 --- a/src/main/java/org/orekit/rugged/api/Rugged.java +++ b/src/main/java/org/orekit/rugged/api/Rugged.java @@ -26,8 +26,6 @@ import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.util.FastMath; import org.orekit.bodies.GeodeticPoint; import org.orekit.frames.Transform; -import org.orekit.rugged.atmosphericrefraction.AtmosphericRefraction; -import org.orekit.rugged.atmosphericrefraction.MultiLayerModel; import org.orekit.rugged.errors.DumpManager; import org.orekit.rugged.errors.RuggedException; import org.orekit.rugged.errors.RuggedMessages; @@ -36,6 +34,7 @@ import org.orekit.rugged.linesensor.LineSensor; import org.orekit.rugged.linesensor.SensorMeanPlaneCrossing; import org.orekit.rugged.linesensor.SensorPixel; import org.orekit.rugged.linesensor.SensorPixelCrossing; +import org.orekit.rugged.refraction.AtmosphericRefraction; import org.orekit.rugged.utils.ExtendedEllipsoid; import org.orekit.rugged.utils.NormalizedGeodeticPoint; import org.orekit.rugged.utils.SpacecraftToObservedBody; @@ -81,6 +80,9 @@ public class Rugged { /** Flag for aberration of light correction. */ private boolean aberrationOfLightCorrection; + /** Atmospheric refraction for line of sight correction. */ + private AtmosphericRefraction atmosphericRefraction; + /** Build a configured instance. * <p> * By default, the instance performs both light time correction (which refers @@ -94,13 +96,14 @@ public class Rugged { * @param ellipsoid f reference ellipsoid * @param lightTimeCorrection if true, the light travel time between ground * @param aberrationOfLightCorrection if true, the aberration of light - * is corrected for more accurate location - * and spacecraft is compensated for more accurate location +* is corrected for more accurate location +* and spacecraft is compensated for more accurate location + * @param atmosphericRefraction the atmospheric refraction model to be used for more accurate location * @param scToBody transforms interpolator * @param sensors sensors */ - Rugged(final IntersectionAlgorithm algorithm, final ExtendedEllipsoid ellipsoid, - final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection, + Rugged(final IntersectionAlgorithm algorithm, final ExtendedEllipsoid ellipsoid, final boolean lightTimeCorrection, + final boolean aberrationOfLightCorrection, final AtmosphericRefraction atmosphericRefraction, final SpacecraftToObservedBody scToBody, final Collection<LineSensor> sensors) { // space reference @@ -120,7 +123,7 @@ public class Rugged { this.lightTimeCorrection = lightTimeCorrection; this.aberrationOfLightCorrection = aberrationOfLightCorrection; - + this.atmosphericRefraction = atmosphericRefraction; } /** Get the DEM intersection algorithm. @@ -146,6 +149,13 @@ public class Rugged { return aberrationOfLightCorrection; } + /** Get the atmospheric refraction model. + * @return atmospheric refraction model + */ + public AtmosphericRefraction getRefractionCorrection() { + return atmosphericRefraction; + } + /** Get the line sensors. * @return line sensors */ @@ -214,8 +224,8 @@ public class Rugged { final GeodeticPoint[] gp = new GeodeticPoint[sensor.getNbPixels()]; for (int i = 0; i < sensor.getNbPixels(); ++i) { - DumpManager.dumpDirectLocation(date, sensor.getPosition(), sensor.getLos(date, i), - lightTimeCorrection, aberrationOfLightCorrection); + DumpManager.dumpDirectLocation(date, sensor.getPosition(), sensor.getLos(date, i), lightTimeCorrection, + aberrationOfLightCorrection, atmosphericRefraction != null); final Vector3D obsLInert = scToInert.transformVector(sensor.getLos(date, i)); final Vector3D lInert; @@ -264,6 +274,12 @@ public class Rugged { algorithm.intersection(ellipsoid, pBody, lBody)); } + if (atmosphericRefraction != null) { + // apply atmospheric refraction correction + gp[i] = atmosphericRefraction.applyCorrection(sensor.getPosition(), sensor.getLos(date, i), + (NormalizedGeodeticPoint) gp[i], algorithm); + } + DumpManager.dumpDirectLocationResult(gp[i]); } @@ -282,7 +298,8 @@ public class Rugged { public GeodeticPoint directLocation(final AbsoluteDate date, final Vector3D position, final Vector3D los) throws RuggedException { - DumpManager.dumpDirectLocation(date, position, los, lightTimeCorrection, aberrationOfLightCorrection); + DumpManager.dumpDirectLocation(date, position, los, lightTimeCorrection, aberrationOfLightCorrection, + atmosphericRefraction != null); // compute the approximate transform between spacecraft and observed body final Transform scToInert = scToBody.getScToInertial(date); @@ -315,7 +332,7 @@ public class Rugged { lInert = obsLInert; } - final NormalizedGeodeticPoint result; + final NormalizedGeodeticPoint gp; if (lightTimeCorrection) { // compute DEM intersection with light time correction final Vector3D sP = approximate.transformPosition(position); @@ -330,7 +347,7 @@ public class Rugged { final Vector3D eP2 = ellipsoid.transform(gp1); final double deltaT2 = eP2.distance(sP) / Constants.SPEED_OF_LIGHT; final Transform shifted2 = inertToBody.shiftedBy(-deltaT2); - result = algorithm.refineIntersection(ellipsoid, + gp = algorithm.refineIntersection(ellipsoid, shifted2.transformPosition(pInert), shifted2.transformVector(lInert), gp1); @@ -339,14 +356,17 @@ public class Rugged { // compute DEM intersection without light time correction final Vector3D pBody = inertToBody.transformPosition(pInert); final Vector3D lBody = inertToBody.transformVector(lInert); - result = algorithm.refineIntersection(ellipsoid, pBody, lBody, + gp = algorithm.refineIntersection(ellipsoid, pBody, lBody, algorithm.intersection(ellipsoid, pBody, lBody)); + } - // compute atmosphere deviation. - //AtmosphericRefraction atmosphericRefraction = new MultiLayerModel(); - // result.getZenith() - //long deviation = atmosphericRefraction.getDeviation(pBody, lBody, result.getAltitude()); - + final NormalizedGeodeticPoint result; + if (atmosphericRefraction != null) { + // apply atmospheric refraction correction + result = atmosphericRefraction.applyCorrection(position, los, gp, algorithm); + } else { + // don't apply atmospheric refraction correction + result = gp; } DumpManager.dumpDirectLocationResult(result); diff --git a/src/main/java/org/orekit/rugged/api/RuggedBuilder.java b/src/main/java/org/orekit/rugged/api/RuggedBuilder.java index 679d909ef151813607399f869fa66570369f1aab..a6c5439a7fab91435300772b011c34fa7b91b930 100644 --- a/src/main/java/org/orekit/rugged/api/RuggedBuilder.java +++ b/src/main/java/org/orekit/rugged/api/RuggedBuilder.java @@ -45,6 +45,7 @@ import org.orekit.rugged.intersection.IntersectionAlgorithm; import org.orekit.rugged.intersection.duvenhage.DuvenhageAlgorithm; import org.orekit.rugged.linesensor.LineSensor; import org.orekit.rugged.raster.TileUpdater; +import org.orekit.rugged.refraction.AtmosphericRefraction; import org.orekit.rugged.utils.ExtendedEllipsoid; import org.orekit.rugged.utils.SpacecraftToObservedBody; import org.orekit.time.AbsoluteDate; @@ -155,6 +156,9 @@ public class RuggedBuilder { /** Flag for aberration of light correction. */ private boolean aberrationOfLightCorrection; + /** Atmospheric refraction to use for line of sight correction. */ + private AtmosphericRefraction atmosphericRefraction; + /** Sensors. */ private final List<LineSensor> sensors; @@ -838,6 +842,32 @@ public class RuggedBuilder { return aberrationOfLightCorrection; } + /** Set atmospheric refraction for line of sight correction. + * <p> + * This method sets an atmospheric refraction model to be used between + * spacecraft and ground for the correction of intersected points on ground. + * Compensating for the effect of atmospheric refraction improves location + * accuracy. + * </p> + * @param atmosphericRefraction the atmospheric refraction model to be used for more accurate location + * @return the builder instance + * @see #getRefractionCorrection() + */ + // CHECKSTYLE: stop HiddenField check + public RuggedBuilder setRefractionCorrection(final AtmosphericRefraction atmosphericRefraction) { + // CHECKSTYLE: resume HiddenField check + this.atmosphericRefraction = atmosphericRefraction; + return this; + } + + /** Get the atmospheric refraction model. + * @return atmospheric refraction model + * @see #setRefractionCorrection(AtmosphericRefraction) + */ + public AtmosphericRefraction getRefractionCorrection() { + return atmosphericRefraction; + } + /** Set up line sensor model. * @param lineSensor line sensor model * @return the builder instance @@ -996,7 +1026,7 @@ public class RuggedBuilder { } createInterpolatorIfNeeded(); return new Rugged(createAlgorithm(algorithmID, tileUpdater, maxCachedTiles, constantElevation), ellipsoid, - lightTimeCorrection, aberrationOfLightCorrection, scToBody, sensors); + lightTimeCorrection, aberrationOfLightCorrection, atmosphericRefraction, scToBody, sensors); } } diff --git a/src/main/java/org/orekit/rugged/errors/Dump.java b/src/main/java/org/orekit/rugged/errors/Dump.java index e74fad66a41855dc497f153e15e7d78288765e24..26f2b254a1c7d5d44c21c6ff0f93fbf7e7b66426 100644 --- a/src/main/java/org/orekit/rugged/errors/Dump.java +++ b/src/main/java/org/orekit/rugged/errors/Dump.java @@ -150,17 +150,19 @@ class Dump { * @param los normalized line-of-sight in spacecraft frame * @param lightTimeCorrection flag for light time correction * @param aberrationOfLightCorrection flag for aberration of light correction + * @param refractionCorrection flag for refraction correction * @exception RuggedException if date cannot be converted to UTC */ public void dumpDirectLocation(final AbsoluteDate date, final Vector3D position, final Vector3D los, - final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection) + final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection, + final boolean refractionCorrection) throws RuggedException { writer.format(Locale.US, - "direct location: date %s position %22.15e %22.15e %22.15e los %22.15e %22.15e %22.15e lightTime %b aberration %b%n", + "direct location: date %s position %22.15e %22.15e %22.15e los %22.15e %22.15e %22.15e lightTime %b aberration %b refraction %b %n", convertDate(date), position.getX(), position.getY(), position.getZ(), los.getX(), los.getY(), los.getZ(), - lightTimeCorrection, aberrationOfLightCorrection); + lightTimeCorrection, aberrationOfLightCorrection, refractionCorrection); } /** Dump a direct location result. diff --git a/src/main/java/org/orekit/rugged/errors/DumpManager.java b/src/main/java/org/orekit/rugged/errors/DumpManager.java index 379bef031aa207f93e730c6138578736d158ac45..f787f0f9c7712d9bd5cac5420fda6c8254650a83 100644 --- a/src/main/java/org/orekit/rugged/errors/DumpManager.java +++ b/src/main/java/org/orekit/rugged/errors/DumpManager.java @@ -139,13 +139,16 @@ public class DumpManager { * @param los normalized line-of-sight in spacecraft frame * @param lightTimeCorrection flag for light time correction * @param aberrationOfLightCorrection flag for aberration of light correction + * @param refractionCorrection flag for refraction correction * @exception RuggedException if date cannot be converted to UTC */ public static void dumpDirectLocation(final AbsoluteDate date, final Vector3D position, final Vector3D los, - final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection) + final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection, + final boolean refractionCorrection) throws RuggedException { if (isActive()) { - DUMP.get().dumpDirectLocation(date, position, los, lightTimeCorrection, aberrationOfLightCorrection); + DUMP.get().dumpDirectLocation(date, position, los, lightTimeCorrection, aberrationOfLightCorrection, + refractionCorrection); } } diff --git a/src/main/java/org/orekit/rugged/atmosphericrefraction/AtmosphericRefraction.java b/src/main/java/org/orekit/rugged/refraction/AtmosphericRefraction.java similarity index 62% rename from src/main/java/org/orekit/rugged/atmosphericrefraction/AtmosphericRefraction.java rename to src/main/java/org/orekit/rugged/refraction/AtmosphericRefraction.java index 21a545bf19dc08e8ff417b48ca7d81147f096bb4..3a234db4992f4e7fb402e16f5cf4b4699ab2bd0c 100644 --- a/src/main/java/org/orekit/rugged/atmosphericrefraction/AtmosphericRefraction.java +++ b/src/main/java/org/orekit/rugged/refraction/AtmosphericRefraction.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.orekit.rugged.atmosphericrefraction; +package org.orekit.rugged.refraction; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; @@ -23,13 +23,23 @@ import org.orekit.rugged.intersection.IntersectionAlgorithm; import org.orekit.rugged.utils.NormalizedGeodeticPoint; /** - * Interface for atmospheric refraction. + * Interface for atmospheric refraction model. * @author Sergio Esteves */ public interface AtmosphericRefraction { + /** Apply correction to the intersected point with an atmospheric refraction model. + * @param satPos satellite position + * @param satLos satellite line of sight + * @param rawIntersection intersection point before refraction correction + * @param algorithm intersection algorithm + * @return corrected point with the effect of atmospheric refraction + * @throws RuggedException if there is no refraction data at altitude of rawIntersection or see + * {@link org.orekit.rugged.utils.ExtendedEllipsoid#pointAtAltitude(Vector3D, Vector3D, double)} or see + * {@link IntersectionAlgorithm#refineIntersection(ExtendedEllipsoid, Vector3D, Vector3D, NormalizedGeodeticPoint)} + */ NormalizedGeodeticPoint applyCorrection(Vector3D satPos, Vector3D satLos, NormalizedGeodeticPoint rawIntersection, IntersectionAlgorithm algorithm) - throws RuggedException; + throws RuggedException; } diff --git a/src/main/java/org/orekit/rugged/atmosphericrefraction/ConstantRefractionLayer.java b/src/main/java/org/orekit/rugged/refraction/ConstantRefractionLayer.java similarity index 52% rename from src/main/java/org/orekit/rugged/atmosphericrefraction/ConstantRefractionLayer.java rename to src/main/java/org/orekit/rugged/refraction/ConstantRefractionLayer.java index 6e9dd6a012782ae29c5f2877c44994b170d10e06..3b0da0c8169d04a509ee90bff98a7c1144d6938c 100644 --- a/src/main/java/org/orekit/rugged/atmosphericrefraction/ConstantRefractionLayer.java +++ b/src/main/java/org/orekit/rugged/refraction/ConstantRefractionLayer.java @@ -14,18 +14,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.orekit.rugged.atmosphericrefraction; +package org.orekit.rugged.refraction; /** * Class that represents a constant refraction layer to be used with {@link MultiLayerModel}. - * * @author Sergio Esteves */ public class ConstantRefractionLayer implements Comparable<ConstantRefractionLayer> { - private Double lowestAltitude; - private double refractiveIndex; - public ConstantRefractionLayer(double lowestAltitude, double refractiveIndex) { + /** lowest altitude of this layer. */ + private final Double lowestAltitude; + + /** refractive index of this layer. */ + private final double refractiveIndex; + + /** Simple constructor. + * @param lowestAltitude lowest altitude of the layer + * @param refractiveIndex refractive index of the layer + */ + public ConstantRefractionLayer(final double lowestAltitude, final double refractiveIndex) { this.lowestAltitude = lowestAltitude; this.refractiveIndex = refractiveIndex; } @@ -39,7 +46,29 @@ public class ConstantRefractionLayer implements Comparable<ConstantRefractionLay } @Override - public int compareTo(ConstantRefractionLayer o) { + public int compareTo(final ConstantRefractionLayer o) { return lowestAltitude.compareTo(o.lowestAltitude); } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final ConstantRefractionLayer that = (ConstantRefractionLayer) o; + + if (Double.compare(that.refractiveIndex, refractiveIndex) != 0) return false; + return lowestAltitude != null ? lowestAltitude.equals(that.lowestAltitude) : that.lowestAltitude == null; + + } + + @Override + public int hashCode() { + int result; + long temp; + result = lowestAltitude != null ? lowestAltitude.hashCode() : 0; + temp = Double.doubleToLongBits(refractiveIndex); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; + } } diff --git a/src/main/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModel.java b/src/main/java/org/orekit/rugged/refraction/MultiLayerModel.java similarity index 90% rename from src/main/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModel.java rename to src/main/java/org/orekit/rugged/refraction/MultiLayerModel.java index 1c44c2759ce7d4fe2c2e6d75790538bc4e99c9d2..d16522480610db11276ce5b629fb3a48baa79b60 100644 --- a/src/main/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModel.java +++ b/src/main/java/org/orekit/rugged/refraction/MultiLayerModel.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.orekit.rugged.atmosphericrefraction; +package org.orekit.rugged.refraction; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.util.FastMath; @@ -39,14 +39,16 @@ public class MultiLayerModel implements AtmosphericRefraction { /** Observed body ellipsoid. */ private final ExtendedEllipsoid ellipsoid; - /** Constant refraction layers */ + /** Constant refraction layers. */ private final List<ConstantRefractionLayer> refractionLayers; - /** Atmosphere lowest altitude */ + /** Atmosphere lowest altitude. */ private final double atmosphereLowestAltitude; - public MultiLayerModel(final ExtendedEllipsoid ellipsoid) - throws OrekitException { + /** Simple constructor. + * @param ellipsoid the ellipsoid to be used. + */ + public MultiLayerModel(final ExtendedEllipsoid ellipsoid) { this.ellipsoid = ellipsoid; refractionLayers = new ArrayList<ConstantRefractionLayer>(15); @@ -69,22 +71,26 @@ public class MultiLayerModel implements AtmosphericRefraction { atmosphereLowestAltitude = refractionLayers.get(refractionLayers.size() - 1).getLowestAltitude(); } - public MultiLayerModel(final ExtendedEllipsoid ellipsoid, final List<ConstantRefractionLayer> refractionLayers) - throws OrekitException { + /** Simple constructor. + * @param ellipsoid the ellipsoid to be used. + * @param refractionLayers the refraction layers to be used with this model. + */ + public MultiLayerModel(final ExtendedEllipsoid ellipsoid, final List<ConstantRefractionLayer> refractionLayers) { this.ellipsoid = ellipsoid; this.refractionLayers = refractionLayers; Collections.sort(this.refractionLayers, Collections.<ConstantRefractionLayer>reverseOrder()); atmosphereLowestAltitude = refractionLayers.get(refractionLayers.size() - 1).getLowestAltitude(); } + /** {@inheritDoc} */ @Override public NormalizedGeodeticPoint applyCorrection(final Vector3D satPos, final Vector3D satLos, final NormalizedGeodeticPoint rawIntersection, final IntersectionAlgorithm algorithm) - throws RuggedException { + throws RuggedException { try { - if(rawIntersection.getAltitude() < atmosphereLowestAltitude) { + if (rawIntersection.getAltitude() < atmosphereLowestAltitude) { throw new RuggedException(RuggedMessages.NO_LAYER_DATA, rawIntersection.getAltitude(), atmosphereLowestAltitude); } diff --git a/src/test/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModelTest.java b/src/test/java/org/orekit/rugged/refraction/MultiLayerModelTest.java similarity index 99% rename from src/test/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModelTest.java rename to src/test/java/org/orekit/rugged/refraction/MultiLayerModelTest.java index 4103307c2e814594b65f4a1c80943c86421ce621..fa97250860a6329b5bf3dfc73f7f4dd1eb1174cf 100644 --- a/src/test/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModelTest.java +++ b/src/test/java/org/orekit/rugged/refraction/MultiLayerModelTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.orekit.rugged.atmosphericrefraction; +package org.orekit.rugged.refraction; import org.apache.commons.math3.geometry.euclidean.threed.Rotation; import org.apache.commons.math3.geometry.euclidean.threed.RotationConvention;