diff --git a/src/main/java/org/orekit/rugged/atmosphericrefraction/ConstantRefractionLayer.java b/src/main/java/org/orekit/rugged/atmosphericrefraction/ConstantRefractionLayer.java index 96739d3057c3dbd83f427d87ef2fa94ff1769027..6e9dd6a012782ae29c5f2877c44994b170d10e06 100644 --- a/src/main/java/org/orekit/rugged/atmosphericrefraction/ConstantRefractionLayer.java +++ b/src/main/java/org/orekit/rugged/atmosphericrefraction/ConstantRefractionLayer.java @@ -21,8 +21,8 @@ package org.orekit.rugged.atmosphericrefraction; * * @author Sergio Esteves */ -public class ConstantRefractionLayer { - private double lowestAltitude; +public class ConstantRefractionLayer implements Comparable<ConstantRefractionLayer> { + private Double lowestAltitude; private double refractiveIndex; public ConstantRefractionLayer(double lowestAltitude, double refractiveIndex) { @@ -37,4 +37,9 @@ public class ConstantRefractionLayer { public double getRefractiveIndex() { return refractiveIndex; } + + @Override + public int compareTo(ConstantRefractionLayer o) { + return lowestAltitude.compareTo(o.lowestAltitude); + } } diff --git a/src/main/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModel.java b/src/main/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModel.java index 0a6dc5bc2896a0513df9e5eb0e0b255e9415a5f7..02cbf993ee8b189fa470b5803a5b1c6bca4d0ca2 100644 --- a/src/main/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModel.java +++ b/src/main/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModel.java @@ -21,11 +21,13 @@ import org.apache.commons.math3.util.FastMath; import org.orekit.bodies.GeodeticPoint; import org.orekit.errors.OrekitException; import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.errors.RuggedMessages; import org.orekit.rugged.intersection.IntersectionAlgorithm; import org.orekit.rugged.utils.ExtendedEllipsoid; import org.orekit.rugged.utils.NormalizedGeodeticPoint; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -40,6 +42,9 @@ public class MultiLayerModel implements AtmosphericRefraction { /** Constant refraction layers */ private final List<ConstantRefractionLayer> refractionLayers; + /** Atmosphere lowest altitude */ + private final double atmosphereLowestAltitude; + public MultiLayerModel(final ExtendedEllipsoid ellipsoid) throws OrekitException { this.ellipsoid = ellipsoid; @@ -60,14 +65,16 @@ public class MultiLayerModel implements AtmosphericRefraction { refractionLayers.add(new ConstantRefractionLayer( 1000.00, 1.000252)); refractionLayers.add(new ConstantRefractionLayer( 0.00, 1.000278)); refractionLayers.add(new ConstantRefractionLayer( -1000.00, 1.000306)); + + atmosphereLowestAltitude = refractionLayers.get(refractionLayers.size() - 1).getLowestAltitude(); } public MultiLayerModel(final ExtendedEllipsoid ellipsoid, final List<ConstantRefractionLayer> refractionLayers) throws OrekitException { this.ellipsoid = ellipsoid; - // TODO guarantee that list is already ordered by altitude? - // TODO guarantee that a minimum altitude value exists? this.refractionLayers = refractionLayers; + atmosphereLowestAltitude = refractionLayers.get(refractionLayers.size() - 1).getLowestAltitude(); + Collections.sort(this.refractionLayers, Collections.<ConstantRefractionLayer>reverseOrder()); } @Override @@ -77,6 +84,10 @@ public class MultiLayerModel implements AtmosphericRefraction { throws RuggedException { try { + if(rawIntersection.getAltitude() < atmosphereLowestAltitude) { + throw new RuggedException(RuggedMessages.NO_LAYER_DATA, rawIntersection.getAltitude(), + atmosphereLowestAltitude); + } Vector3D pos = satPos; Vector3D los = satLos.normalize(); diff --git a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java index 7eab55a39ff476d1ccbe72998e3fa59cc2a846d5..bf686ed249d3aeaed67cded71740bd5183879183 100644 --- a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java +++ b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java @@ -74,7 +74,9 @@ 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}"), + NO_LAYER_DATA("no atmospheric layer data at altitude {0} (lowest altitude: {1})"); + // CHECKSTYLE: resume JavadocVariable check 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 5cffbc9118488232c3ba50612d1eb078b1aca5cf..c9e49f1bc204dc825a4729f3107aac5f901b07df 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> + +# no atmospheric layer data at altitude {0} (lowest altitude: {1}) +NO_LAYER_DATA = <MISSING TRANSLATION> \ No newline at end of file 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 fab5d639f9c886918fcb3cf06b8cd3a5aee1005c..f960b7bba5e6249337eb03ebabcad70282c67ac5 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 @@ -73,3 +73,5 @@ 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} +# no atmospheric layer data at altitude {0} (lowest altitude: {1}) +NO_LAYER_DATA = no atmospheric layer data at altitude {0} (lowest altitude: {1}) \ No newline at end of file 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 a69adf7509b20b2aec97cda3f6540ff687e936e2..a16cd893c9691ba4ae77e857fad83bb3ddd41e69 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> + +# no atmospheric layer data at altitude {0} (lowest altitude: {1}) +NO_LAYER_DATA = <MISSING TRANSLATION> \ No newline at end of file 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 dd0357672ec1bb9dbdf643c09519a927f8642273..bf476377f84e05b00d57e1c54d31781095b102d9 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 @@ -73,3 +73,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} +# no atmospheric layer data at altitude {0} (lowest altitude: {1}) +NO_LAYER_DATA = <MISSING TRANSLATION> + 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 ffb0978899ee5262c2d94927e3db06696cbc0aba..a77f148f1d740f7268cd15defebf2db0578025ee 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 @@ -73,3 +73,5 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION> # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = <MISSING TRANSLATION> +# no atmospheric layer data at altitude {0} (lowest altitude: {1}) +NO_LAYER_DATA = <MISSING TRANSLATION> \ No newline at end of file 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 21b54586d1587e5b2b123ab0c176a131a0cb6421..f76a9705068725b5ae3521623e2ce6f7072796ea 100644 --- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 +++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 @@ -73,3 +73,5 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION> # unknown tile {0}, line {1}, file {2}: {3} UNKNOWN_TILE = <MISSING TRANSLATION> +# no atmospheric layer data at altitude {0} (lowest altitude: {1}) +NO_LAYER_DATA = <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 05765b86097bca0a18fba3841ea64ecd2aa2f5cc..14519f5add7db13e1d78d571badc68f630c63af7 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> + +# no atmospheric layer data at altitude {0} (lowest altitude: {1}) +NO_LAYER_DATA = <MISSING TRANSLATION> \ No newline at end of file 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 68d195bb5fdde088d0462ed3e659e2713f102eb9..01ddbfde68c0fc345c2b9297a9d0c3a5f1845fc6 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> + +# no atmospheric layer data at altitude {0} (lowest altitude: {1}) +NO_LAYER_DATA = <MISSING TRANSLATION> \ No newline at end of file diff --git a/src/test/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModelTest.java b/src/test/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModelTest.java index 87dbaf81bb92ce27a6189c348d67a5f773f4d161..5cc3a9c96d8ad603d039c54a863d2c14c8168532 100644 --- a/src/test/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModelTest.java +++ b/src/test/java/org/orekit/rugged/atmosphericrefraction/MultiLayerModelTest.java @@ -16,6 +16,7 @@ */ package org.orekit.rugged.atmosphericrefraction; +import org.apache.commons.math3.geometry.Vector; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.util.FastMath; import org.junit.Assert; @@ -30,6 +31,7 @@ import org.orekit.rugged.raster.TileUpdater; import org.orekit.rugged.utils.NormalizedGeodeticPoint; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class MultiLayerModelTest extends AbstractAlgorithmTest { @@ -54,9 +56,9 @@ public class MultiLayerModelTest extends AbstractAlgorithmTest { // a test with indices all set to 1.0 - correction must be zero - final int numberOfLayers = 15; + final int numberOfLayers = 16; List<ConstantRefractionLayer> refractionLayers = new ArrayList<ConstantRefractionLayer>(numberOfLayers); - for(int i = numberOfLayers; i > 0; i--) { + for(int i = numberOfLayers - 1; i >= 0; i--) { refractionLayers.add(new ConstantRefractionLayer(i * 1.0e4, 1.0)); } model = new MultiLayerModel(earth, refractionLayers); @@ -68,42 +70,43 @@ public class MultiLayerModelTest extends AbstractAlgorithmTest { // an intentionally flawed atmosphere with refractive indices decreasing with altitude, // that should exhibit a LOS bending upwards refractionLayers = new ArrayList<ConstantRefractionLayer>(numberOfLayers); - for(int i = numberOfLayers; i > 0; i--) { + for(int i = numberOfLayers - 1; i >= 0; i--) { refractionLayers.add(new ConstantRefractionLayer(i * 1.0e4, 1.0 + i*i*1e-6)); } model = new MultiLayerModel(earth, refractionLayers); correctedIntersection = model.applyCorrection(position, los, rawIntersection, algorithm); - distance = Vector3D.distance(earth.transform(rawIntersection), earth.transform(correctedIntersection)); - Assert.assertEquals(0.0, distance, 0.5); - + double anglePosRawIntersection = Vector3D.angle(position, earth.transform(rawIntersection)); + double anglePosCorrectedIntersection = Vector3D.angle(position, earth.transform(correctedIntersection)); + Assert.assertTrue(anglePosRawIntersection < anglePosCorrectedIntersection); // a comparison between two atmospheres, one more dense than the other and showing correction // is more important with high indices - List<ConstantRefractionLayer> lessDenseRefracLayers = new ArrayList<ConstantRefractionLayer>(numberOfLayers); - List<ConstantRefractionLayer> moreDenseRefracLayers = new ArrayList<ConstantRefractionLayer>(numberOfLayers); - for(int i = numberOfLayers; i > 0; i--) { + List<ConstantRefractionLayer> baseRefracLayers = new ArrayList<ConstantRefractionLayer>(numberOfLayers); + List<ConstantRefractionLayer> denserRefracLayers = new ArrayList<ConstantRefractionLayer>(numberOfLayers); + for(int i = numberOfLayers - 1; i >= 0; i--) { double baseRefractiveIndex = FastMath.pow(numberOfLayers - i + 1, 2) * 1e-6; - lessDenseRefracLayers.add(new ConstantRefractionLayer(i * 1.0e4, baseRefractiveIndex)); - moreDenseRefracLayers.add(new ConstantRefractionLayer(i * 1.0e4, baseRefractiveIndex + 1e-3)); + baseRefracLayers.add(new ConstantRefractionLayer(i * 1.0e4, baseRefractiveIndex)); + denserRefracLayers.add(new ConstantRefractionLayer(i * 1.0e4, baseRefractiveIndex + 1e-3)); } - MultiLayerModel lessDenseModel = new MultiLayerModel(earth, lessDenseRefracLayers); - MultiLayerModel moreDenseModel = new MultiLayerModel(earth, moreDenseRefracLayers); - GeodeticPoint lessDenseIntersection = lessDenseModel.applyCorrection(position, los, rawIntersection, algorithm); - GeodeticPoint moreDenseIntersection = moreDenseModel.applyCorrection(position, los, rawIntersection, algorithm); - double LDDistance = Vector3D.distance(earth.transform(rawIntersection), earth.transform(lessDenseIntersection)); - double MDDistance = Vector3D.distance(earth.transform(rawIntersection), earth.transform(moreDenseIntersection)); - - // LDDistance: 2860.295484362817, MDDistance: 251.62683758334745 - // Assert.assertTrue(MDDistance > LDDistance); + MultiLayerModel baseModel = new MultiLayerModel(earth, baseRefracLayers); + MultiLayerModel denserModel = new MultiLayerModel(earth, denserRefracLayers); + GeodeticPoint baseIntersection = baseModel.applyCorrection(position, los, rawIntersection, algorithm); + GeodeticPoint denserIntersection = denserModel.applyCorrection(position, los, rawIntersection, algorithm); + double baseDistance = Vector3D.distance(earth.transform(rawIntersection), earth.transform(baseIntersection)); + double denserDistance = Vector3D.distance(earth.transform(rawIntersection), + earth.transform(denserIntersection)); + // denserDistance: 291.6042252928431, baseDistance: 2710.1036961651967 + Assert.assertTrue(denserDistance > baseDistance); // a test with a single refraction layer refractionLayers = new ArrayList<ConstantRefractionLayer>(numberOfLayers); - refractionLayers.add(new ConstantRefractionLayer(600000, 1.2)); + refractionLayers.add(new ConstantRefractionLayer(0, 1.2)); model = new MultiLayerModel(earth, refractionLayers); correctedIntersection = model.applyCorrection(position, los, rawIntersection, algorithm); distance = Vector3D.distance(earth.transform(rawIntersection), earth.transform(correctedIntersection)); Assert.assertEquals(0.0, distance, 0.0); + } @Override diff --git a/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java b/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java index bceb8253d576d488dea378dc028171442714d0c3..62e411c53f5f95c2c73212e9eceeaf9924c63954 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