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.errors.OrekitException;
35 import org.orekit.frames.FactoryManagedFrame;
36 import org.orekit.frames.Frame;
37 import org.orekit.frames.Transform;
38 import org.orekit.rugged.api.AlgorithmId;
39 import org.orekit.rugged.linesensor.LineSensor;
40 import org.orekit.rugged.linesensor.SensorMeanPlaneCrossing;
41 import org.orekit.rugged.linesensor.SensorPixel;
42 import org.orekit.rugged.raster.Tile;
43 import org.orekit.rugged.utils.ExtendedEllipsoid;
44 import org.orekit.rugged.utils.SpacecraftToObservedBody;
45 import org.orekit.time.AbsoluteDate;
46 import org.orekit.time.DateTimeComponents;
47 import org.orekit.time.TimeScalesFactory;
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
155 public void dumpDirectLocation(final AbsoluteDate date, final Vector3D position, final Vector3D los,
156 final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection,
157 final boolean refractionCorrection)
158 throws RuggedException {
159 writer.format(Locale.US,
160 "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",
161 convertDate(date),
162 position.getX(), position.getY(), position.getZ(),
163 los.getX(), los.getY(), los.getZ(),
164 lightTimeCorrection, aberrationOfLightCorrection, refractionCorrection);
165 }
166
167
168
169
170
171 public void dumpDirectLocationResult(final GeodeticPoint gp)
172 throws RuggedException {
173 if (gp != null) {
174 writer.format(Locale.US,
175 "direct location result: latitude %22.15e longitude %22.15e elevation %22.15e%n",
176 gp.getLatitude(), gp.getLongitude(), gp.getAltitude());
177 }
178 }
179
180
181
182
183
184
185
186
187
188 public void dumpInverseLocation(final LineSensor sensor, final GeodeticPoint point,
189 final int minLine, final int maxLine,
190 final boolean lightTimeCorrection, final boolean aberrationOfLightCorrection) {
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%n",
194 ds.getDumpName(),
195 point.getLatitude(), point.getLongitude(), point.getAltitude(),
196 minLine, maxLine,
197 lightTimeCorrection, aberrationOfLightCorrection);
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 }
209 }
210
211
212
213
214
215
216
217
218 public void dumpTransform(final SpacecraftToObservedBody scToBody, final int index,
219 final Transform bodyToInertial, final Transform scToInertial)
220 throws RuggedException {
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
248 public void dumpSensorMeanPlane(final SensorMeanPlaneCrossing meanPlane)
249 throws RuggedException {
250 getSensorData(meanPlane.getSensor()).setMeanPlane(meanPlane);
251 }
252
253
254
255
256
257
258
259
260 public void dumpSensorLOS(final LineSensor sensor, final AbsoluteDate date, final int i, final Vector3D los)
261 throws RuggedException {
262 getSensorData(sensor).setLOS(date, i, los);
263 }
264
265
266
267
268
269
270
271 public void dumpSensorDatation(final LineSensor sensor, final double lineNumber, final AbsoluteDate date)
272 throws RuggedException {
273 getSensorData(sensor).setDatation(lineNumber, date);
274 }
275
276
277
278
279
280
281 public void dumpSensorRate(final LineSensor sensor, final double lineNumber, final double rate) {
282 getSensorData(sensor).setRate(lineNumber, rate);
283 }
284
285
286
287
288
289 private String getKeyOrName(final Frame frame) {
290 if (frame instanceof FactoryManagedFrame) {
291
292 return ((FactoryManagedFrame) frame).getFactoryKey().toString();
293 } else {
294
295 return frame.getName();
296 }
297 }
298
299
300
301
302
303 private DumpedTileData getTileData(final Tile tile) {
304
305 for (final DumpedTileData dumpedTileData : tiles) {
306 if (tile == dumpedTileData.getTile()) {
307
308 return dumpedTileData;
309 }
310 }
311
312
313 final DumpedTileData dumpedTileData = new DumpedTileData("t" + tiles.size(), tile);
314 tiles.add(dumpedTileData);
315 dumpedTileData.setElevation(tile.getMinElevationLatitudeIndex(),
316 tile.getMinElevationLongitudeIndex(),
317 tile.getMinElevation());
318 dumpedTileData.setElevation(tile.getMaxElevationLatitudeIndex(),
319 tile.getMaxElevationLongitudeIndex(),
320 tile.getMaxElevation());
321 return dumpedTileData;
322
323 }
324
325
326
327
328
329 private DumpedSensorData getSensorData(final LineSensor sensor) {
330
331 for (final DumpedSensorData dumpedSensorData : sensors) {
332 if (sensor == dumpedSensorData.getSensor()) {
333
334 return dumpedSensorData;
335 }
336 }
337
338
339 final DumpedSensorData dumpedSensorData = new DumpedSensorData("s" + sensors.size(), sensor);
340 sensors.add(dumpedSensorData);
341 return dumpedSensorData;
342
343 }
344
345
346
347
348
349
350 private String convertDate(final AbsoluteDate date)
351 throws RuggedException {
352 try {
353 final DateTimeComponents dt = date.getComponents(TimeScalesFactory.getUTC());
354 return String.format(Locale.US, "%04d-%02d-%02dT%02d:%02d:%017.14fZ",
355 dt.getDate().getYear(), dt.getDate().getMonth(), dt.getDate().getDay(),
356 dt.getTime().getHour(), dt.getTime().getMinute(), dt.getTime().getSecond());
357 } catch (OrekitException oe) {
358 throw new RuggedException(oe, oe.getSpecifier(), oe.getParts());
359 }
360 }
361
362
363
364
365
366
367
368 private String convertTranslation(final Vector3D translation, final Vector3D velocity, final Vector3D acceleration) {
369 return String.format(Locale.US,
370 "p %22.15e %22.15e %22.15e v %22.15e %22.15e %22.15e a %22.15e %22.15e %22.15e",
371 translation.getX(), translation.getY(), translation.getZ(),
372 velocity.getX(), velocity.getY(), velocity.getZ(),
373 acceleration.getX(), acceleration.getY(), acceleration.getZ());
374 }
375
376
377
378
379
380
381
382 private String convertRotation(final Rotation rotation, final Vector3D rate, final Vector3D acceleration) {
383 return String.format(Locale.US,
384 "r %22.15e %22.15e %22.15e %22.15e Ω %22.15e %22.15e %22.15e ΩDot %22.15e %22.15e %22.15e",
385 rotation.getQ0(), rotation.getQ1(), rotation.getQ2(), rotation.getQ3(),
386 rate.getX(), rate.getY(), rate.getZ(),
387 acceleration.getX(), acceleration.getY(), acceleration.getZ());
388 }
389
390
391
392 public void deactivate() {
393 writer.close();
394 }
395
396
397 private class DumpedTileData {
398
399
400 private final String name;
401
402
403 private final Tile tile;
404
405
406 private final OpenIntToDoubleHashMap elevations;
407
408
409
410
411
412 DumpedTileData(final String name, final Tile tile) {
413 this.name = name;
414 this.tile = tile;
415 this.elevations = new OpenIntToDoubleHashMap();
416 writer.format(Locale.US,
417 "DEM tile: %s latMin %22.15e latStep %22.15e latRows %d lonMin %22.15e lonStep %22.15e lonCols %d%n",
418 name,
419 tile.getMinimumLatitude(), tile.getLatitudeStep(), tile.getLatitudeRows(),
420 tile.getMinimumLongitude(), tile.getLongitudeStep(), tile.getLongitudeColumns());
421 }
422
423
424
425
426 public Tile getTile() {
427 return tile;
428 }
429
430
431
432
433
434
435 public void setElevation(final int latitudeIndex, final int longitudeIndex, final double elevation) {
436 final int key = latitudeIndex * tile.getLongitudeColumns() + longitudeIndex;
437 if (!elevations.containsKey(key)) {
438
439 elevations.put(key, elevation);
440 writer.format(Locale.US,
441 "DEM cell: %s latIndex %d lonIndex %d elevation %22.15e%n",
442 name, latitudeIndex, longitudeIndex, elevation);
443 }
444 }
445
446 }
447
448
449 private class DumpedSensorData {
450
451
452 private final String dumpName;
453
454
455 private final LineSensor sensor;
456
457
458 private final Map<Integer, List<Pair<AbsoluteDate, Vector3D>>> losMap;
459
460
461 private final List<Pair<Double, AbsoluteDate>> datation;
462
463
464 private final List<Pair<Double, Double>> rates;
465
466
467 private SensorMeanPlaneCrossing meanPlane;
468
469
470
471
472
473 DumpedSensorData(final String dumpName, final LineSensor sensor) {
474 this.dumpName = dumpName;
475 this.sensor = sensor;
476 this.losMap = new HashMap<Integer, List<Pair<AbsoluteDate, Vector3D>>>();
477 this.datation = new ArrayList<Pair<Double, AbsoluteDate>>();
478 this.rates = new ArrayList<Pair<Double, Double>>();
479 writer.format(Locale.US,
480 "sensor: sensorName %s nbPixels %d position %22.15e %22.15e %22.15e%n",
481 dumpName, sensor.getNbPixels(),
482 sensor.getPosition().getX(), sensor.getPosition().getY(), sensor.getPosition().getZ());
483 }
484
485
486
487
488 public String getDumpName() {
489 return dumpName;
490 }
491
492
493
494
495 public LineSensor getSensor() {
496 return sensor;
497 }
498
499
500
501
502
503 public void setMeanPlane(final SensorMeanPlaneCrossing meanPlane) throws RuggedException {
504 try {
505 if (this.meanPlane == null) {
506 this.meanPlane = meanPlane;
507 final long nbResults = meanPlane.getCachedResults().count();
508 writer.format(Locale.US,
509 "sensor mean plane: sensorName %s minLine %d maxLine %d maxEval %d accuracy %22.15e normal %22.15e %22.15e %22.15e cachedResults %d",
510 dumpName,
511 meanPlane.getMinLine(), meanPlane.getMaxLine(),
512 meanPlane.getMaxEval(), meanPlane.getAccuracy(),
513 meanPlane.getMeanPlaneNormal().getX(), meanPlane.getMeanPlaneNormal().getY(), meanPlane.getMeanPlaneNormal().getZ(),
514 nbResults);
515 meanPlane.getCachedResults().forEach(result -> {
516 try {
517 writer.format(Locale.US,
518 " 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",
519 result.getLine(), convertDate(result.getDate()),
520 result.getTarget().getX(), result.getTarget().getY(), result.getTarget().getZ(),
521 result.getTargetDirection().getX(),
522 result.getTargetDirection().getY(),
523 result.getTargetDirection().getZ(),
524 result.getTargetDirectionDerivative().getZ(),
525 result.getTargetDirectionDerivative().getY(),
526 result.getTargetDirectionDerivative().getZ());
527 } catch (RuggedException re) {
528 throw new RuggedExceptionWrapper(re);
529 }
530 });
531 writer.format(Locale.US, "%n");
532
533
534 final AbsoluteDate midDate = meanPlane.getSensor().getDate(0.5 * (meanPlane.getMinLine() + meanPlane.getMaxLine()));
535 meanPlane.getScToBody().getBodyToInertial(midDate);
536 meanPlane.getScToBody().getScToInertial(midDate);
537
538 }
539 } catch (RuggedExceptionWrapper rew) {
540 throw rew.getException();
541 }
542 }
543
544
545
546
547
548
549
550 public void setLOS(final AbsoluteDate date, final int pixelNumber, final Vector3D los)
551 throws RuggedException {
552 List<Pair<AbsoluteDate, Vector3D>> list = losMap.get(pixelNumber);
553 if (list == null) {
554 list = new ArrayList<Pair<AbsoluteDate, Vector3D>>();
555 losMap.put(pixelNumber, list);
556 }
557 for (final Pair<AbsoluteDate, Vector3D> alreadyDumped : list) {
558 if (FastMath.abs(date.durationFrom(alreadyDumped.getFirst())) < 1.0e-12 &&
559 Vector3D.angle(los, alreadyDumped.getSecond()) < 1.0e-12) {
560 return;
561 }
562 }
563 list.add(new Pair<AbsoluteDate, Vector3D>(date, los));
564 writer.format(Locale.US,
565 "sensor LOS: sensorName %s date %s pixelNumber %d los %22.15e %22.15e %22.15e%n",
566 dumpName, convertDate(date), pixelNumber, los.getX(), los.getY(), los.getZ());
567 }
568
569
570
571
572
573
574 public void setDatation(final double lineNumber, final AbsoluteDate date)
575 throws RuggedException {
576 for (final Pair<Double, AbsoluteDate> alreadyDumped : datation) {
577 if (FastMath.abs(date.durationFrom(alreadyDumped.getSecond())) < 1.0e-12 &&
578 FastMath.abs(lineNumber - alreadyDumped.getFirst()) < 1.0e-12) {
579 return;
580 }
581 }
582 datation.add(new Pair<Double, AbsoluteDate>(lineNumber, date));
583 writer.format(Locale.US,
584 "sensor datation: sensorName %s lineNumber %22.15e date %s%n",
585 dumpName, lineNumber, convertDate(date));
586 }
587
588
589
590
591
592 public void setRate(final double lineNumber, final double rate) {
593 for (final Pair<Double, Double> alreadyDumped : rates) {
594 if (FastMath.abs(rate - alreadyDumped.getSecond()) < 1.0e-12 &&
595 FastMath.abs(lineNumber - alreadyDumped.getFirst()) < 1.0e-12) {
596 return;
597 }
598 }
599 rates.add(new Pair<Double, Double>(lineNumber, rate));
600 writer.format(Locale.US,
601 "sensor rate: sensorName %s lineNumber %22.15e rate %22.15e%n",
602 dumpName, lineNumber, rate);
603 }
604
605 }
606
607 }