Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • orekit/rugged
  • sdinot/rugged
  • yzokras/rugged
  • youngcle/rugged-mod
4 results
Show changes
Showing
with 2205 additions and 206 deletions
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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;
import java.util.Locale;
import org.junit.Assert;
import org.junit.Test;
public class RuggedExceptionTest {
@Test
public void testTranslation() {
RuggedException re = new RuggedException(RuggedMessages.DUPLICATED_PARAMETER_NAME, "dummy");
Assert.assertFalse(re.getMessage(Locale.FRENCH).contains("parameter"));
Assert.assertTrue(re.getMessage(Locale.FRENCH).contains("paramètre"));
Assert.assertTrue(re.getMessage(Locale.FRENCH).contains("dummy"));
Assert.assertTrue(re.getMessage(Locale.US).contains("parameter"));
Assert.assertFalse(re.getMessage(Locale.US).contains("paramètre"));
Assert.assertTrue(re.getMessage(Locale.US).contains("dummy"));
Assert.assertEquals(re.getMessage(), re.getMessage(Locale.US));
}
@Test
public void testParameters() {
RuggedException re = new RuggedException(RuggedMessages.DUPLICATED_PARAMETER_NAME, "dummy");
Assert.assertEquals(RuggedMessages.DUPLICATED_PARAMETER_NAME, re.getSpecifier());
Assert.assertEquals("dummy", re.getParts()[0]);
}
@Test
public void testNullSpecifier() {
RuggedException re = new RuggedException(null, (Object[]) null);
Assert.assertEquals("", re.getMessage());
}
@Test
public void testNullParts() {
RuggedException re1 = new RuggedException(RuggedMessages.NO_PARAMETERS_SELECTED, (Object[]) null);
Assert.assertEquals(RuggedMessages.NO_PARAMETERS_SELECTED, re1.getSpecifier());
Assert.assertEquals(0, re1.getParts().length);
RuggedException re2 = new RuggedException(new RuntimeException(),
RuggedMessages.NO_PARAMETERS_SELECTED, (Object[]) null);
Assert.assertEquals(RuggedMessages.NO_PARAMETERS_SELECTED, re2.getSpecifier());
Assert.assertEquals(0, re2.getParts().length);
}
@Test
public void testInternalError() {
RuggedException re = new RuggedException(RuggedMessages.DUPLICATED_PARAMETER_NAME, "dummy");
RuntimeException rte = new RuggedInternalError(re);
Assert.assertFalse(re.getLocalizedMessage().contains("https://gitlab.orekit.org/orekit/rugged/issues"));
Assert.assertTrue(rte.getLocalizedMessage().contains("https://gitlab.orekit.org/orekit/rugged/issues"));
Assert.assertTrue(rte.getMessage().contains("https://gitlab.orekit.org/orekit/rugged/issues"));
}
@Deprecated
@Test
public void testCoverage() {
RuggedExceptionWrapper rew = new RuggedExceptionWrapper(new RuggedException(RuggedMessages.DUPLICATED_PARAMETER_NAME, "dummy"));
RuggedException re = rew.getException();
Assert.assertEquals(RuggedMessages.DUPLICATED_PARAMETER_NAME, re.getSpecifier());
Assert.assertEquals("dummy", re.getParts()[0]);
}
}
/* Copyright 2002-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.rugged.api;
package org.orekit.rugged.errors;
import java.text.MessageFormat;
......@@ -27,17 +27,18 @@ import org.junit.Test;
public class RuggedMessagesTest {
private final String[] LANGUAGES_LIST = { "da", "de", "en", "es", "fr", "gl", "it", "no", "ro" } ;
@Test
public void testMessageNumber() {
Assert.assertEquals(15, RuggedMessages.values().length);
Assert.assertEquals(35, RuggedMessages.values().length);
}
@Test
public void testAllKeysPresentInPropertiesFiles() {
for (final String language : new String[] { "de", "en", "es", "fr", "gl", "it" } ) {
for (final String language : LANGUAGES_LIST) {
ResourceBundle bundle =
ResourceBundle.getBundle("assets/org/orekit/rugged/RuggedMessages",
new Locale(language), new RuggedMessages.UTF8Control());
ResourceBundle.getBundle("assets/org/orekit/rugged/RuggedMessages",
new Locale(language), new RuggedMessages.UTF8Control());
for (RuggedMessages message : RuggedMessages.values()) {
final String messageKey = message.toString();
boolean keyPresent = false;
......@@ -54,10 +55,10 @@ public class RuggedMessagesTest {
@Test
public void testAllPropertiesCorrespondToKeys() {
for (final String language : new String[] { "de", "en", "es", "fr", "gl", "it" } ) {
for (final String language : LANGUAGES_LIST) {
ResourceBundle bundle =
ResourceBundle.getBundle("assets/org/orekit/rugged/RuggedMessages",
new Locale(language), new RuggedMessages.UTF8Control());
ResourceBundle.getBundle("assets/org/orekit/rugged/RuggedMessages",
new Locale(language), new RuggedMessages.UTF8Control());
for (final Enumeration<String> keys = bundle.getKeys(); keys.hasMoreElements();) {
final String propertyKey = keys.nextElement();
try {
......@@ -87,9 +88,29 @@ public class RuggedMessagesTest {
}
}
@Test
public void testMissingLanguageFallback() {
for (RuggedMessages message : RuggedMessages.values()) {
String translated = message.getLocalizedString(Locale.TRADITIONAL_CHINESE);
Assert.assertEquals(message.getSourceString(), translated);
}
}
@Test
public void testMissingLanguageMissingTranslation() {
Assert.assertEquals(RuggedMessages.INTERNAL_ERROR.getSourceString(),
RuggedMessages.INTERNAL_ERROR.getLocalizedString(Locale.KOREAN));
Assert.assertEquals(RuggedMessages.NO_DEM_DATA.getSourceString(),
RuggedMessages.NO_DEM_DATA.getLocalizedString(Locale.KOREAN));
Assert.assertEquals("ABCDEF {0}",
RuggedMessages.UNKNOWN_SENSOR.getLocalizedString(Locale.KOREAN));
Assert.assertEquals(RuggedMessages.EMPTY_TILE.getSourceString(),
RuggedMessages.EMPTY_TILE.getLocalizedString(Locale.KOREAN));
}
@Test
public void testVariablePartsConsistency() {
for (final String language : new String[] { "de", "en", "es", "fr", "gl", "it" } ) {
for (final String language : LANGUAGES_LIST) {
Locale locale = new Locale(language);
for (RuggedMessages message : RuggedMessages.values()) {
MessageFormat source = new MessageFormat(message.getSourceString());
......
/* Copyright 2002-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -20,25 +20,22 @@ package org.orekit.rugged.intersection;
import java.io.File;
import java.net.URISyntaxException;
import org.apache.commons.math3.geometry.euclidean.threed.Line;
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.hipparchus.geometry.euclidean.threed.Line;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.attitudes.Attitude;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.data.DataProvidersManager;
import org.orekit.data.DataContext;
import org.orekit.data.DirectoryCrawler;
import org.orekit.errors.OrekitException;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.Transform;
import org.orekit.orbits.CartesianOrbit;
import org.orekit.propagation.SpacecraftState;
import org.orekit.rugged.api.RuggedException;
import org.orekit.rugged.intersection.IntersectionAlgorithm;
import org.orekit.rugged.intersection.duvenhage.MinMaxTreeTile;
import org.orekit.rugged.intersection.duvenhage.MinMaxTreeTileFactory;
import org.orekit.rugged.raster.CliffsElevationUpdater;
......@@ -56,8 +53,7 @@ public abstract class AbstractAlgorithmTest {
protected abstract IntersectionAlgorithm createAlgorithm(TileUpdater updater, int maxCachedTiles);
@Test
public void testMayonVolcanoOnSubTileCorner()
throws RuggedException, OrekitException {
public void testMayonVolcanoOnSubTileCorner() {
setUpMayonVolcanoContext();
......@@ -94,8 +90,7 @@ public abstract class AbstractAlgorithmTest {
}
@Test
public void testMayonVolcanoWithinPixel()
throws RuggedException, OrekitException {
public void testMayonVolcanoWithinPixel() {
setUpMayonVolcanoContext();
......@@ -121,7 +116,7 @@ public abstract class AbstractAlgorithmTest {
@Test
public void testCliffsOfMoher()
throws RuggedException, OrekitException {
{
setUpCliffsOfMoherContext();
......@@ -135,6 +130,8 @@ public abstract class AbstractAlgorithmTest {
Vector3D groundP = earth.transform(groundGP);
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
Assert.assertEquals( 0.0, algorithm.getElevation(latitude, longitude - 2.0e-5), 1.0e-6);
Assert.assertEquals(120.0, algorithm.getElevation(latitude, longitude + 2.0e-5), 1.0e-6);
// preliminary check: the point has been chosen in the spacecraft (YZ) plane
Transform earthToSpacecraft = new Transform(state.getDate(),
......@@ -154,8 +151,7 @@ public abstract class AbstractAlgorithmTest {
}
protected void checkIntersection(Vector3D position, Vector3D los, GeodeticPoint intersection)
throws RuggedException {
protected void checkIntersection(Vector3D position, Vector3D los, GeodeticPoint intersection) {
// check the point is on the line
Line line = new Line(position, new Vector3D(1, position, 1e6, los), 1.0e-12);
......@@ -170,7 +166,7 @@ public abstract class AbstractAlgorithmTest {
}
protected void setUpMayonVolcanoContext()
throws RuggedException, OrekitException {
{
// Mayon Volcano location according to Wikipedia: 13°15′24″N 123°41′6″E
GeodeticPoint summit =
......@@ -218,7 +214,7 @@ public abstract class AbstractAlgorithmTest {
}
protected void setUpCliffsOfMoherContext()
throws RuggedException, OrekitException {
{
// cliffs of Moher location according to Wikipedia: 52°56′10″N 9°28′15″ W
GeodeticPoint north = new GeodeticPoint(FastMath.toRadians(52.9984),
......@@ -272,10 +268,10 @@ public abstract class AbstractAlgorithmTest {
}
@Before
public void setUp()
throws OrekitException, URISyntaxException {
public void setUp() throws URISyntaxException {
String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath();
DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(new File(path)));
DataContext.getDefault().getDataProvidersManager().addProvider(new DirectoryCrawler(new File(path)));
earth = new ExtendedEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
FramesFactory.getITRF(IERSConventions.IERS_2010, true));
......
/* Copyright 2002-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -17,8 +17,10 @@
package org.orekit.rugged.intersection;
import org.orekit.rugged.intersection.BasicScanAlgorithm;
import org.orekit.rugged.intersection.IntersectionAlgorithm;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.orekit.rugged.api.AlgorithmId;
import org.orekit.rugged.raster.TileUpdater;
public class BasicScanAlgorithmTest extends AbstractAlgorithmTest {
......@@ -27,4 +29,10 @@ public class BasicScanAlgorithmTest extends AbstractAlgorithmTest {
return new BasicScanAlgorithm(updater, maxCachedTiles);
}
@Test
public void testAlgorithmId() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
assertEquals(AlgorithmId.BASIC_SLOW_EXHAUSTIVE_SCAN_FOR_TESTS_ONLY, algorithm.getAlgorithmId());
}
}
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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.intersection;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.net.URISyntaxException;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.attitudes.Attitude;
import org.orekit.data.DataContext;
import org.orekit.data.DirectoryCrawler;
import org.orekit.frames.FramesFactory;
import org.orekit.orbits.CartesianOrbit;
import org.orekit.propagation.SpacecraftState;
import org.orekit.rugged.api.AlgorithmId;
import org.orekit.rugged.intersection.duvenhage.DuvenhageAlgorithm;
import org.orekit.rugged.raster.CheckedPatternElevationUpdater;
import org.orekit.rugged.raster.TileUpdater;
import org.orekit.rugged.utils.ExtendedEllipsoid;
import org.orekit.rugged.utils.NormalizedGeodeticPoint;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinates;
public class ConstantElevationAlgorithmTest {
@Test
public void testDuvenhageComparison() {
final Vector3D los = new Vector3D(-0.626242839, 0.0124194184, -0.7795291301);
IntersectionAlgorithm duvenhage = new DuvenhageAlgorithm(new CheckedPatternElevationUpdater(FastMath.toRadians(1.0),
256, 150.0, 150.0),
8, false);
IntersectionAlgorithm constantElevation = new ConstantElevationAlgorithm(150.0);
NormalizedGeodeticPoint gpRef = duvenhage.intersection(earth, state.getPVCoordinates().getPosition(), los);
NormalizedGeodeticPoint gpConst = constantElevation.intersection(earth, state.getPVCoordinates().getPosition(), los);
Assert.assertEquals(gpRef.getLatitude(), gpConst.getLatitude(), 1.0e-6);
Assert.assertEquals(gpRef.getLongitude(), gpConst.getLongitude(), 1.0e-6);
Assert.assertEquals(gpRef.getAltitude(), gpConst.getAltitude(), 1.0e-3);
Assert.assertEquals(150.0, constantElevation.getElevation(0.0, 0.0), 1.0e-3);
// shift longitude 2π
NormalizedGeodeticPoint shifted =
constantElevation.refineIntersection(earth, state.getPVCoordinates().getPosition(), los,
new NormalizedGeodeticPoint(gpConst.getLatitude(),
gpConst.getLongitude(),
gpConst.getAltitude(),
2 * FastMath.PI));
Assert.assertEquals(2 * FastMath.PI + gpConst.getLongitude(), shifted.getLongitude(), 1.0e-6);
}
@Test
public void testIgnoreDEMComparison() {
final Vector3D los = new Vector3D(-0.626242839, 0.0124194184, -0.7795291301);
IntersectionAlgorithm ignore = new IgnoreDEMAlgorithm();
IntersectionAlgorithm constantElevation = new ConstantElevationAlgorithm(0.0);
NormalizedGeodeticPoint gpRef = ignore.intersection(earth, state.getPVCoordinates().getPosition(), los);
NormalizedGeodeticPoint gpConst = constantElevation.intersection(earth, state.getPVCoordinates().getPosition(), los);
Assert.assertEquals(gpRef.getLatitude(), gpConst.getLatitude(), 1.0e-6);
Assert.assertEquals(gpRef.getLongitude(), gpConst.getLongitude(), 1.0e-6);
Assert.assertEquals(gpRef.getAltitude(), gpConst.getAltitude(), 1.0e-3);
Assert.assertEquals(0.0, constantElevation.getElevation(0.0, 0.0), 1.0e-3);
// shift longitude 2π
NormalizedGeodeticPoint shifted =
constantElevation.refineIntersection(earth, state.getPVCoordinates().getPosition(), los,
new NormalizedGeodeticPoint(gpConst.getLatitude(),
gpConst.getLongitude(),
gpConst.getAltitude(),
2 * FastMath.PI));
Assert.assertEquals(2 * FastMath.PI + gpConst.getLongitude(), shifted.getLongitude(), 1.0e-6);
// Simple test for test coverage purpose
double elevation0 = ignore.getElevation(gpRef.getLatitude(), gpConst.getLatitude());
Assert.assertEquals(elevation0, 0.0, 1.e-15);
}
@Test
public void testAlgorithmId() {
IntersectionAlgorithm constantElevation = new ConstantElevationAlgorithm(0.0);
assertEquals(AlgorithmId.CONSTANT_ELEVATION_OVER_ELLIPSOID, constantElevation.getAlgorithmId());
IntersectionAlgorithm ignore = new IgnoreDEMAlgorithm();
assertEquals(AlgorithmId.IGNORE_DEM_USE_ELLIPSOID, ignore.getAlgorithmId());
}
@Before
public void setUp() throws URISyntaxException {
String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath();
DataContext.getDefault().getDataProvidersManager().addProvider(new DirectoryCrawler(new File(path)));
earth = new ExtendedEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
FramesFactory.getITRF(IERSConventions.IERS_2010, true));
AbsoluteDate crossing = new AbsoluteDate("2012-01-07T11:50:04.935272115", TimeScalesFactory.getUTC());
state = new SpacecraftState(new CartesianOrbit(new PVCoordinates(new Vector3D( 412324.544397459,
-4325872.329311633,
5692124.593989491),
new Vector3D(-1293.174701214779,
-5900.764863603793,
-4378.671036383179)),
FramesFactory.getEME2000(),
crossing,
Constants.EIGEN5C_EARTH_MU),
new Attitude(crossing,
FramesFactory.getEME2000(),
new Rotation(-0.17806699079182878,
0.60143347387211290,
-0.73251248177468900,
-0.26456641385623986,
true),
new Vector3D(-4.289600857433520e-05,
-1.039151496480297e-03,
5.811423736843181e-05),
Vector3D.ZERO));
}
@After
public void tearDown() {
earth = null;
updater = null;
state = null;
}
protected ExtendedEllipsoid earth;
protected TileUpdater updater;
protected SpacecraftState state;
}
/* Copyright 2002-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -17,18 +17,22 @@
package org.orekit.rugged.intersection.duvenhage;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import static org.junit.Assert.assertEquals;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.apache.commons.math3.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.errors.OrekitException;
import org.orekit.rugged.api.RuggedException;
import org.orekit.rugged.api.RuggedMessages;
import org.orekit.rugged.api.AlgorithmId;
import org.orekit.rugged.errors.RuggedException;
import org.orekit.rugged.errors.RuggedMessages;
import org.orekit.rugged.intersection.AbstractAlgorithmTest;
import org.orekit.rugged.intersection.IntersectionAlgorithm;
import org.orekit.rugged.raster.CheckedPatternElevationUpdater;
......@@ -45,7 +49,7 @@ public class DuvenhageAlgorithmTest extends AbstractAlgorithmTest {
}
@Test
public void testNumericalIssueAtTileExit() throws RuggedException, OrekitException {
public void testNumericalIssueAtTileExit() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
Vector3D position = new Vector3D(-3787079.6453602533, 5856784.405679551, 1655869.0582939098);
......@@ -56,7 +60,7 @@ public class DuvenhageAlgorithmTest extends AbstractAlgorithmTest {
}
@Test
public void testCrossingBeforeLineSegmentStart() throws RuggedException, OrekitException {
public void testCrossingBeforeLineSegmentStart() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
Vector3D position = new Vector3D(-3787079.6453602533, 5856784.405679551, 1655869.0582939098);
......@@ -67,7 +71,7 @@ public class DuvenhageAlgorithmTest extends AbstractAlgorithmTest {
}
@Test
public void testWrongPositionMissesGround() throws RuggedException, OrekitException {
public void testWrongPositionMissesGround() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
Vector3D position = new Vector3D(7.551889113912788E9, -3.173692685491814E10, 1.5727517321541348E9);
......@@ -81,12 +85,12 @@ public class DuvenhageAlgorithmTest extends AbstractAlgorithmTest {
}
@Test
public void testInconsistentTileUpdater() throws RuggedException, OrekitException {
public void testInconsistentTileUpdater() {
final int n = 1201;
final double size = FastMath.toRadians(1.0);
updater = new TileUpdater() {
public void updateTile(double latitude, double longitude, UpdatableTile tile)
throws RuggedException {
public void updateTile(double latitude, double longitude, UpdatableTile tile) {
double step = size / (n - 1);
// this geometry is incorrect:
// the specified latitude/longitude belong to rows/columns [1, n-1]
......@@ -112,18 +116,18 @@ public class DuvenhageAlgorithmTest extends AbstractAlgorithmTest {
}
@Test
public void testPureEastWestLOS() throws RuggedException, OrekitException {
public void testPureEastWestLOS() {
updater = new CheckedPatternElevationUpdater(FastMath.toRadians(1.0),1201, 41.0, 1563.0);
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
NormalizedGeodeticPoint gp =
algorithm.intersection(earth,
new Vector3D(-3041185.154503948, 6486750.132281409, -32335.022880173332),
new Vector3D(0.5660218606298548 , -0.8233939240951769, 0.040517885584811814));
Assert.assertEquals(1164.339, gp.getAltitude(), 1.0e-3);
Assert.assertEquals(1164.35, gp.getAltitude(), 0.02);
}
@Test
public void testParallelLOS() throws RuggedException, OrekitException {
public void testParallelLOS() {
double size = 0.125;
int n = 129;
double elevation1 = 0.0;
......@@ -191,9 +195,19 @@ public class DuvenhageAlgorithmTest extends AbstractAlgorithmTest {
1.0e-6);
}
@Test
public void testAlgorithmId() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = new DuvenhageAlgorithm(updater, 8, false);
assertEquals(AlgorithmId.DUVENHAGE, algorithm.getAlgorithmId());
final IntersectionAlgorithm algorithmFlatBody = new DuvenhageAlgorithm(updater, 8, true);
assertEquals(AlgorithmId.DUVENHAGE_FLAT_BODY, algorithmFlatBody.getAlgorithmId());
}
private NormalizedGeodeticPoint findExit(IntersectionAlgorithm algorithm, Tile tile, Vector3D position, Vector3D los)
throws RuggedException, OrekitException {
private NormalizedGeodeticPoint findExit(IntersectionAlgorithm algorithm, Tile tile, Vector3D position, Vector3D los) {
try {
Method findExit = DuvenhageAlgorithm.class.getDeclaredMethod("findExit",
......
/* Copyright 2013-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -16,20 +16,23 @@
*/
package org.orekit.rugged.intersection.duvenhage;
import org.hipparchus.random.RandomGenerator;
import org.hipparchus.random.Well1024a;
import org.hipparchus.util.FastMath;
import java.io.IOException;
import java.lang.reflect.Field;
import org.apache.commons.math3.util.FastMath;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.orekit.rugged.api.RuggedException;
import org.orekit.rugged.intersection.duvenhage.MinMaxTreeTile;
import org.orekit.rugged.intersection.duvenhage.MinMaxTreeTileFactory;
import org.junit.rules.TemporaryFolder;
public class MinMaxTreeTileTest {
@Test
public void testSizeTall()
throws RuggedException, SecurityException, NoSuchFieldException,
throws SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException {
MinMaxTreeTile tile = createTile(107, 19);
Assert.assertEquals(9, tile.getLevels());
......@@ -68,7 +71,7 @@ public class MinMaxTreeTileTest {
@Test
public void testSizeFat()
throws RuggedException, SecurityException, NoSuchFieldException,
throws SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException {
MinMaxTreeTile tile = createTile(4, 7);
Assert.assertEquals(4, tile.getLevels());
......@@ -96,12 +99,12 @@ public class MinMaxTreeTileTest {
}
@Test
public void testSinglePixel() throws RuggedException {
public void testSinglePixel() {
Assert.assertEquals(0, createTile(1, 1).getLevels());
}
@Test
public void testMinMax() throws RuggedException {
public void testMinMax() {
for (int nbRows = 1; nbRows < 25; nbRows++) {
for (int nbColumns = 1; nbColumns < 25; nbColumns++) {
......@@ -133,14 +136,63 @@ public class MinMaxTreeTileTest {
}
@Test
public void testMergeLarge() throws RuggedException {
public void testLocateMinMax() {
RandomGenerator random = new Well1024a(0xca9883209c6e740cl);
for (int nbRows = 1; nbRows < 25; nbRows++) {
for (int nbColumns = 1; nbColumns < 25; nbColumns++) {
MinMaxTreeTile tile = new MinMaxTreeTileFactory().createTile();
tile.setGeometry(1.0, 2.0, 0.1, 0.2, nbRows, nbColumns);
for (int i = 0; i < nbRows; ++i) {
for (int j = 0; j < nbColumns; ++j) {
final double e = 1000.0 * random.nextDouble();
tile.setElevation(i, j, e);
}
}
tile.tileUpdateCompleted();
for (int i = 0; i < tile.getLatitudeRows(); ++i) {
for (int j = 0; j < tile.getLongitudeColumns(); ++j) {
for (int l = 0; l < tile.getLevels(); ++l) {
int[] min = tile.locateMin(i, j, l);
Assert.assertEquals(tile.getMinElevation(i, j, l),
tile.getElevationAtIndices(min[0], min[1]),
1.0e-10);
int[] max = tile.locateMax(i, j, l);
Assert.assertEquals(tile.getMaxElevation(i, j, l),
tile.getElevationAtIndices(max[0], max[1]),
1.0e-10);
}
}
}
}
}
}
@Test
public void testIssue189() {
MinMaxTreeTile tile = new MinMaxTreeTileFactory().createTile();
tile.setGeometry(1.0, 2.0, 0.1, 0.2, 2, 2);
tile.setElevation(0, 0, 1.0);
tile.setElevation(0, 1, 2.0);
tile.setElevation(1, 0, 3.0);
tile.setElevation(1, 1, 4.0);
tile.tileUpdateCompleted();
Assert.assertEquals(1.0, tile.getMinElevation(0, 0, 0), 1.0e-10);
Assert.assertEquals(3.0, tile.getMinElevation(1, 0, 0), 1.0e-10);
Assert.assertEquals(4.0, tile.getMaxElevation(0, 0, 0), 1.0e-10);
Assert.assertEquals(4.0, tile.getMaxElevation(1, 0, 0), 1.0e-10);
}
@Test
public void testMergeLarge() {
MinMaxTreeTile tile = createTile(1201, 1201);
Assert.assertEquals(21, tile.getLevels());
Assert.assertEquals( 7, tile.getMergeLevel(703, 97, 765, 59));
}
@Test
public void testMergeLevel() throws RuggedException {
public void testMergeLevel() {
for (int nbRows = 1; nbRows < 20; nbRows++) {
for (int nbColumns = 1; nbColumns < 20; nbColumns++) {
......@@ -187,7 +239,7 @@ public class MinMaxTreeTileTest {
}
@Test
public void testSubTilesLimits() throws RuggedException {
public void testSubTilesLimits() {
for (int nbRows = 1; nbRows < 25; nbRows++) {
for (int nbColumns = 1; nbColumns < 25; nbColumns++) {
......@@ -216,6 +268,17 @@ public class MinMaxTreeTileTest {
}
}
@Test
public void testForCoverage() throws IOException {
org.orekit.rugged.errors.DumpManager.activate(tempFolder.newFile());
MinMaxTreeTile tile = createTile(1201, 1201);
tile.getMinElevation(100, 100, 0);
org.orekit.rugged.errors.DumpManager.deactivate();
}
private int[] neighbors(int row, int column, int nbRows, int nbColumns, int stages) {
// poor man identification of neighbors cells merged together with specified cell
......@@ -286,7 +349,7 @@ public class MinMaxTreeTileTest {
}
private MinMaxTreeTile createTile(int nbRows, int nbColumns) throws RuggedException {
private MinMaxTreeTile createTile(int nbRows, int nbColumns) {
MinMaxTreeTile tile = new MinMaxTreeTileFactory().createTile();
tile.setGeometry(1.0, 2.0, 0.1, 0.2, nbRows, nbColumns);
for (int i = 0; i < nbRows; ++i) {
......@@ -297,5 +360,8 @@ public class MinMaxTreeTileTest {
tile.tileUpdateCompleted();
return tile;
}
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
}
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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.linesensor;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.hipparchus.analysis.UnivariateMatrixFunction;
import org.hipparchus.analysis.differentiation.DSFactory;
import org.hipparchus.analysis.differentiation.DerivativeStructure;
import org.hipparchus.analysis.differentiation.FiniteDifferencesDifferentiator;
import org.hipparchus.analysis.differentiation.UnivariateDifferentiableMatrixFunction;
import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.RotationConvention;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.random.UncorrelatedRandomVectorGenerator;
import org.hipparchus.random.UniformRandomGenerator;
import org.hipparchus.random.Well19937a;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.rugged.los.FixedRotation;
import org.orekit.rugged.los.LOSBuilder;
import org.orekit.rugged.los.TimeDependentLOS;
import org.orekit.rugged.utils.DerivativeGenerator;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.ParameterDriver;
public class FixedRotationTest {
private List<Vector3D> raw;
@Test
public void testIdentity() {
UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xaba71348a77d77cbl));
UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng);
for (int k = 0; k < 20; ++k) {
LOSBuilder builder = new LOSBuilder(raw);
builder.addTransform(new FixedRotation("identity",
new Vector3D(rvg.nextVector()),
0.0));
TimeDependentLOS tdl = builder.build();
for (int i = 0; i < raw.size(); ++i) {
Assert.assertEquals(0.0,
Vector3D.distance(raw.get(i), tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)),
2.0e-15);
}
Assert.assertEquals(1, tdl.getParametersDrivers().count());
Assert.assertEquals("identity", tdl.getParametersDrivers().findFirst().get().getName());
}
}
@Test
public void testCombination() {
UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xefac03d9be4d24b9l));
UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng);
for (int k = 0; k < 20; ++k) {
LOSBuilder builder = new LOSBuilder(raw);
Vector3D axis1 = new Vector3D(rvg.nextVector());
double angle1 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3);
builder.addTransform(new FixedRotation("r1", axis1, angle1));
Rotation r1 = new Rotation(axis1, angle1, RotationConvention.VECTOR_OPERATOR);
Vector3D axis2 = new Vector3D(rvg.nextVector());
double angle2 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3);
builder.addTransform(new FixedRotation("r2", axis2, angle2));
Rotation r2 = new Rotation(axis2, angle2, RotationConvention.VECTOR_OPERATOR);
Vector3D axis3 = new Vector3D(rvg.nextVector());
double angle3 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3);
builder.addTransform(new FixedRotation("r3", axis3, angle3));
Rotation r3 = new Rotation(axis3, angle3, RotationConvention.VECTOR_OPERATOR);
TimeDependentLOS tdl = builder.build();
Rotation combined = r3.applyTo(r2.applyTo(r1));
for (int i = 0; i < raw.size(); ++i) {
Assert.assertEquals(0.0,
Vector3D.distance(combined.applyTo(raw.get(i)),
tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)),
2.0e-15);
}
List<ParameterDriver> drivers = tdl.getParametersDrivers().collect(Collectors.toList());
Assert.assertEquals(3, drivers.size());
ParameterDriver driver1 = drivers.get(0);
ParameterDriver driver2 = drivers.get(1);
ParameterDriver driver3 = drivers.get(2);
Assert.assertEquals("r1", driver1.getName());
Assert.assertEquals(-2 * FastMath.PI, driver1.getMinValue(), 2.0e-15);
Assert.assertEquals(+2 * FastMath.PI, driver1.getMaxValue(), 2.0e-15);
Assert.assertEquals(angle1, driver1.getValue(), 2.0e-15);
Assert.assertEquals("r2", driver2.getName());
Assert.assertEquals(-2 * FastMath.PI, driver2.getMinValue(), 2.0e-15);
Assert.assertEquals(+2 * FastMath.PI, driver2.getMaxValue(), 2.0e-15);
Assert.assertEquals(angle2, driver2.getValue(), 2.0e-15);
Assert.assertEquals("r3", driver3.getName());
Assert.assertEquals(-2 * FastMath.PI, driver3.getMinValue(), 2.0e-15);
Assert.assertEquals(+2 * FastMath.PI, driver3.getMaxValue(), 2.0e-15);
Assert.assertEquals(angle3, driver3.getValue(), 2.0e-15);
driver1.setValue(0.0);
driver2.setValue(0.0);
driver3.setValue(0.0);
for (int i = 0; i < raw.size(); ++i) {
Assert.assertEquals(0.0,
Vector3D.distance(raw.get(i),
tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)),
2.0e-15);
}
}
}
@Test
public void testDerivatives() {
UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xddae2b46b2207e08l));
UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng);
for (int k = 0; k < 20; ++k) {
LOSBuilder builder = new LOSBuilder(raw);
builder.addTransform(new FixedRotation("r1",
new Vector3D(rvg.nextVector()),
2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3)));
builder.addTransform(new FixedRotation("r2",
new Vector3D(rvg.nextVector()),
2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3)));
builder.addTransform(new FixedRotation("r3",
new Vector3D(rvg.nextVector()),
2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3)));
TimeDependentLOS tdl = builder.build();
final List<ParameterDriver> selected = tdl.getParametersDrivers().collect(Collectors.toList());
for (final ParameterDriver driver : selected) {
driver.setSelected(true);
}
final DSFactory factoryS = new DSFactory(selected.size(), 1);
DerivativeGenerator<DerivativeStructure> generator = new DerivativeGenerator<DerivativeStructure>() {
/** {@inheritDoc} */
@Override
public List<ParameterDriver> getSelected() {
return selected;
}
/** {@inheritDoc} */
@Override
public DerivativeStructure constant(final double value) {
return factoryS.constant(value);
}
/** {@inheritDoc} */
@Override
public DerivativeStructure variable(final ParameterDriver driver) {
int index = 0;
for (ParameterDriver d : getSelected()) {
if (d == driver) {
return factoryS.variable(index, driver.getValue());
}
++index;
}
return constant(driver.getValue());
}
};
Assert.assertEquals(3, generator.getSelected().size());
FiniteDifferencesDifferentiator differentiator =
new FiniteDifferencesDifferentiator(4, 0.001);
int index = 0;
DSFactory factory11 = new DSFactory(1, 1);
for (final ParameterDriver driver : selected) {
int[] orders = new int[selected.size()];
orders[index] = 1;
UnivariateDifferentiableMatrixFunction f =
differentiator.differentiate((UnivariateMatrixFunction) x -> {
double oldX = driver.getValue();
double[][] matrix = new double[raw.size()][];
driver.setValue(x);
for (int i = 0 ; i < raw.size(); ++i) {
matrix[i] = tdl.getLOS(i, AbsoluteDate.J2000_EPOCH).toArray();
}
driver.setValue(oldX);
return matrix;
});
DerivativeStructure[][] mDS = f.value(factory11.variable(0, driver.getValue()));
for (int i = 0; i < raw.size(); ++i) {
Vector3D los = tdl.getLOS(i, AbsoluteDate.J2000_EPOCH);
FieldVector3D<DerivativeStructure> losDS =
tdl.getLOSDerivatives(i, AbsoluteDate.J2000_EPOCH, generator);
Assert.assertEquals(los.getX(), losDS.getX().getValue(), 2.0e-15);
Assert.assertEquals(los.getY(), losDS.getY().getValue(), 2.0e-15);
Assert.assertEquals(los.getZ(), losDS.getZ().getValue(), 2.0e-15);
Assert.assertEquals(mDS[i][0].getPartialDerivative(1), losDS.getX().getPartialDerivative(orders), 2.0e-12);
Assert.assertEquals(mDS[i][1].getPartialDerivative(1), losDS.getY().getPartialDerivative(orders), 2.0e-12);
Assert.assertEquals(mDS[i][2].getPartialDerivative(1), losDS.getZ().getPartialDerivative(orders), 2.0e-12);
}
++index;
}
}
}
@Before
public void setUp() throws URISyntaxException {
final Vector3D normal = Vector3D.PLUS_I;
final Vector3D fovCenter = Vector3D.PLUS_K;
final Vector3D cross = Vector3D.crossProduct(normal, fovCenter);
// build lists of pixels regularly spread on a perfect plane
raw = new ArrayList<Vector3D>();
for (int i = -100; i <= 100; ++i) {
final double alpha = i * 0.17 / 1000;
raw.add(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross));
}
}
}
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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.linesensor;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.hipparchus.Field;
import org.hipparchus.analysis.UnivariateMatrixFunction;
import org.hipparchus.analysis.differentiation.DSFactory;
import org.hipparchus.analysis.differentiation.DerivativeStructure;
import org.hipparchus.analysis.differentiation.FiniteDifferencesDifferentiator;
import org.hipparchus.analysis.differentiation.Gradient;
import org.hipparchus.analysis.differentiation.GradientField;
import org.hipparchus.analysis.differentiation.UnivariateDifferentiableMatrixFunction;
import org.hipparchus.analysis.polynomials.PolynomialFunction;
import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.RotationConvention;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.random.UncorrelatedRandomVectorGenerator;
import org.hipparchus.random.UniformRandomGenerator;
import org.hipparchus.random.Well19937a;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.rugged.los.LOSBuilder;
import org.orekit.rugged.los.PolynomialRotation;
import org.orekit.rugged.los.TimeDependentLOS;
import org.orekit.rugged.utils.DerivativeGenerator;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.ParameterDriver;
public class PolynomialRotationTest {
private List<Vector3D> raw;
@Test
public void testIdentity() {
UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xbe0d9b530fe7f53cl));
UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng);
for (int k = 0; k < 20; ++k) {
LOSBuilder builder = new LOSBuilder(raw);
builder.addTransform(new PolynomialRotation("identity",
new Vector3D(rvg.nextVector()),
AbsoluteDate.J2000_EPOCH, 0.0));
TimeDependentLOS tdl = builder.build();
for (int i = 0; i < raw.size(); ++i) {
Assert.assertEquals(0.0,
Vector3D.distance(raw.get(i), tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)),
2.0e-15);
}
Assert.assertEquals(1, tdl.getParametersDrivers().count());
Assert.assertEquals("identity[0]", tdl.getParametersDrivers().findFirst().get().getName());
}
}
@Test
public void testFixedCombination() {
UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xdc4cfdea38edd2bbl));
UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng);
for (int k = 0; k < 20; ++k) {
LOSBuilder builder = new LOSBuilder(raw);
Vector3D axis1 = new Vector3D(rvg.nextVector());
double angle1 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3);
builder.addTransform(new PolynomialRotation("r1", axis1, AbsoluteDate.J2000_EPOCH, angle1));
Rotation r1 = new Rotation(axis1, angle1, RotationConvention.VECTOR_OPERATOR);
Vector3D axis2 = new Vector3D(rvg.nextVector());
double angle2 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3);
builder.addTransform(new PolynomialRotation("r2", axis2, AbsoluteDate.J2000_EPOCH, angle2));
Rotation r2 = new Rotation(axis2, angle2, RotationConvention.VECTOR_OPERATOR);
Vector3D axis3 = new Vector3D(rvg.nextVector());
double angle3 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3);
builder.addTransform(new PolynomialRotation("r3", axis3, AbsoluteDate.J2000_EPOCH, angle3));
Rotation r3 = new Rotation(axis3, angle3, RotationConvention.VECTOR_OPERATOR);
TimeDependentLOS tdl = builder.build();
Rotation combined = r3.applyTo(r2.applyTo(r1));
for (int i = 0; i < raw.size(); ++i) {
Assert.assertEquals(0.0,
Vector3D.distance(combined.applyTo(raw.get(i)),
tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)),
2.0e-15);
}
List<ParameterDriver> drivers = tdl.getParametersDrivers().collect(Collectors.toList());
Assert.assertEquals(3, drivers.size());
ParameterDriver driver1 = drivers.get(0);
ParameterDriver driver2 = drivers.get(1);
ParameterDriver driver3 = drivers.get(2);
Assert.assertEquals("r1[0]", driver1.getName());
Assert.assertTrue(Double.isInfinite(driver1.getMinValue()));
Assert.assertTrue(driver1.getMinValue() < 0);
Assert.assertTrue(Double.isInfinite(driver1.getMaxValue()));
Assert.assertTrue(driver1.getMaxValue() > 0);
Assert.assertEquals(angle1, driver1.getValue(), 2.0e-15);
Assert.assertEquals("r2[0]", driver2.getName());
Assert.assertTrue(Double.isInfinite(driver2.getMinValue()));
Assert.assertTrue(driver2.getMinValue() < 0);
Assert.assertTrue(Double.isInfinite(driver2.getMaxValue()));
Assert.assertTrue(driver2.getMaxValue() > 0);
Assert.assertEquals(angle2, driver2.getValue(), 2.0e-15);
Assert.assertEquals("r3[0]", driver3.getName());
Assert.assertTrue(Double.isInfinite(driver3.getMinValue()));
Assert.assertTrue(driver3.getMinValue() < 0);
Assert.assertTrue(Double.isInfinite(driver3.getMaxValue()));
Assert.assertTrue(driver3.getMaxValue() > 0);
Assert.assertEquals(angle3, driver3.getValue(), 2.0e-15);
driver1.setValue(0.0);
driver2.setValue(0.0);
driver3.setValue(0.0);
for (int i = 0; i < raw.size(); ++i) {
Assert.assertEquals(0.0,
Vector3D.distance(raw.get(i),
tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)),
2.0e-15);
}
}
}
@Test
public void testDerivatives() {
UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xc60acfc04eb27935l));
UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng);
for (int k = 0; k < 20; ++k) {
LOSBuilder builder = new LOSBuilder(raw);
builder.addTransform(new PolynomialRotation("r1",
new Vector3D(rvg.nextVector()),
AbsoluteDate.J2000_EPOCH,
2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3),
1.0e-4 * 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3)));
builder.addTransform(new PolynomialRotation("r2",
new Vector3D(rvg.nextVector()),
AbsoluteDate.J2000_EPOCH,
new PolynomialFunction(new double[] {
2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3),
1.0e-4 * 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3),
1.0e-8 * 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3)
})));
builder.addTransform(new PolynomialRotation("r3",
new Vector3D(rvg.nextVector()),
AbsoluteDate.J2000_EPOCH,
2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3),
1.0e-4 * 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3)));
TimeDependentLOS tdl = builder.build();
final List<ParameterDriver> selected = tdl.getParametersDrivers().collect(Collectors.toList());
for (final ParameterDriver driver : selected) {
driver.setSelected(true);
}
final GradientField field = GradientField.getField(selected.size());
DerivativeGenerator<Gradient> generator = new DerivativeGenerator<Gradient>() {
/** {@inheritDoc} */
@Override
public List<ParameterDriver> getSelected() {
return selected;
}
/** {@inheritDoc} */
@Override
public Gradient constant(final double value) {
return Gradient.constant(selected.size(), value);
}
/** {@inheritDoc} */
@Override
public Gradient variable(final ParameterDriver driver) {
int index = 0;
for (ParameterDriver d : getSelected()) {
if (d == driver) {
return Gradient.variable(selected.size(), index, driver.getValue());
}
++index;
}
return constant(driver.getValue());
}
/** {@inheritDoc} */
@Override
public Field<Gradient> getField() {
return field;
}
};
Assert.assertEquals(7, generator.getSelected().size());
FiniteDifferencesDifferentiator differentiator =
new FiniteDifferencesDifferentiator(4, 0.0001);
int index = 0;
DSFactory factory11 = new DSFactory(1, 1);
final AbsoluteDate date = AbsoluteDate.J2000_EPOCH.shiftedBy(7.0);
for (final ParameterDriver driver : selected) {
int[] orders = new int[selected.size()];
orders[index] = 1;
UnivariateDifferentiableMatrixFunction f =
differentiator.differentiate((UnivariateMatrixFunction) x -> {
double oldX = driver.getValue();
double[][] matrix = new double[raw.size()][];
driver.setValue(x);
for (int i = 0 ; i < raw.size(); ++i) {
matrix[i] = tdl.getLOS(i, date).toArray();
}
driver.setValue(oldX);
return matrix;
});
DerivativeStructure[][] mDS = f.value(factory11.variable(0, driver.getValue()));
for (int i = 0; i < raw.size(); ++i) {
Vector3D los = tdl.getLOS(i, date);
FieldVector3D<Gradient> losDS = tdl.getLOSDerivatives(i, date, generator);
Assert.assertEquals(los.getX(), losDS.getX().getValue(), 2.0e-15);
Assert.assertEquals(los.getY(), losDS.getY().getValue(), 2.0e-15);
Assert.assertEquals(los.getZ(), losDS.getZ().getValue(), 2.0e-15);
Assert.assertEquals(mDS[i][0].getPartialDerivative(1), losDS.getX().getPartialDerivative(orders), 2.0e-10);
Assert.assertEquals(mDS[i][1].getPartialDerivative(1), losDS.getY().getPartialDerivative(orders), 2.0e-10);
Assert.assertEquals(mDS[i][2].getPartialDerivative(1), losDS.getZ().getPartialDerivative(orders), 2.0e-10);
}
++index;
}
}
}
@Before
public void setUp() throws URISyntaxException {
final Vector3D normal = Vector3D.PLUS_I;
final Vector3D fovCenter = Vector3D.PLUS_K;
final Vector3D cross = Vector3D.crossProduct(normal, fovCenter);
// build lists of pixels regularly spread on a perfect plane
raw = new ArrayList<Vector3D>();
for (int i = -100; i <= 100; ++i) {
final double alpha = i * 0.17 / 1000;
raw.add(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross));
}
}
}
/* Copyright 2013-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -14,67 +14,72 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.rugged.api;
package org.orekit.rugged.linesensor;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.random.Well19937a;
import org.apache.commons.math3.util.FastMath;
import org.hipparchus.geometry.euclidean.threed.Line;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.random.RandomGenerator;
import org.hipparchus.random.Well19937a;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.attitudes.NadirPointing;
import org.orekit.attitudes.YawCompensation;
import org.orekit.bodies.BodyShape;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.data.DataProvidersManager;
import org.orekit.data.DataContext;
import org.orekit.data.DirectoryCrawler;
import org.orekit.errors.OrekitException;
import org.orekit.errors.PropagationException;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.Transform;
import org.orekit.orbits.CircularOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.propagation.sampling.OrekitFixedStepHandler;
import org.orekit.rugged.api.LinearLineDatation;
import org.orekit.rugged.api.LineSensor;
import org.orekit.rugged.TestUtils;
import org.orekit.rugged.errors.RuggedException;
import org.orekit.rugged.errors.RuggedMessages;
import org.orekit.rugged.linesensor.SensorMeanPlaneCrossing.CrossingResult;
import org.orekit.rugged.los.LOSBuilder;
import org.orekit.rugged.utils.SpacecraftToObservedBody;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.AngularDerivativesFilter;
import org.orekit.utils.CartesianDerivativesFilter;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinates;
import org.orekit.utils.TimeStampedAngularCoordinates;
import org.orekit.utils.TimeStampedPVCoordinates;
public class SensorMeanPlaneCrossingTest {
@Test
public void testPerfectLine() throws RuggedException, OrekitException {
public void testPerfectLine() {
final Vector3D position = new Vector3D(1.5, Vector3D.PLUS_I);
final Vector3D normal = Vector3D.PLUS_I;
final Vector3D fovCenter = Vector3D.PLUS_K;
final Vector3D cross = Vector3D.crossProduct(normal, fovCenter);
final Vector3D position = new Vector3D(1.5, Vector3D.PLUS_I);
final Vector3D normal = Vector3D.PLUS_I;
final Vector3D fovCenter = Vector3D.PLUS_K;
final Vector3D cross = Vector3D.crossProduct(normal, fovCenter);
// build lists of pixels regularly spread on a perfect plane
final List<TimeDependentLOS> los = new ArrayList<TimeDependentLOS>();
final List<Vector3D> los = new ArrayList<Vector3D>();
for (int i = -1000; i <= 1000; ++i) {
final double alpha = i * 0.17 / 1000;
los.add(new FixedLOS(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross)));
los.add(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross));
}
final LineSensor sensor = new LineSensor("perfect line",
new LinearLineDatation(AbsoluteDate.J2000_EPOCH, 0.0, 1.0 / 1.5e-3),
position, los);
new LinearLineDatation(AbsoluteDate.J2000_EPOCH, 0.0, 1.0 / 1.5e-3),
position, new LOSBuilder(los).build());
Assert.assertEquals("perfect line", sensor.getName());
Assert.assertEquals(AbsoluteDate.J2000_EPOCH, sensor.getDate(0.0));
......@@ -87,7 +92,7 @@ public class SensorMeanPlaneCrossingTest {
}
@Test
public void testNoisyLine() throws RuggedException, OrekitException {
public void testNoisyLine() {
final RandomGenerator random = new Well19937a(0xf3ddb33785e12bdal);
final Vector3D position = new Vector3D(1.5, Vector3D.PLUS_I);
......@@ -96,7 +101,7 @@ public class SensorMeanPlaneCrossingTest {
final Vector3D cross = Vector3D.crossProduct(normal, fovCenter);
// build lists of pixels regularly spread on a perfect plane
final List<TimeDependentLOS> los = new ArrayList<TimeDependentLOS>();
final List<Vector3D> los = new ArrayList<Vector3D>();
for (int i = -1000; i <= 1000; ++i) {
final double alpha = i * 0.17 / 10 + 1.0e-5 * random.nextDouble();
final double delta = 1.0e-5 * random.nextDouble();
......@@ -104,12 +109,12 @@ public class SensorMeanPlaneCrossingTest {
final double sA = FastMath.sin(alpha);
final double cD = FastMath.cos(delta);
final double sD = FastMath.sin(delta);
los.add(new FixedLOS(new Vector3D(cA * cD, fovCenter, sA * cD, cross, sD, normal)));
los.add(new Vector3D(cA * cD, fovCenter, sA * cD, cross, sD, normal));
}
final LineSensor sensor = new LineSensor("noisy line",
new LinearLineDatation(AbsoluteDate.J2000_EPOCH, 0.0, 1.0 / 1.5e-3),
position, los);
position, new LOSBuilder(los).build());
Assert.assertEquals("noisy line", sensor.getName());
Assert.assertEquals(AbsoluteDate.J2000_EPOCH, sensor.getDate(0.0));
......@@ -121,8 +126,180 @@ public class SensorMeanPlaneCrossingTest {
}
private SpacecraftToObservedBody createInterpolator(LineSensor sensor)
throws RuggedException, OrekitException {
@Test
public void testDerivativeWithoutCorrections() {
doTestDerivative(false, false, 3.1e-11);
}
@Test
public void testDerivativeLightTimeCorrection() {
doTestDerivative(true, false, 2.4e-7);
}
@Test
public void testDerivativeAberrationOfLightCorrection() {
doTestDerivative(false, true, 1.1e-7);
}
@Test
public void testDerivativeWithAllCorrections() {
doTestDerivative(true, true, 1.4e-7);
}
private void doTestDerivative(boolean lightTimeCorrection,
boolean aberrationOfLightCorrection,
double tol) {
final Vector3D position = new Vector3D(1.5, Vector3D.PLUS_I);
final Vector3D normal = Vector3D.PLUS_I;
final Vector3D fovCenter = Vector3D.PLUS_K;
final Vector3D cross = Vector3D.crossProduct(normal, fovCenter);
// build lists of pixels regularly spread on a perfect plane
final List<Vector3D> los = new ArrayList<Vector3D>();
for (int i = -1000; i <= 1000; ++i) {
final double alpha = i * 0.17 / 1000;
los.add(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross));
}
final LineSensor sensor = new LineSensor("perfect line",
new LinearLineDatation(AbsoluteDate.J2000_EPOCH, 0.0, 1.0 / 1.5e-3),
position, new LOSBuilder(los).build());
Assert.assertEquals("perfect line", sensor.getName());
Assert.assertEquals(AbsoluteDate.J2000_EPOCH, sensor.getDate(0.0));
Assert.assertEquals(0.0, Vector3D.distance(position, sensor.getPosition()), 1.0e-15);
SensorMeanPlaneCrossing mean = new SensorMeanPlaneCrossing(sensor, createInterpolator(sensor),
0, 2000, lightTimeCorrection,
aberrationOfLightCorrection, 50, 1.0e-6);
double refLine = 1200.0;
AbsoluteDate refDate = sensor.getDate(refLine);
int refPixel= 1800;
Transform b2i = mean.getScToBody().getBodyToInertial(refDate);
Transform sc2i = mean.getScToBody().getScToInertial(refDate);
Transform sc2b = new Transform(refDate, sc2i, b2i.getInverse());
Vector3D p1 = sc2b.transformPosition(position);
Vector3D p2 = sc2b.transformPosition(new Vector3D(1, position,
1.0e6, los.get(refPixel)));
Line line = new Line(p1, p2, 0.001);
BodyShape earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
mean.getScToBody().getBodyFrame());
GeodeticPoint groundPoint = earth.getIntersectionPoint(line, p1, mean.getScToBody().getBodyFrame(), refDate);
Vector3D gpCartesian = earth.transform(groundPoint);
SensorMeanPlaneCrossing.CrossingResult result = mean.find(gpCartesian);
if (lightTimeCorrection) {
// applying corrections shifts the point with respect
// to the reference result computed from a simple model above
Assert.assertTrue(result.getLine() - refLine > 0.02);
} else if (aberrationOfLightCorrection) {
// applying corrections shifts the point with respect
// to the reference result computed from a simple model above
Assert.assertTrue(result.getLine() - refLine > 1.9);
} else {
// the simple model from which reference results have been compute applies here
Assert.assertEquals(refLine, result.getLine(), 5.0e-11* refLine);
Assert.assertEquals(0.0, result.getDate().durationFrom(refDate), 1.0e-9);
Assert.assertEquals(0.0, Vector3D.angle(los.get(refPixel), result.getTargetDirection()), 5.4e-15);
}
double deltaL = 0.5;
Transform b2scPlus = sc2b.getInverse().shiftedBy(deltaL / sensor.getRate(refLine));
Vector3D dirPlus = b2scPlus.transformPosition(gpCartesian).subtract(position).normalize();
Transform b2scMinus = sc2b.getInverse().shiftedBy(-deltaL / sensor.getRate(refLine));
Vector3D dirMinus = b2scMinus.transformPosition(gpCartesian).subtract(position).normalize();
Vector3D dirDer = new Vector3D(1.0 / (2 * deltaL), dirPlus.subtract(dirMinus));
Assert.assertEquals(0.0,
Vector3D.distance(result.getTargetDirectionDerivative(), dirDer),
tol * dirDer.getNorm());
try {
mean.getScToBody().getBodyToInertial(refDate.shiftedBy(-Constants.JULIAN_CENTURY));
Assert.fail("an exception should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.OUT_OF_TIME_RANGE, re.getSpecifier());
}
try {
mean.getScToBody().getBodyToInertial(refDate.shiftedBy(Constants.JULIAN_CENTURY));
Assert.fail("an exception should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.OUT_OF_TIME_RANGE, re.getSpecifier());
}
Assert.assertNotNull(mean.getScToBody().getBodyToInertial(refDate));
}
@Test
public void testSlowFind()
throws NoSuchMethodException,
SecurityException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
final Vector3D position = new Vector3D(1.5, Vector3D.PLUS_I);
final Vector3D normal = Vector3D.PLUS_I;
final Vector3D fovCenter = Vector3D.PLUS_K;
final Vector3D cross = Vector3D.crossProduct(normal, fovCenter);
// build lists of pixels regularly spread on a perfect plane
final List<Vector3D> los = new ArrayList<Vector3D>();
for (int i = -1000; i <= 1000; ++i) {
final double alpha = i * 0.17 / 1000;
los.add(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross));
}
final LineSensor sensor = new LineSensor("perfect line",
new LinearLineDatation(AbsoluteDate.J2000_EPOCH, 0.0, 1.0 / 1.5e-3),
position, new LOSBuilder(los).build());
Assert.assertEquals("perfect line", sensor.getName());
Assert.assertEquals(AbsoluteDate.J2000_EPOCH, sensor.getDate(0.0));
Assert.assertEquals(0.0, Vector3D.distance(position, sensor.getPosition()), 1.0e-15);
SensorMeanPlaneCrossing mean = new SensorMeanPlaneCrossing(sensor, createInterpolator(sensor),
0, 2000, true, true, 50, 1.0e-6);
double refLine = 1200.0;
AbsoluteDate refDate = sensor.getDate(refLine);
int refPixel= 1800;
Transform b2i = mean.getScToBody().getBodyToInertial(refDate);
Transform sc2i = mean.getScToBody().getScToInertial(refDate);
Transform sc2b = new Transform(refDate, sc2i, b2i.getInverse());
Vector3D p1 = sc2b.transformPosition(position);
Vector3D p2 = sc2b.transformPosition(new Vector3D(1, position,
1.0e6, los.get(refPixel)));
Line line = new Line(p1, p2, 0.001);
BodyShape earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
mean.getScToBody().getBodyFrame());
GeodeticPoint groundPoint = earth.getIntersectionPoint(line, p1, mean.getScToBody().getBodyFrame(), refDate);
Vector3D gpCartesian = earth.transform(groundPoint);
SensorMeanPlaneCrossing.CrossingResult result = mean.find(gpCartesian);
Method slowFind = SensorMeanPlaneCrossing.class.getDeclaredMethod("slowFind",
PVCoordinates.class,
Double.TYPE);
slowFind.setAccessible(true);
SensorMeanPlaneCrossing.CrossingResult slowResult =
(CrossingResult) slowFind.invoke(mean,
new PVCoordinates(gpCartesian, Vector3D.ZERO),
400.0);
Assert.assertEquals(result.getLine(), slowResult.getLine(), 2.0e-8);
Assert.assertEquals(0.0,
Vector3D.distance(result.getTargetDirection(),
slowResult.getTargetDirection()),
2.0e-13);
Assert.assertEquals(0.0,
Vector3D.distance(result.getTargetDirectionDerivative(),
slowResult.getTargetDirectionDerivative()),
1.0e-15);
}
private SpacecraftToObservedBody createInterpolator(LineSensor sensor) {
Orbit orbit = new CircularOrbit(7173352.811913891,
-4.029194321683225E-4, 0.0013530362644647786,
FastMath.toRadians(98.63218182243709),
......@@ -146,51 +323,40 @@ public class SensorMeanPlaneCrossingTest {
private List<TimeStampedPVCoordinates> orbitToPV(Orbit orbit, BodyShape earth,
AbsoluteDate minDate, AbsoluteDate maxDate,
double step)
throws PropagationException {
double step) {
Propagator propagator = new KeplerianPropagator(orbit);
propagator.setAttitudeProvider(new YawCompensation(new NadirPointing(earth)));
propagator.setAttitudeProvider(new YawCompensation(orbit.getFrame(), new NadirPointing(orbit.getFrame(), earth)));
propagator.propagate(minDate);
final List<TimeStampedPVCoordinates> list = new ArrayList<TimeStampedPVCoordinates>();
propagator.setMasterMode(step, new OrekitFixedStepHandler() {
public void init(SpacecraftState s0, AbsoluteDate t) {
}
public void handleStep(SpacecraftState currentState, boolean isLast) {
list.add(new TimeStampedPVCoordinates(currentState.getDate(),
currentState.getPVCoordinates().getPosition(),
currentState.getPVCoordinates().getVelocity(),
Vector3D.ZERO));
}
});
propagator.getMultiplexer().add(step, currentState -> list.add(new TimeStampedPVCoordinates(currentState.getDate(),
currentState.getPVCoordinates().getPosition(),
currentState.getPVCoordinates().getVelocity(),
Vector3D.ZERO)));
propagator.propagate(maxDate);
return list;
}
private List<TimeStampedAngularCoordinates> orbitToQ(Orbit orbit, BodyShape earth,
AbsoluteDate minDate, AbsoluteDate maxDate,
double step)
throws PropagationException {
double step) {
Propagator propagator = new KeplerianPropagator(orbit);
propagator.setAttitudeProvider(new YawCompensation(new NadirPointing(earth)));
propagator.setAttitudeProvider(new YawCompensation(orbit.getFrame(), new NadirPointing(orbit.getFrame(), earth)));
propagator.propagate(minDate);
final List<TimeStampedAngularCoordinates> list = new ArrayList<TimeStampedAngularCoordinates>();
propagator.setMasterMode(step, new OrekitFixedStepHandler() {
public void init(SpacecraftState s0, AbsoluteDate t) {
}
public void handleStep(SpacecraftState currentState, boolean isLast) {
list.add(new TimeStampedAngularCoordinates(currentState.getDate(),
currentState.getAttitude().getRotation(),
Vector3D.ZERO, Vector3D.ZERO));
}
});
propagator.getMultiplexer().add(step, currentState -> list.add(new TimeStampedAngularCoordinates(currentState.getDate(),
currentState.getAttitude().getRotation(),
Vector3D.ZERO, Vector3D.ZERO)));
propagator.propagate(maxDate);
return list;
}
@Before
public void setUp() throws OrekitException, URISyntaxException {
public void setUp() throws URISyntaxException {
TestUtils.clearFactories();
String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath();
DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(new File(path)));
DataContext.getDefault().getDataProvidersManager().addProvider(new DirectoryCrawler(new File(path)));
}
}
/* Copyright 2013-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -16,8 +16,7 @@
*/
package org.orekit.rugged.raster;
import org.apache.commons.math3.util.FastMath;
import org.orekit.rugged.api.RuggedException;
import org.hipparchus.util.FastMath;
public class CheckedPatternElevationUpdater implements TileUpdater {
......@@ -33,8 +32,8 @@ public class CheckedPatternElevationUpdater implements TileUpdater {
this.elevation2 = elevation2;
}
public void updateTile(double latitude, double longitude, UpdatableTile tile)
throws RuggedException {
public void updateTile(double latitude, double longitude, UpdatableTile tile) {
double step = size / (n - 1);
double minLatitude = size * FastMath.floor(latitude / size);
double minLongitude = size * FastMath.floor(longitude / size);
......
/* Copyright 2013-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -16,9 +16,8 @@
*/
package org.orekit.rugged.raster;
import org.apache.commons.math3.util.FastMath;
import org.hipparchus.util.FastMath;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.rugged.api.RuggedException;
public class CliffsElevationUpdater implements TileUpdater {
......@@ -40,8 +39,8 @@ public class CliffsElevationUpdater implements TileUpdater {
this.n = n;
}
public void updateTile(double latitude, double longitude, UpdatableTile tile)
throws RuggedException {
public void updateTile(double latitude, double longitude, UpdatableTile tile) {
double step = size / (n - 1);
double minLatitude = size * FastMath.floor(latitude / size);
double minLongitude = size * FastMath.floor(longitude / size);
......
/* Copyright 2013-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -16,10 +16,6 @@
*/
package org.orekit.rugged.raster;
import org.orekit.rugged.raster.SimpleTile;
import org.orekit.rugged.raster.SimpleTileFactory;
import org.orekit.rugged.raster.TileFactory;
public class CountingFactory implements TileFactory<SimpleTile> {
private int count;
......
/* Copyright 2013-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -16,13 +16,12 @@
*/
package org.orekit.rugged.raster;
import org.apache.commons.math3.exception.MathIllegalArgumentException;
import org.apache.commons.math3.exception.util.LocalizedFormats;
import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.random.Well19937a;
import org.apache.commons.math3.util.ArithmeticUtils;
import org.apache.commons.math3.util.FastMath;
import org.orekit.rugged.api.RuggedException;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.hipparchus.exception.MathIllegalArgumentException;
import org.hipparchus.random.RandomGenerator;
import org.hipparchus.random.Well19937a;
import org.hipparchus.util.ArithmeticUtils;
import org.hipparchus.util.FastMath;
public class RandomLandscapeUpdater implements TileUpdater {
......@@ -30,13 +29,20 @@ public class RandomLandscapeUpdater implements TileUpdater {
private int n;
private double[][] heightMap;
/**
* @param baseH elevation of the base of DEM; unit = m
* @param initialScale
* @param reductionFactor for smoothing for low value (0.1) or not (0.5 for instance) the landscape
* @param seed
* @param size size in latitude / size in longitude (rad)
* @param n number of latitude / number of longitude
*/
public RandomLandscapeUpdater(double baseH, double initialScale, double reductionFactor,
long seed, double size, int n)
throws MathIllegalArgumentException {
long seed, double size, int n) {
if (!ArithmeticUtils.isPowerOfTwo(n - 1)) {
throw new MathIllegalArgumentException(LocalizedFormats.SIMPLE_MESSAGE,
"tile size must be a power of two plus one");
throw new MathIllegalArgumentException(LocalizedCoreFormats.SIMPLE_MESSAGE,
"tile size must be a power of two plus one");
}
this.size = size;
......@@ -65,7 +71,7 @@ public class RandomLandscapeUpdater implements TileUpdater {
i - span / 2, j + span / 2,
i + span / 2, j - span / 2,
i + span / 2, j + span / 2) +
scale * (random.nextDouble() - 0.5);
scale * (random.nextDouble() - 0.5);
heightMap[i][j] = middleH;
}
}
......@@ -78,7 +84,7 @@ public class RandomLandscapeUpdater implements TileUpdater {
i + span / 2, j,
i, j - span / 2,
i, j + span / 2) +
scale * (random.nextDouble() - 0.5);
scale * (random.nextDouble() - 0.5);
heightMap[i][j] = middleH;
if (i == 0) {
heightMap[n - 1][j] = middleH;
......@@ -97,9 +103,9 @@ public class RandomLandscapeUpdater implements TileUpdater {
}
public void updateTile(double latitude, double longitude, UpdatableTile tile)
throws RuggedException {
@Override
public void updateTile(double latitude, double longitude, UpdatableTile tile) {
double step = size / (n - 1);
double minLatitude = size * FastMath.floor(latitude / size);
double minLongitude = size * FastMath.floor(longitude / size);
......@@ -109,14 +115,13 @@ public class RandomLandscapeUpdater implements TileUpdater {
tile.setElevation(i, j, heightMap[i][j]);
}
}
}
private double mean(int i1, int j1, int i2, int j2, int i3, int j3, int i4, int j4) {
return (heightMap[(i1 + n) % n][(j1 + n) % n] +
heightMap[(i2 + n) % n][(j2 + n) % n] +
heightMap[(i3 + n) % n][(j3 + n) % n] +
heightMap[(i4 + n) % n][(j4 + n) % n]) / 4;
heightMap[(i2 + n) % n][(j2 + n) % n] +
heightMap[(i3 + n) % n][(j3 + n) % n] +
heightMap[(i4 + n) % n][(j4 + n) % n]) / 4;
}
}
/* Copyright 2013-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -16,17 +16,16 @@
*/
package org.orekit.rugged.raster;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.apache.commons.math3.util.FastMath;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.hipparchus.util.MathUtils;
import org.junit.Assert;
import org.junit.Test;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.rugged.api.RuggedException;
import org.orekit.rugged.api.RuggedMessages;
import org.orekit.rugged.raster.SimpleTile;
import org.orekit.rugged.raster.SimpleTileFactory;
import org.orekit.rugged.raster.Tile;
import org.orekit.rugged.errors.RuggedException;
import org.orekit.rugged.errors.RuggedMessages;
import org.orekit.rugged.raster.Tile.Location;
import org.orekit.rugged.utils.NormalizedGeodeticPoint;
public class SimpleTileTest {
......@@ -65,7 +64,7 @@ public class SimpleTileTest {
}
@Test
public void testUpdate() throws RuggedException {
public void testUpdate() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(1.0, 2.0, 0.1, 0.2, 100, 200);
......@@ -103,7 +102,7 @@ public class SimpleTileTest {
}
@Test
public void testOutOfBoundsIndices() throws RuggedException {
public void testOutOfBoundsIndices() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(1.0, 2.0, 0.1, 0.2, 100, 200);
......@@ -116,7 +115,7 @@ public class SimpleTileTest {
}
@Test
public void testIndexShift() throws RuggedException {
public void testIndexShift() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(1.0, 2.0, 0.1, 0.2, 100, 200);
......@@ -164,7 +163,7 @@ public class SimpleTileTest {
}
@Test
public void testInterpolation() throws RuggedException {
public void testInterpolation() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 1.0, 1.0, 50, 50);
tile.setElevation(20, 14, 91.0);
......@@ -173,12 +172,13 @@ public class SimpleTileTest {
tile.setElevation(21, 15, 95.0);
tile.tileUpdateCompleted();
Assert.assertEquals(150.5, tile.interpolateElevation(20.0, 14.5), 1.0e-10);
Assert.assertEquals(128.5, tile.interpolateElevation(21.0, 14.5), 1.0e-10);
Assert.assertEquals(128.5, tile.interpolateElevation(FastMath.nextDown(21.0), 14.5), 1.0e-10);
Assert.assertTrue(Double.isNaN(tile.interpolateElevation(FastMath.nextUp(21.0), 14.5)));
Assert.assertEquals(146.1, tile.interpolateElevation(20.2, 14.5), 1.0e-10);
}
@Test
public void testInterpolationWithinTolerance() throws RuggedException {
public void testInterpolationWithinTolerance() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 1.0, 1.0, 2, 2);
tile.setElevation(0, 0, 91.0);
......@@ -194,7 +194,7 @@ public class SimpleTileTest {
}
@Test
public void testInterpolationOutOfTolerance() throws RuggedException {
public void testInterpolationOutOfTolerance() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 1.0, 1.0, 2, 2);
tile.setElevation(0, 0, 91.0);
......@@ -210,7 +210,7 @@ public class SimpleTileTest {
}
@Test
public void testCellIntersection() throws RuggedException {
public void testCellIntersection() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 0.025, 0.025, 50, 50);
tile.setElevation(20, 14, 91.0);
......@@ -218,16 +218,16 @@ public class SimpleTileTest {
tile.setElevation(21, 14, 162.0);
tile.setElevation(21, 15, 95.0);
tile.tileUpdateCompleted();
GeodeticPoint gpA = new GeodeticPoint(tile.getLatitudeAtIndex(20) + 0.1 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.2 * tile.getLongitudeStep(),
300.0);
GeodeticPoint gpB = new GeodeticPoint(tile.getLatitudeAtIndex(20) + 0.7 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.9 * tile.getLongitudeStep(),
10.0);
GeodeticPoint gpIAB = tile.cellIntersection(gpA, los(gpA, gpB), 20, 14);
NormalizedGeodeticPoint gpA = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(20) + 0.1 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.2 * tile.getLongitudeStep(),
300.0, tile.getLongitudeAtIndex(14));
NormalizedGeodeticPoint gpB = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(20) + 0.7 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.9 * tile.getLongitudeStep(),
10.0, tile.getLongitudeAtIndex(14));
NormalizedGeodeticPoint gpIAB = tile.cellIntersection(gpA, los(gpA, gpB), 20, 14);
checkInLine(gpA, gpB, gpIAB);
checkOnTile(tile, gpIAB);
GeodeticPoint gpIBA = tile.cellIntersection(gpB, los(gpB, gpA), 20, 14);
NormalizedGeodeticPoint gpIBA = tile.cellIntersection(gpB, los(gpB, gpA), 20, 14);
checkInLine(gpA, gpB, gpIBA);
checkOnTile(tile, gpIBA);
......@@ -238,7 +238,7 @@ public class SimpleTileTest {
}
@Test
public void testCellIntersection2Solutions() throws RuggedException {
public void testCellIntersection2PiWrapping() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 0.025, 0.025, 50, 50);
tile.setElevation(20, 14, 91.0);
......@@ -246,19 +246,47 @@ public class SimpleTileTest {
tile.setElevation(21, 14, 162.0);
tile.setElevation(21, 15, 95.0);
tile.tileUpdateCompleted();
GeodeticPoint gpA = new GeodeticPoint(tile.getLatitudeAtIndex(20) + 0.1 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.2 * tile.getLongitudeStep(),
120.0);
GeodeticPoint gpB = new GeodeticPoint(tile.getLatitudeAtIndex(20) + 0.7 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.9 * tile.getLongitudeStep(),
130.0);
NormalizedGeodeticPoint gpA = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(20) + 0.1 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.2 * tile.getLongitudeStep(),
300.0, +4 * FastMath.PI);
NormalizedGeodeticPoint gpB = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(20) + 0.7 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.9 * tile.getLongitudeStep(),
10.0, +4 * FastMath.PI);
NormalizedGeodeticPoint gpIAB = tile.cellIntersection(gpA, los(gpA, gpB), 20, 14);
checkInLine(gpA, gpB, gpIAB);
checkOnTile(tile, gpIAB);
NormalizedGeodeticPoint gpIBA = tile.cellIntersection(gpB, los(gpB, gpA), 20, 14);
checkInLine(gpA, gpB, gpIBA);
checkOnTile(tile, gpIBA);
Assert.assertEquals(gpIAB.getLatitude(), gpIBA.getLatitude(), 1.0e-10);
Assert.assertEquals(gpIAB.getLongitude(), gpIBA.getLongitude(), 1.0e-10);
Assert.assertEquals(gpIAB.getAltitude(), gpIBA.getAltitude(), 1.0e-10);
}
@Test
public void testCellIntersection2Solutions() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 0.025, 0.025, 50, 50);
tile.setElevation(20, 14, 91.0);
tile.setElevation(20, 15, 210.0);
tile.setElevation(21, 14, 162.0);
tile.setElevation(21, 15, 95.0);
tile.tileUpdateCompleted();
NormalizedGeodeticPoint gpA = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(20) + 0.1 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.2 * tile.getLongitudeStep(),
120.0, tile.getLongitudeAtIndex(14));
NormalizedGeodeticPoint gpB = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(20) + 0.7 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.9 * tile.getLongitudeStep(),
130.0, tile.getLongitudeAtIndex(14));
// the line from gpA to gpB should traverse the DEM twice within the tile
// we use the points in the two different orders to retrieve both solutions
GeodeticPoint gpIAB = tile.cellIntersection(gpA, los(gpA, gpB), 20, 14);
NormalizedGeodeticPoint gpIAB = tile.cellIntersection(gpA, los(gpA, gpB), 20, 14);
checkInLine(gpA, gpB, gpIAB);
checkOnTile(tile, gpIAB);
GeodeticPoint gpIBA = tile.cellIntersection(gpB, los(gpB, gpA), 20, 14);
NormalizedGeodeticPoint gpIBA = tile.cellIntersection(gpB, los(gpB, gpA), 20, 14);
checkInLine(gpA, gpB, gpIBA);
checkOnTile(tile, gpIBA);
......@@ -269,7 +297,7 @@ public class SimpleTileTest {
}
@Test
public void testCellIntersectionNoSolutions() throws RuggedException {
public void testCellIntersectionNoSolutions() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 0.025, 0.025, 50, 50);
tile.setElevation(20, 14, 91.0);
......@@ -277,19 +305,19 @@ public class SimpleTileTest {
tile.setElevation(21, 14, 162.0);
tile.setElevation(21, 15, 95.0);
tile.tileUpdateCompleted();
GeodeticPoint gpA = new GeodeticPoint(tile.getLatitudeAtIndex(20) + 0.1 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.2 * tile.getLongitudeStep(),
180.0);
GeodeticPoint gpB = new GeodeticPoint(tile.getLatitudeAtIndex(20) + 0.7 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.9 * tile.getLongitudeStep(),
190.0);
NormalizedGeodeticPoint gpA = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(20) + 0.1 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.2 * tile.getLongitudeStep(),
180.0, tile.getLongitudeAtIndex(14));
NormalizedGeodeticPoint gpB = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(20) + 0.7 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(14) + 0.9 * tile.getLongitudeStep(),
190.0, tile.getLongitudeAtIndex(14));
Assert.assertNull(tile.cellIntersection(gpA, los(gpA, gpB), 20, 14));
}
@Test
public void testCellIntersectionLinearOnly() throws RuggedException {
public void testCellIntersectionLinearOnly() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 0.025, 0.025, 50, 50);
tile.setElevation(0, 0, 30.0);
......@@ -297,17 +325,17 @@ public class SimpleTileTest {
tile.setElevation(1, 0, 40.0);
tile.setElevation(1, 1, 40.0);
tile.tileUpdateCompleted();
GeodeticPoint gpA = new GeodeticPoint(tile.getLatitudeAtIndex(0) + 0.25 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
50.0);
GeodeticPoint gpB = new GeodeticPoint(tile.getLatitudeAtIndex(0) + 0.75 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
20.0);
GeodeticPoint gpIAB = tile.cellIntersection(gpA, los(gpA, gpB), 0, 0);
NormalizedGeodeticPoint gpA = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(0) + 0.25 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
50.0, tile.getLongitudeAtIndex(0));
NormalizedGeodeticPoint gpB = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(0) + 0.75 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
20.0, tile.getLongitudeAtIndex(0));
NormalizedGeodeticPoint gpIAB = tile.cellIntersection(gpA, los(gpA, gpB), 0, 0);
checkInLine(gpA, gpB, gpIAB);
checkOnTile(tile, gpIAB);
GeodeticPoint gpIBA = tile.cellIntersection(gpB, los(gpB, gpA), 0, 0);
NormalizedGeodeticPoint gpIBA = tile.cellIntersection(gpB, los(gpB, gpA), 0, 0);
checkInLine(gpA, gpB, gpIBA);
checkOnTile(tile, gpIBA);
......@@ -318,7 +346,7 @@ public class SimpleTileTest {
}
@Test
public void testCellIntersectionLinearIntersectionOutside() throws RuggedException {
public void testCellIntersectionLinearIntersectionOutside() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 0.025, 0.025, 50, 50);
tile.setElevation(0, 0, 30.0);
......@@ -326,19 +354,19 @@ public class SimpleTileTest {
tile.setElevation(1, 0, 40.0);
tile.setElevation(1, 1, 40.0);
tile.tileUpdateCompleted();
GeodeticPoint gpA = new GeodeticPoint(tile.getLatitudeAtIndex(0) + 0.25 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
45.0);
GeodeticPoint gpB = new GeodeticPoint(tile.getLatitudeAtIndex(0) + 0.75 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
55.0);
NormalizedGeodeticPoint gpA = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(0) + 0.25 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
45.0, tile.getLongitudeAtIndex(0));
NormalizedGeodeticPoint gpB = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(0) + 0.75 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
55.0, tile.getLongitudeAtIndex(0));
Assert.assertNull(tile.cellIntersection(gpA, los(gpA, gpB), 0, 0));
}
@Test
public void testCellIntersectionLinearNoIntersection() throws RuggedException {
public void testCellIntersectionLinearNoIntersection() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 0.025, 0.025, 50, 50);
tile.setElevation(0, 0, 30.0);
......@@ -346,19 +374,19 @@ public class SimpleTileTest {
tile.setElevation(1, 0, 40.0);
tile.setElevation(1, 1, 40.0);
tile.tileUpdateCompleted();
GeodeticPoint gpA = new GeodeticPoint(tile.getLatitudeAtIndex(0) + 0.25 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
45.0);
GeodeticPoint gpB = new GeodeticPoint(tile.getLatitudeAtIndex(0) + 0.75 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
50.0);
NormalizedGeodeticPoint gpA = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(0) + 0.25 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
45.0, tile.getLongitudeAtIndex(0));
NormalizedGeodeticPoint gpB = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(0) + 0.75 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
50.0, tile.getLongitudeAtIndex(0));
Assert.assertNull(tile.cellIntersection(gpA, los(gpA, gpB), 0, 0));
}
@Test
public void testCellIntersectionConstant0() throws RuggedException {
public void testCellIntersectionConstant0() {
SimpleTile tile = new SimpleTileFactory().createTile();
tile.setGeometry(0.0, 0.0, 0.025, 0.025, 50, 50);
tile.setElevation(0, 0, 30.0);
......@@ -366,17 +394,17 @@ public class SimpleTileTest {
tile.setElevation(1, 0, 40.0);
tile.setElevation(1, 1, 40.0);
tile.tileUpdateCompleted();
GeodeticPoint gpA = new GeodeticPoint(tile.getLatitudeAtIndex(0) + 0.25 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
32.5);
GeodeticPoint gpB = new GeodeticPoint(tile.getLatitudeAtIndex(0) + 0.75 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
37.5);
GeodeticPoint gpIAB = tile.cellIntersection(gpA, los(gpA, gpB), 0, 0);
NormalizedGeodeticPoint gpA = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(0) + 0.25 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
32.5, tile.getLongitudeAtIndex(0));
NormalizedGeodeticPoint gpB = new NormalizedGeodeticPoint(tile.getLatitudeAtIndex(0) + 0.75 * tile.getLatitudeStep(),
tile.getLongitudeAtIndex(0) + 0.50 * tile.getLongitudeStep(),
37.5, tile.getLongitudeAtIndex(0));
NormalizedGeodeticPoint gpIAB = tile.cellIntersection(gpA, los(gpA, gpB), 0, 0);
checkInLine(gpA, gpB, gpIAB);
checkOnTile(tile, gpIAB);
GeodeticPoint gpIBA = tile.cellIntersection(gpB, los(gpB, gpA), 0, 0);
NormalizedGeodeticPoint gpIBA = tile.cellIntersection(gpB, los(gpB, gpA), 0, 0);
checkInLine(gpA, gpB, gpIBA);
checkOnTile(tile, gpIBA);
......@@ -434,16 +462,14 @@ public class SimpleTileTest {
1.0e-10);
Assert.assertEquals(gpI.getLongitude(),
gpA.getLongitude() * (1 - t) + gpB.getLongitude() * t,
MathUtils.normalizeAngle(gpA.getLongitude() * (1 - t) + gpB.getLongitude() * t, gpI.getLongitude()),
1.0e-10);
}
private void checkOnTile(Tile tile, GeodeticPoint gpI)
throws RuggedException {
private void checkOnTile(Tile tile, GeodeticPoint gpI) {
Assert.assertEquals(gpI.getAltitude(),
tile.interpolateElevation(gpI.getLatitude(), gpI.getLongitude()),
1.0e-10);
}
}
/* Copyright 2013-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -16,19 +16,16 @@
*/
package org.orekit.rugged.raster;
import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.random.Well19937a;
import org.apache.commons.math3.util.FastMath;
import org.hipparchus.random.RandomGenerator;
import org.hipparchus.random.Well19937a;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
import org.orekit.rugged.api.RuggedException;
import org.orekit.rugged.raster.SimpleTile;
import org.orekit.rugged.raster.TilesCache;
public class TilesCacheTest {
@Test
public void testSingleTile() throws RuggedException {
public void testSingleTile() {
CountingFactory factory = new CountingFactory();
TilesCache<SimpleTile> cache = new TilesCache<SimpleTile>(factory,
new CheckedPatternElevationUpdater(FastMath.toRadians(3.0), 11, 10.0, 20.0), 1000);
......@@ -43,7 +40,7 @@ public class TilesCacheTest {
}
@Test
public void testEviction() throws RuggedException {
public void testEviction() {
CountingFactory factory = new CountingFactory();
TilesCache<SimpleTile> cache = new TilesCache<SimpleTile>(factory,
new CheckedPatternElevationUpdater(FastMath.toRadians(1.0), 11, 10.0, 20.0), 12);
......@@ -65,6 +62,13 @@ public class TilesCacheTest {
}
Assert.assertEquals(12, factory.getCount());
// ensure the (0.0, 0.0) tile is the least recently used one
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 3; ++j) {
cache.getTile(FastMath.toRadians(0.5 + j), FastMath.toRadians(0.5 + i));
}
}
// ask for one point outside of the covered area, to evict the (0.0, 0.0) tile
cache.getTile(FastMath.toRadians(20.5), FastMath.toRadians(30.5));
Assert.assertEquals(13, factory.getCount());
......@@ -88,7 +92,7 @@ public class TilesCacheTest {
}
@Test
public void testExactEnd() throws RuggedException {
public void testExactEnd() {
CountingFactory factory = new CountingFactory();
TilesCache<SimpleTile> cache =
new TilesCache<SimpleTile>(factory,
......@@ -116,7 +120,7 @@ public class TilesCacheTest {
}
@Test
public void testNonContiguousFill() throws RuggedException {
public void testNonContiguousFill() {
CountingFactory factory = new CountingFactory();
TilesCache<SimpleTile> cache =
new TilesCache<SimpleTile>(factory,
......
/* Copyright 2013-2014 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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
......@@ -16,9 +16,8 @@
*/
package org.orekit.rugged.raster;
import org.apache.commons.math3.util.FastMath;
import org.hipparchus.util.FastMath;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.rugged.api.RuggedException;
import org.orekit.utils.Constants;
public class VolcanicConeElevationUpdater implements TileUpdater {
......@@ -38,8 +37,8 @@ public class VolcanicConeElevationUpdater implements TileUpdater {
this.n = n;
}
public void updateTile(double latitude, double longitude, UpdatableTile tile)
throws RuggedException {
public void updateTile(double latitude, double longitude, UpdatableTile tile) {
double step = size / (n - 1);
double minLatitude = size * FastMath.floor(latitude / size);
double minLongitude = size * FastMath.floor(longitude / size);
......@@ -58,5 +57,4 @@ public class VolcanicConeElevationUpdater implements TileUpdater {
}
}
}
}
package org.orekit.rugged.refraction;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import org.hipparchus.analysis.differentiation.Derivative;
import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.RotationConvention;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
import org.orekit.bodies.BodyShape;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.data.DataContext;
import org.orekit.data.DirectoryCrawler;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.models.earth.ReferenceEllipsoid;
import org.orekit.orbits.Orbit;
import org.orekit.rugged.TestUtils;
import org.orekit.rugged.api.AlgorithmId;
import org.orekit.rugged.api.BodyRotatingFrameId;
import org.orekit.rugged.api.EllipsoidId;
import org.orekit.rugged.api.InertialFrameId;
import org.orekit.rugged.api.Rugged;
import org.orekit.rugged.api.RuggedBuilder;
import org.orekit.rugged.errors.RuggedException;
import org.orekit.rugged.errors.RuggedMessages;
import org.orekit.rugged.linesensor.LineDatation;
import org.orekit.rugged.linesensor.LineSensor;
import org.orekit.rugged.linesensor.LinearLineDatation;
import org.orekit.rugged.linesensor.SensorPixel;
import org.orekit.rugged.los.LOSBuilder;
import org.orekit.rugged.los.TimeDependentLOS;
import org.orekit.rugged.raster.RandomLandscapeUpdater;
import org.orekit.rugged.raster.TileUpdater;
import org.orekit.rugged.utils.DerivativeGenerator;
import org.orekit.rugged.utils.GeodeticUtilities;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.AngularDerivativesFilter;
import org.orekit.utils.CartesianDerivativesFilter;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.ParameterDriver;
import org.orekit.utils.TimeStampedAngularCoordinates;
import org.orekit.utils.TimeStampedPVCoordinates;
public class AtmosphericRefractionTest {
@Test
public void testAtmosphericRefractionCorrection() throws URISyntaxException {
String sensorName = "line";
int dimension = 4000;
RuggedBuilder builder = initRuggedForAtmosphericTests(dimension, sensorName);
// Build Rugged without atmospheric refraction model
Rugged ruggedWithout = builder.build();
// Defines atmospheric refraction model (with the default multi layers model)
AtmosphericRefraction atmosphericRefraction = new MultiLayerModel(ruggedWithout.getEllipsoid());
int pixelStep = 100;
int lineStep = 100;
atmosphericRefraction.setGridSteps(pixelStep, lineStep);
// Build Rugged with atmospheric refraction model
builder.setRefractionCorrection(atmosphericRefraction);
Rugged ruggedWith = builder.build();
// For test coverage
assertTrue(ruggedWith.getRefractionCorrection().getClass().isInstance(new MultiLayerModel(ruggedWith.getEllipsoid())));
LineSensor lineSensor = ruggedWithout.getLineSensor(sensorName);
int minLine = (int) FastMath.floor(lineSensor.getLine(ruggedWithout.getMinDate()));
int maxLine = (int) FastMath.ceil(lineSensor.getLine(ruggedWithout.getMaxDate()));
final double pixelThreshold = 1.e-3;
final double lineThreshold = 1.e-2;
final double epsilonPixel = pixelThreshold;
final double epsilonLine = lineThreshold;
double earthRadius = ruggedWithout.getEllipsoid().getEquatorialRadius();
// Direct loc on a line WITHOUT and WITH atmospheric correction
// ============================================================
double chosenLine = 200.;
GeodeticPoint[] gpWithoutAtmosphericRefractionCorrection = ruggedWithout.directLocation(sensorName, chosenLine);
GeodeticPoint[] gpWithAtmosphericRefractionCorrection = ruggedWith.directLocation(sensorName, chosenLine);
// Check the shift on the ground due to atmospheric correction
for (int i = 0; i < gpWithAtmosphericRefractionCorrection.length; i++) {
double currentRadius = earthRadius + (gpWithAtmosphericRefractionCorrection[i].getAltitude()+ gpWithoutAtmosphericRefractionCorrection[i].getAltitude())/2.;
double distance = GeodeticUtilities.computeDistanceInMeter(currentRadius, gpWithAtmosphericRefractionCorrection[i], gpWithoutAtmosphericRefractionCorrection[i]);
// Check if the distance is not 0 and < 2m
Assert.assertTrue(distance > 0.0);
Assert.assertTrue(distance < 2.);
}
// Inverse loc WITH atmospheric correction
// ==========================================================================
for (int i = 0; i < gpWithAtmosphericRefractionCorrection.length; i++) {
// to check if we go back to the initial point when taking the geodetic point with atmospheric correction
GeodeticPoint gpWith = gpWithAtmosphericRefractionCorrection[i];
SensorPixel sensorPixelReverseWith = ruggedWith.inverseLocation(sensorName, gpWith, minLine, maxLine);
if (sensorPixelReverseWith != null) {
assertEquals(i, sensorPixelReverseWith.getPixelNumber(), epsilonPixel);
assertEquals(chosenLine, sensorPixelReverseWith.getLineNumber(), epsilonLine);
} else {
fail("Inverse location failed for pixel " + i + " with atmospheric refraction correction for geodetic point computed with" );
}
} // end loop on pixel i
// For test coverage
double dummyLat = gpWithAtmosphericRefractionCorrection[0].getLatitude() + FastMath.PI/4.;
double dummyLon = gpWithAtmosphericRefractionCorrection[0].getLongitude() - FastMath.PI/4.;
GeodeticPoint dummyGP = new GeodeticPoint(dummyLat, dummyLon, 0.);
try {
ruggedWith.inverseLocation(sensorName, dummyGP, minLine, maxLine);
Assert.fail("an exeption should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.SENSOR_PIXEL_NOT_FOUND_IN_RANGE_LINES, re.getSpecifier());
}
try {
ruggedWith.inverseLocation(sensorName,
gpWithAtmosphericRefractionCorrection[0],
210, maxLine);
Assert.fail("an exeption should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.SENSOR_PIXEL_NOT_FOUND_IN_RANGE_LINES, re.getSpecifier());
}
try {
ruggedWith.inverseLocation(sensorName,
gpWithAtmosphericRefractionCorrection[0],
minLine, 190);
Assert.fail("an exeption should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.SENSOR_PIXEL_NOT_FOUND_IN_RANGE_LINES, re.getSpecifier());
}
}
private RuggedBuilder initRuggedForAtmosphericTests(final int dimension, final String sensorName) throws URISyntaxException {
String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath();
DataContext.getDefault().getDataProvidersManager().addProvider(new DirectoryCrawler(new File(path)));
final BodyShape earth = TestUtils.createEarth();
final Orbit orbit = TestUtils.createOrbit(Constants.EIGEN5C_EARTH_MU);
// one line sensor
// position: 1.5m in front (+X) and 20 cm above (-Z) of the S/C center of mass
// los: swath in the (YZ) plane, looking at 5° roll, 2.6" per pixel
Vector3D position = new Vector3D(1.5, 0, -0.2);
TimeDependentLOS los = TestUtils.createLOSPerfectLine(new Rotation(Vector3D.PLUS_I,
FastMath.toRadians(5.0),
RotationConvention.VECTOR_OPERATOR).applyTo(Vector3D.PLUS_K),
Vector3D.PLUS_I,
FastMath.toRadians((dimension/2.) * 2.6 / 3600.0), dimension).build();
// With the orbit (795km), the size of the pixel on the ground is around : 10m
// linear datation model: at reference time we get the middle line, and the rate is one line every 1.5ms
AbsoluteDate crossing = new AbsoluteDate("2012-01-01T12:30:00.000", TimeScalesFactory.getUTC());
LineDatation lineDatation = new LinearLineDatation(crossing, dimension / 2, 1.0 / 1.5e-3);
int firstLine = 0;
int lastLine = dimension;
LineSensor lineSensor = new LineSensor(sensorName, lineDatation, position, los);
AbsoluteDate minDate = lineSensor.getDate(firstLine).shiftedBy(-1.0);
AbsoluteDate maxDate = lineSensor.getDate(lastLine).shiftedBy(+1.0);
TileUpdater updater = new RandomLandscapeUpdater(800.0, 9000.0, 0.1, 0xf0a401650191f9f6l, FastMath.toRadians(2.0), 257);
RuggedBuilder builder = new RuggedBuilder().
setDigitalElevationModel(updater, 8).
setAlgorithm(AlgorithmId.DUVENHAGE).
setEllipsoid(EllipsoidId.WGS84, BodyRotatingFrameId.ITRF).
setTimeSpan(minDate, maxDate, 0.001, 5.0).
setTrajectory(InertialFrameId.EME2000,
TestUtils.orbitToPV(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25),
8, CartesianDerivativesFilter.USE_PV,
TestUtils.orbitToQ(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25),
2, AngularDerivativesFilter.USE_R).
setLightTimeCorrection(false).
setAberrationOfLightCorrection(false).
addLineSensor(lineSensor);
return builder;
}
/**
* Test for issue #391
*/
@Test
public void testInverseLocationMargin() throws URISyntaxException {
String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath();
DataContext.getDefault().getDataProvidersManager().addProvider(new DirectoryCrawler(new File(path)));
RuggedBuilder builder = new RuggedBuilder();
Frame ecf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
builder.setEllipsoid(ReferenceEllipsoid.getWgs84(ecf));
MultiLayerModel atmosphere = new MultiLayerModel(builder.getEllipsoid());
builder.setRefractionCorrection(atmosphere);
builder.setLightTimeCorrection(true);
builder.setAberrationOfLightCorrection(true);
builder.setAlgorithm(AlgorithmId.IGNORE_DEM_USE_ELLIPSOID);
AbsoluteDate start = AbsoluteDate.ARBITRARY_EPOCH;
AbsoluteDate end = start.shiftedBy(10);
AbsoluteDate middle = start.shiftedBy(end.durationFrom(start) / 2);
builder.setTimeSpan(start, end, 1e-3, 1e-3);
final double h = 500e3;
Vector3D p = new Vector3D(6378137 + h, 0, 0);
Vector3D v = Vector3D.ZERO;
List<TimeStampedPVCoordinates> pvs = Arrays.asList(
new TimeStampedPVCoordinates(start, p, v),
new TimeStampedPVCoordinates(end, p, v));
Rotation rotation = new Rotation(Vector3D.MINUS_I, Vector3D.MINUS_K, Vector3D.PLUS_K, Vector3D.PLUS_I);
TimeStampedAngularCoordinates attitude =
new TimeStampedAngularCoordinates(
middle, rotation,
Vector3D.PLUS_I.scalarMultiply(0.1), Vector3D.ZERO);
List<TimeStampedAngularCoordinates> attitudes = Arrays.asList(
attitude.shiftedBy(start.durationFrom(attitude.getDate())),
attitude,
attitude.shiftedBy(end.durationFrom(attitude.getDate())));
builder.setTrajectory(ecf,
pvs, 2, CartesianDerivativesFilter.USE_P,
attitudes, 2, AngularDerivativesFilter.USE_R);
final double iFov = 1e-6;
TimeDependentLOS los = new TimeDependentLOS() {
@Override
public int getNbPixels() {
return 1000;
}
@Override
public Vector3D getLOS(int index, AbsoluteDate date) {
// simplistic pinhole camera, assumes small angle
final double center = getNbPixels() / 2.0;
final double x = (index - center);
final double los = x * iFov;
return new Vector3D(los, 0, 1);
}
@Override
public <T extends Derivative<T>> FieldVector3D<T> getLOSDerivatives(
int index,
AbsoluteDate date,
DerivativeGenerator<T> generator) {
throw new UnsupportedOperationException("not implemented");
}
@Override
public Stream<ParameterDriver> getParametersDrivers() {
return Stream.empty();
}
};
LineSensor sensor = new LineSensor("sensor",
new LinearLineDatation(middle, 0, 1000),
Vector3D.ZERO,
los);
builder.addLineSensor(sensor);
Rugged ruggedWithDefaultMargin = builder.build();
GeodeticPoint point = ruggedWithDefaultMargin.directLocation(sensor.getName(), 1000)[500];
try {
final int maxLine = 4999; // works with 4980, fails with 4999
ruggedWithDefaultMargin.inverseLocation(sensor.getName(), point, 0, maxLine);
Assert.fail("An exception should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.SENSOR_PIXEL_NOT_FOUND_IN_PIXELS_LINE,re.getSpecifier());
}
// Check the default margin is equal to the used one
Assert.assertEquals(builder.getRefractionCorrection().getComputationParameters().getDefaultInverseLocMargin(),
builder.getRefractionCorrection().getComputationParameters().getInverseLocMargin(),
1.0e-10);
// Change the margin to an admissible one for this case
builder.getRefractionCorrection().setInverseLocMargin(0.81);
Rugged ruggedWithCustomMargin = builder.build();
point = ruggedWithCustomMargin.directLocation(sensor.getName(), 1000)[500];
final int maxLine = 4999; // works with a margin > 0.803
SensorPixel pixel = ruggedWithCustomMargin.inverseLocation(sensor.getName(), point, 0, maxLine);
Assert.assertTrue(pixel != null);
}
@Test
public void testBadConfig() {
int dimension = 400;
TimeDependentLOS los = new LOSBuilder(new ArrayList<Vector3D>(dimension)).build();
LineSensor lineSensor = new LineSensor("line", null, Vector3D.ZERO, los);
// Defines atmospheric refraction model (with the default multi layers model)
AtmosphericRefraction atmosphericRefraction = new MultiLayerModel(null);
// Check the context
atmosphericRefraction.setGridSteps(100, 100);
atmosphericRefraction.configureCorrectionGrid(lineSensor, 0, 300);
assertFalse(atmosphericRefraction.isSameContext("otherSensor", 0, 300));
assertFalse(atmosphericRefraction.isSameContext("line", 42, 300));
assertFalse(atmosphericRefraction.isSameContext("line", 0, 42));
// Check the test of validity of min / max line vs line step
try {
atmosphericRefraction.setGridSteps(100, 100);
atmosphericRefraction.configureCorrectionGrid(lineSensor, 0, 100);
Assert.fail("An exception should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.INVALID_RANGE_FOR_LINES,re.getSpecifier());
}
// Bad pixel step
try {
atmosphericRefraction.setGridSteps(-5, 100);
atmosphericRefraction.configureCorrectionGrid(lineSensor, 0, 100);
Assert.fail("An exception should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.INVALID_STEP,re.getSpecifier());
}
// Bad line step
try {
atmosphericRefraction.setGridSteps(10, -42);
atmosphericRefraction.configureCorrectionGrid(lineSensor, 0, 100);
Assert.fail("An exception should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.INVALID_STEP,re.getSpecifier());
}
}
}
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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.refraction;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hipparchus.analysis.UnivariateFunction;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.RotationConvention;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
import org.orekit.rugged.errors.RuggedException;
import org.orekit.rugged.errors.RuggedMessages;
import org.orekit.rugged.intersection.AbstractAlgorithmTest;
import org.orekit.rugged.intersection.IntersectionAlgorithm;
import org.orekit.rugged.intersection.duvenhage.DuvenhageAlgorithm;
import org.orekit.rugged.raster.TileUpdater;
import org.orekit.rugged.utils.NormalizedGeodeticPoint;
public class MultiLayerModelTest extends AbstractAlgorithmTest {
@Test
public void testAlmostNadir() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
final Vector3D position = new Vector3D(-3787079.6453602533, 5856784.405679551, 1655869.0582939098);
final Vector3D los = new Vector3D( 0.5127552821932051, -0.8254313129088879, -0.2361041470463311);
final NormalizedGeodeticPoint rawIntersection =
algorithm.refineIntersection(earth, position, los,
algorithm.intersection(earth, position, los));
MultiLayerModel model = new MultiLayerModel(earth);
NormalizedGeodeticPoint correctedIntersection = model.applyCorrection(position, los, rawIntersection, algorithm);
double distance = Vector3D.distance(earth.transform(rawIntersection), earth.transform(correctedIntersection));
// this is almost a Nadir observation (LOS deviates between 1.4 and 1.6 degrees from vertical)
// so the refraction correction is small
Assert.assertEquals(0.0553796, distance, 1.0e-6);
}
@Test
public void testNoOpRefraction() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
final Vector3D position = new Vector3D(-3787079.6453602533, 5856784.405679551, 1655869.0582939098);
final Vector3D los = los(position, FastMath.toRadians(50.0));
final NormalizedGeodeticPoint rawIntersection = algorithm.refineIntersection(earth, position, los,
algorithm.intersection(earth, position, los));
MultiLayerModel model = new MultiLayerModel(earth);
NormalizedGeodeticPoint correctedIntersection = model.applyCorrection(position, los, rawIntersection, algorithm);
double distance = Vector3D.distance(earth.transform(rawIntersection), earth.transform(correctedIntersection));
// a test with indices all set to 1.0 - correction must be zero
final int numberOfLayers = 16;
List<ConstantRefractionLayer> refractionLayers = new ArrayList<ConstantRefractionLayer>(numberOfLayers);
for(int i = numberOfLayers - 1; i >= 0; i--) {
refractionLayers.add(new ConstantRefractionLayer(i * 1.0e4, 1.0));
}
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, 1.7e-9);
}
@Test
public void testReversedAtmosphere()
throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
final Vector3D position = new Vector3D(-3787079.6453602533, 5856784.405679551, 1655869.0582939098);
final Vector3D los = los(position, FastMath.toRadians(50.0));
final NormalizedGeodeticPoint rawIntersection = algorithm.refineIntersection(earth, position, los,
algorithm.intersection(earth, position, los));
MultiLayerModel baseModel = new MultiLayerModel(earth);
NormalizedGeodeticPoint correctedIntersection = baseModel.applyCorrection(position, los, rawIntersection, algorithm);
// an intentionally flawed atmosphere with refractive indices decreasing with altitude,
// that should exhibit a LOS bending upwards
Field refractionLayersField = MultiLayerModel.class.getDeclaredField("refractionLayers");
refractionLayersField.setAccessible(true);
@SuppressWarnings("unchecked")
List<ConstantRefractionLayer> baseRefractionLayers =
(List<ConstantRefractionLayer>) refractionLayersField.get(baseModel);
List<ConstantRefractionLayer> denserRefractionLayers = new ArrayList<>();
for (final ConstantRefractionLayer layer : baseRefractionLayers) {
denserRefractionLayers.add(new ConstantRefractionLayer(layer.getLowestAltitude(),
1.0 / layer.getRefractiveIndex()));
}
MultiLayerModel reversedModel = new MultiLayerModel(earth, denserRefractionLayers);
NormalizedGeodeticPoint reversedIntersection = reversedModel.applyCorrection(position, los, rawIntersection, algorithm);
double anglePosRawIntersection = Vector3D.angle(position, earth.transform(rawIntersection));
double anglePosCorrectedIntersection = Vector3D.angle(position, earth.transform(correctedIntersection));
double anglePosReversedIntersection = Vector3D.angle(position, earth.transform(reversedIntersection));
// with regular atmosphere, the ray bends downwards,
// so the ground point is closer to the sub-satellite point than the raw intersection
Assert.assertTrue(anglePosCorrectedIntersection < anglePosRawIntersection);
// with reversed atmosphere, the ray bends upwards,
// so the ground point is farther from the sub-satellite point than the raw intersection
Assert.assertTrue(anglePosReversedIntersection > anglePosRawIntersection);
// the points are almost aligned (for distances around 20m, Earth curvature is small enough)
double dRawCorrected = Vector3D.distance(earth.transform(rawIntersection), earth.transform(correctedIntersection));
double dRawReversed = Vector3D.distance(earth.transform(rawIntersection), earth.transform(reversedIntersection));
double dReversedCorrected = Vector3D.distance(earth.transform(reversedIntersection), earth.transform(correctedIntersection));
Assert.assertEquals(dRawCorrected + dRawReversed, dReversedCorrected, 1.0e-12 * dReversedCorrected);
}
@Test
public void testTwoAtmospheres()
throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
final Vector3D position = new Vector3D(-3787079.6453602533, 5856784.405679551, 1655869.0582939098);
final Vector3D los = los(position, FastMath.toRadians(50.0));
final NormalizedGeodeticPoint rawIntersection = algorithm.refineIntersection(earth, position, los,
algorithm.intersection(earth, position, los));
// a comparison between two atmospheres, one more dense than the other and showing correction
// is more important with high indices
MultiLayerModel baseModel = new MultiLayerModel(earth);
Field refractionLayersField = MultiLayerModel.class.getDeclaredField("refractionLayers");
refractionLayersField.setAccessible(true);
@SuppressWarnings("unchecked")
List<ConstantRefractionLayer> baseRefractionLayers =
(List<ConstantRefractionLayer>) refractionLayersField.get(baseModel);
List<ConstantRefractionLayer> denserRefractionLayers = new ArrayList<>();
double previousBaseN = 1.0;
double previousDenserN = 1.0;
double factor = 1.00001;
for (final ConstantRefractionLayer layer : baseRefractionLayers) {
final double currentBaseN = layer.getRefractiveIndex();
final double baseRatio = currentBaseN / previousBaseN;
final double currentDenserN = previousDenserN * factor * baseRatio;
denserRefractionLayers.add(new ConstantRefractionLayer(layer.getLowestAltitude(),
currentDenserN));
previousBaseN = currentBaseN;
previousDenserN = currentDenserN;
}
MultiLayerModel denserModel = new MultiLayerModel(earth, denserRefractionLayers);
NormalizedGeodeticPoint baseIntersection = baseModel.applyCorrection(position, los, rawIntersection, algorithm);
NormalizedGeodeticPoint 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));
Assert.assertTrue(denserDistance > baseDistance);
}
@Test
public void testMissingLayers() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
final Vector3D position = new Vector3D(-3787079.6453602533, 5856784.405679551, 1655869.0582939098);
final Vector3D los = los(position, FastMath.toRadians(50.0));
final NormalizedGeodeticPoint rawIntersection = algorithm.refineIntersection(earth, position, los,
algorithm.intersection(earth, position, los));
final double h = rawIntersection.getAltitude();
MultiLayerModel model = new MultiLayerModel(earth,
Collections.singletonList(new ConstantRefractionLayer(h + 100.0,
1.5)));
try {
model.applyCorrection(position, los, rawIntersection, algorithm);
Assert.fail("an exception should have been thrown");
} catch (RuggedException re) {
Assert.assertEquals(RuggedMessages.NO_LAYER_DATA, re.getSpecifier());
Assert.assertEquals(h, ((Double) re.getParts()[0]).doubleValue(), 1.0e-6);
Assert.assertEquals(h + 100.0, ((Double) re.getParts()[1]).doubleValue(), 1.0e-6);
}
}
@Test
public void testLayersBelowDEM() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
final Vector3D position = new Vector3D(-3787079.6453602533, 5856784.405679551, 1655869.0582939098);
final Vector3D los = los(position, FastMath.toRadians(50.0));
final NormalizedGeodeticPoint rawIntersection = algorithm.refineIntersection(earth, position, los,
algorithm.intersection(earth, position, los));
MultiLayerModel model = new MultiLayerModel(earth,
Collections.singletonList(new ConstantRefractionLayer(rawIntersection.getAltitude() - 100.0,
1.5)));
NormalizedGeodeticPoint correctedIntersection = model.applyCorrection(position, los, rawIntersection, algorithm);
double distance = Vector3D.distance(earth.transform(rawIntersection), earth.transform(correctedIntersection));
Assert.assertEquals(0.0, distance, 1.3e-9);
}
@Test
public void testDivingAngleChange() {
setUpMayonVolcanoContext();
final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8);
final Vector3D position = new Vector3D(-3787079.6453602533, 5856784.405679551, 1655869.0582939098);
AtmosphericRefraction model = new MultiLayerModel(earth);
// deviation should increase from 0 to about 17m
// as the angle between los and nadir increases from 0 to 50 degrees
// the reference model below has been obtained by fitting the test results themselves
// it is NOT considered a full featured model, it's just a helper function for this specific test
UnivariateFunction reference = alpha -> 1.17936 * FastMath.tan((2.94613 - 1.40162 * alpha) * alpha);
for (double alpha = 0; alpha < FastMath.toRadians(50.0); alpha += 0.1) {
final Vector3D rotatingLos = los(position, alpha);
final NormalizedGeodeticPoint rawIntersection = algorithm.refineIntersection(earth, position, rotatingLos,
algorithm.intersection(earth, position, rotatingLos));
final NormalizedGeodeticPoint correctedIntersection = model.applyCorrection(position, rotatingLos, rawIntersection, algorithm);
final double distance = Vector3D.distance(earth.transform(rawIntersection),
earth.transform(correctedIntersection));
Assert.assertEquals(reference.value(alpha), distance, 0.12);
}
}
private Vector3D los(final Vector3D position, final double angleFromNadir) {
final Vector3D nadir = earth.transform(position, earth.getBodyFrame(), null).getNadir();
final Rotation losRotation = new Rotation(nadir.orthogonal(), angleFromNadir,
RotationConvention.VECTOR_OPERATOR);
return losRotation.applyTo(nadir);
}
@Override
protected IntersectionAlgorithm createAlgorithm(TileUpdater updater, int maxCachedTiles) {
return new DuvenhageAlgorithm(updater, maxCachedTiles, false);
}
}
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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.utils;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.junit.Assert;
import org.junit.Test;
import org.orekit.errors.OrekitException;
import org.orekit.time.AbsoluteDate;
public class AbsoluteDateForVectorisationTest {
@Test
public void testShiftedBySeveralTimeShiftOneDate() {
AbsoluteDate date1 = new AbsoluteDate();
AbsoluteDate[] dates = new AbsoluteDate[] {date1};
double[] dts = new double[] {10.0, 20.0, 30.0};
AbsoluteDateArrayHandling datesForVect = new AbsoluteDateArrayHandling(dates);
AbsoluteDate[][] datesShifted = datesForVect.multipleShiftedBy(dts);
Assert.assertEquals(datesShifted[0][0].durationFrom(date1.shiftedBy(10)), 0.0, 1e-5);
Assert.assertEquals(datesShifted[0][1].durationFrom(date1.shiftedBy(20)), 0.0, 1e-5);
}
@Test
public void testShiftedByCorrespondingTimeShift() {
AbsoluteDate date1 = new AbsoluteDate();
AbsoluteDate date2 = date1.shiftedBy(10000);
AbsoluteDate date3 = date1.shiftedBy(20000);
AbsoluteDate[] dates = new AbsoluteDate[] {date1, date2, date3};
double[] dts = new double[] {10.0, 20.0, 30.0};
AbsoluteDateArrayHandling datesForVect = new AbsoluteDateArrayHandling(dates);
AbsoluteDate[] datesShifted = datesForVect.shiftedBy(dts);
Assert.assertEquals(datesShifted[0].durationFrom(date1.shiftedBy(10)), 0.0, 1e-5);
Assert.assertEquals(datesShifted[1].durationFrom(date1.shiftedBy(10020)), 0.0, 1e-5);
Assert.assertEquals(datesShifted[2].durationFrom(date1.shiftedBy(20030)), 0.0, 1e-5);
}
@Test
public void testShiftedBySeveralTimeShiftSeveralDates() {
AbsoluteDate date1 = new AbsoluteDate();
AbsoluteDate date2 = date1.shiftedBy(10000);
AbsoluteDate[] dates = new AbsoluteDate[] {date1, date2};
double[] dts = new double[] {10.0, 20.0, 30.0};
AbsoluteDateArrayHandling datesForVect = new AbsoluteDateArrayHandling(dates);
AbsoluteDate[][] datesShifted = datesForVect.multipleShiftedBy(dts);
Assert.assertEquals(datesShifted[0][0].durationFrom(date1.shiftedBy(10)), 0.0, 1e-5);
Assert.assertEquals(datesShifted[0][1].durationFrom(date1.shiftedBy(20)), 0.0, 1e-5);
Assert.assertEquals(datesShifted[1][1].durationFrom(date2.shiftedBy(20)), 0.0, 1e-5);
Assert.assertEquals(datesShifted[1][2].durationFrom(date2.shiftedBy(30)), 0.0, 1e-5);
}
@Test
public void testDurationFromSeveralDates() {
AbsoluteDate date1 = new AbsoluteDate();
AbsoluteDate date2 = date1.shiftedBy(10000);
AbsoluteDate date3 = date1.shiftedBy(20000);
AbsoluteDate date4 = date1.shiftedBy(100000);
AbsoluteDate[] dates = new AbsoluteDate[] {date1, date2, date3};
AbsoluteDate[] datesComputeDuration = new AbsoluteDate[] {date4, date1};
AbsoluteDateArrayHandling datesForVect = new AbsoluteDateArrayHandling(dates);
double[][] datesDurations = datesForVect.multipleDurationFrom(datesComputeDuration);
Assert.assertEquals(datesDurations[0][0], date1.durationFrom(date4), 1e-5);
Assert.assertEquals(datesDurations[0][1], date1.durationFrom(date1), 1e-5);
Assert.assertEquals(datesDurations[1][0], date2.durationFrom(date4), 1e-5);
Assert.assertEquals(datesDurations[1][1], date2.durationFrom(date1), 1e-5);
Assert.assertEquals(datesDurations[2][0], date3.durationFrom(date4), 1e-5);
Assert.assertEquals(datesDurations[2][1], date3.durationFrom(date1), 1e-5);
}
@Test
public void testDurationFromCorrespondingDates() {
AbsoluteDate date1 = new AbsoluteDate();
AbsoluteDate date2 = date1.shiftedBy(10000);
AbsoluteDate date3 = date1.shiftedBy(20000);
AbsoluteDate date4 = date1.shiftedBy(100000);
AbsoluteDate[] dates = new AbsoluteDate[] {date1, date2, date3};
AbsoluteDate[] datesComputeDuration = new AbsoluteDate[] {date4, date1, date2};
AbsoluteDateArrayHandling datesForVect = new AbsoluteDateArrayHandling(dates);
double[] datesDurations = datesForVect.durationFrom(datesComputeDuration);
Assert.assertEquals(datesDurations[0], date1.durationFrom(date4), 1e-5);
Assert.assertEquals(datesDurations[1], date2.durationFrom(date1), 1e-5);
Assert.assertEquals(datesDurations[2], date3.durationFrom(date2), 1e-5);
}
@Test
public void testExceptionDimensions() {
AbsoluteDate date1 = new AbsoluteDate();
AbsoluteDate date2 = date1.shiftedBy(10000);
AbsoluteDate date3 = date1.shiftedBy(20000);
AbsoluteDate date4 = date1.shiftedBy(100000);
AbsoluteDate[] dates = new AbsoluteDate[] {date1, date2, date3};
AbsoluteDate[] datesComputeDuration = new AbsoluteDate[] {date4, date1};
AbsoluteDateArrayHandling datesForVect = new AbsoluteDateArrayHandling(dates);
try {
datesForVect.durationFrom(datesComputeDuration);
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, oe.getSpecifier());
}
}
}