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  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.PrintWriter;
23  
24  import org.orekit.bodies.GeodeticPoint;
25  import org.orekit.frames.Transform;
26  import org.orekit.rugged.api.AlgorithmId;
27  import org.orekit.rugged.linesensor.LineSensor;
28  import org.orekit.rugged.linesensor.SensorMeanPlaneCrossing;
29  import org.orekit.rugged.linesensor.SensorPixel;
30  import org.orekit.rugged.raster.Tile;
31  import org.orekit.rugged.utils.ExtendedEllipsoid;
32  import org.orekit.rugged.utils.SpacecraftToObservedBody;
33  import org.orekit.time.AbsoluteDate;
34  
35  /**
36   * Class managing debug dumps.
37   * <p>
38   * <em>WARNING</em>: this class is public only for technical reasons,
39   * it is not considered to belong to the public API of the library and should
40   * not be called by user code. It is only intended to be called internally by
41   * the Rugged library itself. This class may be changed or even removed at any
42   * time, so user code should not rely on it.
43   * </p>
44   * @author Luc Maisonobe
45   * @author Guylaine Prat
46   */
47  public class DumpManager {
48  
49      /** Dump file (default initial value is null, i.e. nothing is dumped). */
50      private static final ThreadLocal<Dump> DUMP = new ThreadLocal<>();
51  
52      /** Boolean to check if the dump is suspended. */
53      private static boolean isSuspended = false;
54  
55      /** Private constructor for utility class.
56       */
57      private DumpManager() {
58          // by default, nothing is dumped
59      }
60  
61      /** Activate debug dump.
62       * @param file dump file
63       */
64      public static void activate(final File file) {
65          if (isActive()) {
66              throw new RuggedException(RuggedMessages.DEBUG_DUMP_ALREADY_ACTIVE);
67          } else {
68              try {
69                  DUMP.set(new Dump(new PrintWriter(file, "UTF-8")));
70              } catch (IOException ioe) {
71                  throw new RuggedException(ioe, RuggedMessages.DEBUG_DUMP_ACTIVATION_ERROR,
72                                            file.getAbsolutePath(), ioe.getLocalizedMessage());
73              }
74          }
75      }
76  
77      /** Deactivate debug dump.
78       */
79      public static void deactivate() {
80          if (isActive()) {
81              DUMP.get().deactivate();
82              DUMP.set(null);
83          } else {
84              throw new RuggedException(RuggedMessages.DEBUG_DUMP_NOT_ACTIVE);
85          }
86      }
87  
88      /** Suspend the dump.
89       * In case the dump is already suspended, keep the previous status in order to
90       * correctly deal the resume stage.
91       * @return a flag to tell if the dump is already suspended (true; false otherwise)
92       */
93      public static Boolean suspend() {
94          // Check if the dump is already suspended
95          if (isSuspended) {
96              return isSuspended;
97          } else {
98              isSuspended = true;
99              return false;
100         }
101     }
102 
103     /** Resume the dump, only if it was not already suspended.
104      * @param wasSuspended flag to tell if the dump was already suspended (true; false otherwise)
105      */
106     public static void resume(final Boolean wasSuspended) {
107         if (!wasSuspended) {
108             isSuspended = false;
109         }
110     }
111 
112     /** In case dump is suspended and an exception is thrown,
113      * allows the dump to end nicely.
114      */
115     public static void endNicely() {
116         isSuspended = false;
117         if (isActive()) {
118             deactivate();
119         }
120 
121     }
122 
123     /** Check if dump is active for this thread.
124      * @return true if dump is active for this thread
125      */
126     public static boolean isActive() {
127         return DUMP.get() != null && !isSuspended;
128     }
129 
130     /** Dump DEM cell data.
131      * @param tile tile to which the cell belongs
132      * @param latitudeIndex latitude index of the cell
133      * @param longitudeIndex longitude index of the cell
134      * @param elevation elevation of the cell
135      */
136     public static void dumpTileCell(final Tile tile,
137                                     final int latitudeIndex, final int longitudeIndex,
138                                     final double elevation) {
139         if (isActive()) {
140             DUMP.get().dumpTileCell(tile, latitudeIndex, longitudeIndex, elevation);
141         }
142     }
143 
144     /** Dump algorithm data.
145      * @param algorithmId algorithm ID
146      */
147     public static void dumpAlgorithm(final AlgorithmId algorithmId) {
148         if (isActive()) {
149             DUMP.get().dumpAlgorithm(algorithmId);
150         }
151     }
152 
153     /** Dump algorithm data.
154      * @param algorithmId algorithm ID
155      * @param specific algorithm specific extra data
156      */
157     public static void dumpAlgorithm(final AlgorithmId algorithmId, final double specific) {
158         if (isActive()) {
159             DUMP.get().dumpAlgorithm(algorithmId, specific);
160         }
161     }
162 
163     /** Dump ellipsoid data.
164      * @param ellipsoid ellipsoid to dump
165      */
166     public static void dumpEllipsoid(final ExtendedEllipsoid ellipsoid) {
167         if (isActive()) {
168             DUMP.get().dumpEllipsoid(ellipsoid);
169         }
170     }
171 
172     /** Dump a direct location computation.
173      * @param date date of the location
174      * @param sensorPosition sensor position in spacecraft frame
175      * @param los normalized line-of-sight in spacecraft frame
176      * @param lightTimeCorrection flag for light time correction
177      * @param aberrationOfLightCorrection flag for aberration of light correction
178      * @param refractionCorrection flag for refraction correction
179      */
180     public static void dumpDirectLocation(final AbsoluteDate date, final Vector3D sensorPosition, final Vector3D los,
181                                           final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection,
182                                           final boolean refractionCorrection) {
183         if (isActive()) {
184             DUMP.get().dumpDirectLocation(date, sensorPosition, los, lightTimeCorrection, aberrationOfLightCorrection,
185                                           refractionCorrection);
186         }
187     }
188 
189     /** Dump a direct location result.
190      * @param gp resulting geodetic point
191      */
192     public static void dumpDirectLocationResult(final GeodeticPoint gp) {
193         if (isActive()) {
194             DUMP.get().dumpDirectLocationResult(gp);
195         }
196     }
197 
198     /** Dump an inverse location computation.
199      * @param sensor sensor
200      * @param point point to localize
201      * @param ellipsoid the used ellipsoid
202      * @param minLine minimum line number
203      * @param maxLine maximum line number
204      * @param lightTimeCorrection flag for light time correction
205      * @param aberrationOfLightCorrection flag for aberration of light correction
206      * @param refractionCorrection flag for refraction correction
207      */
208     public static void dumpInverseLocation(final LineSensor sensor, final GeodeticPoint point,
209                                            final ExtendedEllipsoid ellipsoid,
210                                            final int minLine, final int maxLine,
211                                            final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection,
212                                            final boolean refractionCorrection) {
213         if (isActive()) {
214             DUMP.get().dumpInverseLocation(sensor, point, minLine, maxLine,
215                                            lightTimeCorrection, aberrationOfLightCorrection, refractionCorrection);
216             DUMP.get().dumpEllipsoid(ellipsoid);
217         }
218     }
219 
220     /** Dump an inverse location result.
221      * @param pixel resulting sensor pixel
222      */
223     public static void dumpInverseLocationResult(final SensorPixel pixel) {
224         if (isActive()) {
225             DUMP.get().dumpInverseLocationResult(pixel);
226         }
227     }
228 
229     /** Dump an observation transform transform.
230      * @param scToBody provider for observation
231      * @param index index of the transform
232      * @param bodyToInertial transform from body frame to inertial frame
233      * @param scToInertial transfrom from spacecraft frame to inertial frame
234      */
235     public static void dumpTransform(final SpacecraftToObservedBody scToBody, final int index,
236                                      final Transform bodyToInertial, final Transform scToInertial) {
237         if (isActive()) {
238             DUMP.get().dumpTransform(scToBody, index, bodyToInertial, scToInertial);
239         }
240     }
241 
242     /** Dump a sensor mean plane.
243      * @param meanPlane mean plane associated with sensor
244      */
245     public static void dumpSensorMeanPlane(final SensorMeanPlaneCrossing meanPlane) {
246         if (isActive()) {
247             DUMP.get().dumpSensorMeanPlane(meanPlane);
248         }
249     }
250 
251     /** Dump a sensor LOS.
252      * @param sensor sensor
253      * @param date date
254      * @param i pixel index
255      * @param los pixel normalized line-of-sight
256      */
257     public static void dumpSensorLOS(final LineSensor sensor, final AbsoluteDate date, final int i, final Vector3D los) {
258         if (isActive()) {
259             DUMP.get().dumpSensorLOS(sensor, date, i, los);
260         }
261     }
262 
263     /** Dump a sensor datation.
264      * @param sensor sensor
265      * @param lineNumber line number
266      * @param date date
267      */
268     public static void dumpSensorDatation(final LineSensor sensor, final double lineNumber, final AbsoluteDate date) {
269         if (isActive()) {
270             DUMP.get().dumpSensorDatation(sensor, lineNumber, date);
271         }
272     }
273 
274     /** Dump a sensor rate.
275      * @param sensor sensor
276      * @param lineNumber line number
277      * @param rate lines rate
278      */
279     public static void dumpSensorRate(final LineSensor sensor, final double lineNumber, final double rate) {
280         if (isActive()) {
281             DUMP.get().dumpSensorRate(sensor, lineNumber, rate);
282         }
283     }
284 
285 }