1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.rugged.errors;
18
19 import java.io.PrintWriter;
20 import java.util.ArrayList;
21 import java.util.Calendar;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Locale;
25 import java.util.Map;
26 import java.util.TimeZone;
27
28 import org.hipparchus.geometry.euclidean.threed.Rotation;
29 import org.hipparchus.geometry.euclidean.threed.Vector3D;
30 import org.hipparchus.util.FastMath;
31 import org.hipparchus.util.OpenIntToDoubleHashMap;
32 import org.hipparchus.util.Pair;
33 import org.orekit.bodies.GeodeticPoint;
34 import org.orekit.frames.FactoryManagedFrame;
35 import org.orekit.frames.Frame;
36 import org.orekit.frames.Transform;
37 import org.orekit.rugged.api.AlgorithmId;
38 import org.orekit.rugged.linesensor.LineSensor;
39 import org.orekit.rugged.linesensor.SensorMeanPlaneCrossing;
40 import org.orekit.rugged.linesensor.SensorPixel;
41 import org.orekit.rugged.raster.Tile;
42 import org.orekit.rugged.utils.ExtendedEllipsoid;
43 import org.orekit.rugged.utils.SpacecraftToObservedBody;
44 import org.orekit.time.AbsoluteDate;
45 import org.orekit.time.DateTimeComponents;
46 import org.orekit.time.TimeScalesFactory;
47
48
49
50
51
52
53 class Dump {
54
55
56 private final PrintWriter writer;
57
58
59 private final List<DumpedTileData> tiles;
60
61
62 private final List<DumpedSensorData> sensors;
63
64
65 private boolean algorithmDumped;
66
67
68 private boolean ellipsoidDumped;
69
70
71 private boolean[] tranformsDumped;
72
73
74
75
76 Dump(final PrintWriter writer) {
77 this.writer = writer;
78 this.tiles = new ArrayList<DumpedTileData>();
79 this.sensors = new ArrayList<DumpedSensorData>();
80 this.algorithmDumped = false;
81 this.ellipsoidDumped = false;
82 this.tranformsDumped = null;
83 dumpHeader();
84 }
85
86
87
88 private void dumpHeader() {
89 writer.format(Locale.US,
90 "# Rugged library dump file, created on %1$tFT%1$tTZ%n",
91 Calendar.getInstance(TimeZone.getTimeZone("Etc/UTC"), Locale.US));
92 writer.format(Locale.US,
93 "# all units are SI units (m, m/s, rad ...)%n");
94 }
95
96
97
98
99
100
101
102 public void dumpTileCell(final Tile tile,
103 final int latitudeIndex, final int longitudeIndex,
104 final double elevation) {
105 getTileData(tile).setElevation(latitudeIndex, longitudeIndex, elevation);
106 }
107
108
109
110
111 public void dumpAlgorithm(final AlgorithmId algorithmId) {
112 if (!algorithmDumped) {
113 writer.format(Locale.US,
114 "algorithm: %s%n",
115 algorithmId.name());
116 algorithmDumped = true;
117 }
118 }
119
120
121
122
123
124 public void dumpAlgorithm(final AlgorithmId algorithmId, final double specific) {
125 if (!algorithmDumped) {
126 writer.format(Locale.US,
127 "algorithm: %s elevation %22.15e%n",
128 algorithmId.name(), specific);
129 algorithmDumped = true;
130 }
131 }
132
133
134
135
136 public void dumpEllipsoid(final ExtendedEllipsoid ellipsoid) {
137 if (!ellipsoidDumped) {
138 writer.format(Locale.US,
139 "ellipsoid: ae %22.15e f %22.15e frame %s%n",
140 ellipsoid.getA(), ellipsoid.getFlattening(),
141 getKeyOrName(ellipsoid.getBodyFrame()));
142 ellipsoidDumped = true;
143 }
144 }
145
146
147
148
149
150
151
152
153
154 public void dumpDirectLocation(final AbsoluteDate date, final Vector3D sensorPosition, final Vector3D los,
155 final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection,
156 final boolean refractionCorrection) {
157 writer.format(Locale.US,
158 "direct location: date %s position %22.15e %22.15e %22.15e los %22.15e %22.15e %22.15e lightTime %b aberration %b refraction %b %n",
159 convertDate(date),
160 sensorPosition.getX(), sensorPosition.getY(), sensorPosition.getZ(),
161 los.getX(), los.getY(), los.getZ(),
162 lightTimeCorrection, aberrationOfLightCorrection, refractionCorrection);
163 }
164
165
166
167
168 public void dumpDirectLocationResult(final GeodeticPoint gp) {
169 if (gp != null) {
170 writer.format(Locale.US,
171 "direct location result: latitude %22.15e longitude %22.15e elevation %22.15e%n",
172 gp.getLatitude(), gp.getLongitude(), gp.getAltitude());
173 } else {
174 writer.format(Locale.US, "direct location result: NULL");
175 }
176 }
177
178
179
180
181
182
183
184
185
186
187 public void dumpInverseLocation(final LineSensor sensor, final GeodeticPoint point,
188 final int minLine, final int maxLine,
189 final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection,
190 final boolean refractionCorrection) {
191 final DumpedSensorData ds = getSensorData(sensor);
192 writer.format(Locale.US,
193 "inverse location: sensorName %s latitude %22.15e longitude %22.15e elevation %22.15e minLine %d maxLine %d lightTime %b aberration %b refraction %b %n",
194 ds.getDumpName(),
195 point.getLatitude(), point.getLongitude(), point.getAltitude(),
196 minLine, maxLine,
197 lightTimeCorrection, aberrationOfLightCorrection, refractionCorrection);
198 }
199
200
201
202
203 public void dumpInverseLocationResult(final SensorPixel pixel) {
204 if (pixel != null) {
205 writer.format(Locale.US,
206 "inverse location result: lineNumber %22.15e pixelNumber %22.15e%n",
207 pixel.getLineNumber(), pixel.getPixelNumber());
208 } else {
209 writer.format(Locale.US, "inverse location result: NULL");
210 }
211 }
212
213
214
215
216
217
218
219 public void dumpTransform(final SpacecraftToObservedBody scToBody, final int index,
220 final Transform bodyToInertial, final Transform scToInertial) {
221 if (tranformsDumped == null) {
222 final AbsoluteDate minDate = scToBody.getMinDate();
223 final AbsoluteDate maxDate = scToBody.getMaxDate();
224 final double tStep = scToBody.getTStep();
225 final double tolerance = scToBody.getOvershootTolerance();
226 final int n = (int) FastMath.ceil(maxDate.durationFrom(minDate) / tStep);
227 writer.format(Locale.US,
228 "span: minDate %s maxDate %s tStep %22.15e tolerance %22.15e inertialFrame %s%n",
229 convertDate(minDate), convertDate(maxDate), tStep, tolerance,
230 getKeyOrName(scToBody.getInertialFrame()));
231 tranformsDumped = new boolean[n];
232 }
233 if (!tranformsDumped[index]) {
234 writer.format(Locale.US,
235 "transform: index %d body %s spacecraft %s %s%n",
236 index,
237 convertRotation(bodyToInertial.getRotation(), bodyToInertial.getRotationRate(), bodyToInertial.getRotationAcceleration()),
238 convertTranslation(scToInertial.getTranslation(), scToInertial.getVelocity(), scToInertial.getAcceleration()),
239 convertRotation(scToInertial.getRotation(), scToInertial.getRotationRate(), scToInertial.getRotationAcceleration()));
240 tranformsDumped[index] = true;
241 }
242 }
243
244
245
246
247 public void dumpSensorMeanPlane(final SensorMeanPlaneCrossing meanPlane) {
248 getSensorData(meanPlane.getSensor()).setMeanPlane(meanPlane);
249 }
250
251
252
253
254
255
256
257 public void dumpSensorLOS(final LineSensor sensor, final AbsoluteDate date, final int i, final Vector3D los) {
258 getSensorData(sensor).setLOS(date, i, los);
259 }
260
261
262
263
264
265
266 public void dumpSensorDatation(final LineSensor sensor, final double lineNumber, final AbsoluteDate date) {
267 getSensorData(sensor).setDatation(lineNumber, date);
268 }
269
270
271
272
273
274
275 public void dumpSensorRate(final LineSensor sensor, final double lineNumber, final double rate) {
276 getSensorData(sensor).setRate(lineNumber, rate);
277 }
278
279
280
281
282
283 private String getKeyOrName(final Frame frame) {
284 if (frame instanceof FactoryManagedFrame) {
285
286 return ((FactoryManagedFrame) frame).getFactoryKey().toString();
287 } else {
288
289 return frame.getName();
290 }
291 }
292
293
294
295
296
297 private DumpedTileData getTileData(final Tile tile) {
298
299 for (final DumpedTileData dumpedTileData : tiles) {
300 if (tile == dumpedTileData.getTile()) {
301
302 return dumpedTileData;
303 }
304 }
305
306
307 final DumpedTileData dumpedTileData = new DumpedTileData("t" + tiles.size(), tile);
308 tiles.add(dumpedTileData);
309 dumpedTileData.setElevation(tile.getMinElevationLatitudeIndex(),
310 tile.getMinElevationLongitudeIndex(),
311 tile.getMinElevation());
312 dumpedTileData.setElevation(tile.getMaxElevationLatitudeIndex(),
313 tile.getMaxElevationLongitudeIndex(),
314 tile.getMaxElevation());
315 return dumpedTileData;
316
317 }
318
319
320
321
322
323 private DumpedSensorData getSensorData(final LineSensor sensor) {
324
325 for (final DumpedSensorData dumpedSensorData : sensors) {
326 if (sensor == dumpedSensorData.getSensor()) {
327
328 return dumpedSensorData;
329 }
330 }
331
332
333 final DumpedSensorData dumpedSensorData = new DumpedSensorData("s" + sensors.size(), sensor);
334 sensors.add(dumpedSensorData);
335 return dumpedSensorData;
336
337 }
338
339
340
341
342
343 private String convertDate(final AbsoluteDate date) {
344 final DateTimeComponents dt = date.getComponents(TimeScalesFactory.getUTC());
345 return String.format(Locale.US, "%04d-%02d-%02dT%02d:%02d:%017.14fZ",
346 dt.getDate().getYear(), dt.getDate().getMonth(), dt.getDate().getDay(),
347 dt.getTime().getHour(), dt.getTime().getMinute(), dt.getTime().getSecond());
348 }
349
350
351
352
353
354
355
356 private String convertTranslation(final Vector3D translation, final Vector3D velocity, final Vector3D acceleration) {
357 return String.format(Locale.US,
358 "p %22.15e %22.15e %22.15e v %22.15e %22.15e %22.15e a %22.15e %22.15e %22.15e",
359 translation.getX(), translation.getY(), translation.getZ(),
360 velocity.getX(), velocity.getY(), velocity.getZ(),
361 acceleration.getX(), acceleration.getY(), acceleration.getZ());
362 }
363
364
365
366
367
368
369
370 private String convertRotation(final Rotation rotation, final Vector3D rate, final Vector3D acceleration) {
371 return String.format(Locale.US,
372 "r %22.15e %22.15e %22.15e %22.15e Ω %22.15e %22.15e %22.15e ΩDot %22.15e %22.15e %22.15e",
373 rotation.getQ0(), rotation.getQ1(), rotation.getQ2(), rotation.getQ3(),
374 rate.getX(), rate.getY(), rate.getZ(),
375 acceleration.getX(), acceleration.getY(), acceleration.getZ());
376 }
377
378
379
380 public void deactivate() {
381 writer.close();
382 }
383
384
385 private class DumpedTileData {
386
387
388 private final String name;
389
390
391 private final Tile tile;
392
393
394 private final OpenIntToDoubleHashMap elevations;
395
396
397
398
399
400 DumpedTileData(final String name, final Tile tile) {
401 this.name = name;
402 this.tile = tile;
403 this.elevations = new OpenIntToDoubleHashMap();
404 writer.format(Locale.US,
405 "DEM tile: %s latMin %22.15e latStep %22.15e latRows %d lonMin %22.15e lonStep %22.15e lonCols %d%n",
406 name,
407 tile.getMinimumLatitude(), tile.getLatitudeStep(), tile.getLatitudeRows(),
408 tile.getMinimumLongitude(), tile.getLongitudeStep(), tile.getLongitudeColumns());
409 }
410
411
412
413
414 public Tile getTile() {
415 return tile;
416 }
417
418
419
420
421
422
423 public void setElevation(final int latitudeIndex, final int longitudeIndex, final double elevation) {
424 final int key = latitudeIndex * tile.getLongitudeColumns() + longitudeIndex;
425 if (!elevations.containsKey(key)) {
426
427 elevations.put(key, elevation);
428 writer.format(Locale.US,
429 "DEM cell: %s latIndex %d lonIndex %d elevation %22.15e%n",
430 name, latitudeIndex, longitudeIndex, elevation);
431 }
432 }
433
434 }
435
436
437 private class DumpedSensorData {
438
439
440 private final String dumpName;
441
442
443 private final LineSensor sensor;
444
445
446 private final Map<Integer, List<Pair<AbsoluteDate, Vector3D>>> losMap;
447
448
449 private final List<Pair<Double, AbsoluteDate>> datation;
450
451
452 private final List<Pair<Double, Double>> rates;
453
454
455 private SensorMeanPlaneCrossing meanPlane;
456
457
458
459
460
461 DumpedSensorData(final String dumpName, final LineSensor sensor) {
462 this.dumpName = dumpName;
463 this.sensor = sensor;
464 this.losMap = new HashMap<Integer, List<Pair<AbsoluteDate, Vector3D>>>();
465 this.datation = new ArrayList<Pair<Double, AbsoluteDate>>();
466 this.rates = new ArrayList<Pair<Double, Double>>();
467 writer.format(Locale.US,
468 "sensor: sensorName %s nbPixels %d position %22.15e %22.15e %22.15e%n",
469 dumpName, sensor.getNbPixels(),
470 sensor.getPosition().getX(), sensor.getPosition().getY(), sensor.getPosition().getZ());
471 }
472
473
474
475
476 public String getDumpName() {
477 return dumpName;
478 }
479
480
481
482
483 public LineSensor getSensor() {
484 return sensor;
485 }
486
487
488
489
490 public void setMeanPlane(final SensorMeanPlaneCrossing meanPlane) {
491
492 if (this.meanPlane == null) {
493 this.meanPlane = meanPlane;
494 final long nbResults = meanPlane.getCachedResults().count();
495 writer.format(Locale.US,
496 "sensor mean plane: sensorName %s minLine %d maxLine %d maxEval %d accuracy %22.15e normal %22.15e %22.15e %22.15e cachedResults %d",
497 dumpName,
498 meanPlane.getMinLine(), meanPlane.getMaxLine(),
499 meanPlane.getMaxEval(), meanPlane.getAccuracy(),
500 meanPlane.getMeanPlaneNormal().getX(), meanPlane.getMeanPlaneNormal().getY(), meanPlane.getMeanPlaneNormal().getZ(),
501 nbResults);
502 meanPlane.getCachedResults().forEach(result -> {
503 try {
504 writer.format(Locale.US,
505 " lineNumber %22.15e date %s target %22.15e %22.15e %22.15e targetDirection %22.15e %22.15e %22.15e %22.15e %22.15e %22.15e",
506 result.getLine(), convertDate(result.getDate()),
507 result.getTarget().getX(), result.getTarget().getY(), result.getTarget().getZ(),
508 result.getTargetDirection().getX(),
509 result.getTargetDirection().getY(),
510 result.getTargetDirection().getZ(),
511 result.getTargetDirectionDerivative().getZ(),
512 result.getTargetDirectionDerivative().getY(),
513 result.getTargetDirectionDerivative().getZ());
514 } catch (RuggedException re) {
515 throw new RuggedInternalError(re);
516 }
517 });
518 writer.format(Locale.US, "%n");
519
520
521 final AbsoluteDate midDate = meanPlane.getSensor().getDate(0.5 * (meanPlane.getMinLine() + meanPlane.getMaxLine()));
522 meanPlane.getScToBody().getBodyToInertial(midDate);
523 meanPlane.getScToBody().getScToInertial(midDate);
524 }
525 }
526
527
528
529
530
531
532 public void setLOS(final AbsoluteDate date, final int pixelNumber, final Vector3D los) {
533 List<Pair<AbsoluteDate, Vector3D>> list = losMap.get(pixelNumber);
534 if (list == null) {
535 list = new ArrayList<Pair<AbsoluteDate, Vector3D>>();
536 losMap.put(pixelNumber, list);
537 }
538 for (final Pair<AbsoluteDate, Vector3D> alreadyDumped : list) {
539 if (FastMath.abs(date.durationFrom(alreadyDumped.getFirst())) < 1.0e-12 &&
540 Vector3D.angle(los, alreadyDumped.getSecond()) < 1.0e-12) {
541 return;
542 }
543 }
544 list.add(new Pair<AbsoluteDate, Vector3D>(date, los));
545 writer.format(Locale.US,
546 "sensor LOS: sensorName %s date %s pixelNumber %d los %22.15e %22.15e %22.15e%n",
547 dumpName, convertDate(date), pixelNumber, los.getX(), los.getY(), los.getZ());
548 }
549
550
551
552
553
554 public void setDatation(final double lineNumber, final AbsoluteDate date) {
555 for (final Pair<Double, AbsoluteDate> alreadyDumped : datation) {
556 if (FastMath.abs(date.durationFrom(alreadyDumped.getSecond())) < 1.0e-12 &&
557 FastMath.abs(lineNumber - alreadyDumped.getFirst()) < 1.0e-12) {
558 return;
559 }
560 }
561 datation.add(new Pair<Double, AbsoluteDate>(lineNumber, date));
562 writer.format(Locale.US,
563 "sensor datation: sensorName %s lineNumber %22.15e date %s%n",
564 dumpName, lineNumber, convertDate(date));
565 }
566
567
568
569
570
571 public void setRate(final double lineNumber, final double rate) {
572 for (final Pair<Double, Double> alreadyDumped : rates) {
573 if (FastMath.abs(rate - alreadyDumped.getSecond()) < 1.0e-12 &&
574 FastMath.abs(lineNumber - alreadyDumped.getFirst()) < 1.0e-12) {
575 return;
576 }
577 }
578 rates.add(new Pair<Double, Double>(lineNumber, rate));
579 writer.format(Locale.US,
580 "sensor rate: sensorName %s lineNumber %22.15e rate %22.15e%n",
581 dumpName, lineNumber, rate);
582 }
583
584 }
585
586 }