1   /* Copyright 2013-2025 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.rugged.errors;
18  
19  
20  import java.io.BufferedReader;
21  import java.io.File;
22  import java.io.FileReader;
23  import java.io.IOException;
24  import java.net.URISyntaxException;
25  
26  import org.hipparchus.geometry.euclidean.threed.Rotation;
27  import org.hipparchus.geometry.euclidean.threed.RotationConvention;
28  import org.hipparchus.geometry.euclidean.threed.Vector3D;
29  import org.hipparchus.util.FastMath;
30  import org.junit.jupiter.api.Assertions;
31  import org.junit.jupiter.api.Test;
32  import org.junit.jupiter.api.io.TempDir;
33  import org.orekit.bodies.BodyShape;
34  import org.orekit.bodies.GeodeticPoint;
35  import org.orekit.data.DataContext;
36  import org.orekit.data.DirectoryCrawler;
37  import org.orekit.orbits.Orbit;
38  import org.orekit.rugged.TestUtils;
39  import org.orekit.rugged.api.AlgorithmId;
40  import org.orekit.rugged.api.BodyRotatingFrameId;
41  import org.orekit.rugged.api.EllipsoidId;
42  import org.orekit.rugged.api.InertialFrameId;
43  import org.orekit.rugged.api.Rugged;
44  import org.orekit.rugged.api.RuggedBuilder;
45  import org.orekit.rugged.linesensor.LineDatation;
46  import org.orekit.rugged.linesensor.LineSensor;
47  import org.orekit.rugged.linesensor.LinearLineDatation;
48  import org.orekit.rugged.linesensor.SensorPixel;
49  import org.orekit.rugged.los.TimeDependentLOS;
50  import org.orekit.rugged.raster.RandomLandscapeUpdater;
51  import org.orekit.rugged.raster.TileUpdater;
52  import org.orekit.time.AbsoluteDate;
53  import org.orekit.time.TimeScalesFactory;
54  import org.orekit.utils.AngularDerivativesFilter;
55  import org.orekit.utils.CartesianDerivativesFilter;
56  import org.orekit.utils.Constants;
57  
58  public class DumpManagerTest {
59  
60      @TempDir
61      public File tempFolder;
62  
63      @Test
64      public void testDump() throws URISyntaxException, IOException {
65  
66          File dump = File.createTempFile("junit", null, tempFolder);
67          DumpManager.activate(dump);
68          variousRuggedCalls();
69          DumpManager.deactivate();
70  
71          int countAlgorithm        = 0;
72          int countEllipsoid        = 0;
73          int countDirectLoc        = 0;
74          int countDirectLocResult  = 0;
75          int countSpan             = 0;
76          int countTransform        = 0;
77          int countDEMTile          = 0;
78          int countDEMCell          = 0;
79          int countInverseLoc       = 0;
80          int countInverseLocResult = 0;
81          int countSensor           = 0;
82          int countSensorMeanPlane  = 0;
83          int countSensorLOS        = 0;
84          int countSensorDatation   = 0;
85          int countSensorRate       = 0;
86          try (final FileReader     fr = new FileReader(dump);
87               final BufferedReader br = new BufferedReader(fr)) {
88              for (String line = br.readLine(); line != null; line = br.readLine()) {
89                  String trimmed = line.trim();
90                  if (trimmed.length() > 0 && !trimmed.startsWith("#")){
91                      if (trimmed.startsWith("algorithm:")) {
92                          ++countAlgorithm;
93                      } else if (trimmed.startsWith("ellipsoid:")) {
94                          ++countEllipsoid;
95                      } else if (trimmed.startsWith("direct location:")) {
96                          ++countDirectLoc;
97                      } else if (trimmed.startsWith("direct location result:")) {
98                          ++countDirectLocResult;
99                      } else if (trimmed.startsWith("span:")) {
100                         ++countSpan;
101                     } else if (trimmed.startsWith("transform:")) {
102                         ++countTransform;
103                     } else if (trimmed.startsWith("DEM tile:")) {
104                         ++countDEMTile;
105                     } else if (trimmed.startsWith("DEM cell:")) {
106                         ++countDEMCell;
107                     } else if (trimmed.startsWith("inverse location:")) {
108                         ++countInverseLoc;
109                     } else if (trimmed.startsWith("inverse location result:")) {
110                         ++countInverseLocResult;
111                     } else if (trimmed.startsWith("sensor:")) {
112                         ++countSensor;
113                     } else if (trimmed.startsWith("sensor mean plane:")) {
114                         ++countSensorMeanPlane;
115                     } else if (trimmed.startsWith("sensor LOS:")) {
116                         ++countSensorLOS;
117                     } else if (trimmed.startsWith("sensor datation:")) {
118                         ++countSensorDatation;
119                     } else if (trimmed.startsWith("sensor rate:")) {
120                         ++countSensorRate;
121                     } else {
122                         Assertions.fail(line);
123                     }
124                 }
125             }
126         }
127 
128         Assertions.assertEquals(1,   countAlgorithm);
129         Assertions.assertEquals(1,   countEllipsoid);
130         Assertions.assertEquals(400, countDirectLoc);
131         Assertions.assertEquals(400, countDirectLocResult);
132         Assertions.assertEquals(1,   countSpan);
133         Assertions.assertEquals(2,   countTransform);
134         Assertions.assertEquals(2,   countDEMTile);
135         Assertions.assertEquals(812, countDEMCell);
136         Assertions.assertEquals(5,   countInverseLoc);
137         Assertions.assertEquals(5,   countInverseLocResult);
138         Assertions.assertEquals(1,   countSensor);
139         Assertions.assertEquals(1,   countSensorMeanPlane);
140         Assertions.assertEquals(422, countSensorLOS);
141         Assertions.assertEquals(19,  countSensorDatation);
142         Assertions.assertEquals(6,   countSensorRate);
143 
144     }
145 
146    public void variousRuggedCalls()
147         throws URISyntaxException {
148 
149        int dimension = 200;
150 
151        String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath();
152        DataContext.getDefault().getDataProvidersManager().addProvider(new DirectoryCrawler(new File(path)));
153        final BodyShape  earth = TestUtils.createEarth();
154        final Orbit      orbit = TestUtils.createOrbit(Constants.EIGEN5C_EARTH_MU);
155 
156        AbsoluteDate crossing = new AbsoluteDate("2012-01-01T12:30:00.000", TimeScalesFactory.getUTC());
157 
158        // one line sensor
159        // position: 1.5m in front (+X) and 20 cm above (-Z) of the S/C center of mass
160        // los: swath in the (YZ) plane, looking at 50° roll, ±1° aperture
161        Vector3D position = new Vector3D(1.5, 0, -0.2);
162        TimeDependentLOS los = TestUtils.createLOSPerfectLine(new Rotation(Vector3D.PLUS_I,
163                                                                           FastMath.toRadians(50.0),
164                                                                           RotationConvention.VECTOR_OPERATOR).applyTo(Vector3D.PLUS_K),
165                                                              Vector3D.PLUS_I, FastMath.toRadians(1.0), dimension).build();
166 
167        // linear datation model: at reference time we get line 100, and the rate is one line every 1.5ms
168        LineDatation lineDatation = new LinearLineDatation(crossing, dimension / 2, 1.0 / 1.5e-3);
169        int firstLine = 0;
170        int lastLine  = dimension;
171        LineSensor lineSensor = new LineSensor("line", lineDatation, position, los);
172        AbsoluteDate minDate = lineSensor.getDate(firstLine);
173        AbsoluteDate maxDate = lineSensor.getDate(lastLine);
174 
175        TileUpdater updater =
176                new RandomLandscapeUpdater(0.0, 9000.0, 0.5, 0xf0a401650191f9f6l,
177                                           FastMath.toRadians(1.0), 257);
178 
179        Rugged rugged = new RuggedBuilder().
180                setDigitalElevationModel(updater, 8).
181                setAlgorithm(AlgorithmId.DUVENHAGE).
182                setEllipsoid(EllipsoidId.WGS84, BodyRotatingFrameId.ITRF).
183                setTimeSpan(minDate, maxDate, 0.001, 5.0).
184                setTrajectory(InertialFrameId.EME2000,
185                              TestUtils.orbitToPV(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25),
186                              8, CartesianDerivativesFilter.USE_PV,
187                              TestUtils.orbitToQ(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25),
188                              2, AngularDerivativesFilter.USE_R).
189                addLineSensor(lineSensor).build();
190        GeodeticPoint[] gpLine = rugged.directLocation("line", 100);
191 
192        for (int i = 0; i < gpLine.length; ++i) {
193            GeodeticPoint gpPixel =
194                    rugged.directLocation(lineSensor.getDate(100), lineSensor.getPosition(),
195                                              lineSensor.getLOS(lineSensor.getDate(100), i));
196            Assertions.assertEquals(gpLine[i].getLatitude(),  gpPixel.getLatitude(),  1.0e-10);
197            Assertions.assertEquals(gpLine[i].getLongitude(), gpPixel.getLongitude(), 1.0e-10);
198            Assertions.assertEquals(gpLine[i].getAltitude(),  gpPixel.getAltitude(),  1.0e-10);
199 
200            if (i % 45 == 0) {
201                SensorPixel sp = rugged.inverseLocation(lineSensor.getName(), gpPixel, 0, 179);
202                Assertions.assertEquals(100, sp.getLineNumber(), 1.0e-5);
203                Assertions.assertEquals(i, sp.getPixelNumber(), 6.0e-9);
204            }
205        }
206 
207     }
208 
209    @Test
210    public void testAlreadyActive() throws URISyntaxException, IOException {
211 
212        DumpManager.activate(File.createTempFile("junit", null, tempFolder));
213        try {
214            DumpManager.activate(File.createTempFile("junit", null, tempFolder));
215            Assertions.fail("an exception should have been thrown");
216        } catch (RuggedException re) {
217            Assertions.assertEquals(RuggedMessages.DEBUG_DUMP_ALREADY_ACTIVE, re.getSpecifier());
218        } finally {
219            DumpManager.deactivate();
220        }
221    }
222 
223    @Test
224    public void testNotActive() throws URISyntaxException, IOException {
225        try {
226            DumpManager.deactivate();
227            Assertions.fail("an exception should have been thrown");
228        } catch (RuggedException re) {
229            Assertions.assertEquals(RuggedMessages.DEBUG_DUMP_NOT_ACTIVE, re.getSpecifier());
230        }
231    }
232 
233    @Test
234    public void testWriteError() throws URISyntaxException, IOException {
235        try {
236            DumpManager.activate(tempFolder);
237            Assertions.fail("an exception should have been thrown");
238        } catch (RuggedException re) {
239            Assertions.assertEquals(RuggedMessages.DEBUG_DUMP_ACTIVATION_ERROR, re.getSpecifier());
240        }
241    }
242 
243 }