1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ilrs;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.SortedSet;
23 import java.util.TreeSet;
24 import java.util.stream.Collectors;
25
26 import org.orekit.time.AbsoluteDate;
27 import org.orekit.time.ChronologicalComparator;
28 import org.orekit.time.TimeStamped;
29 import org.orekit.utils.ImmutableTimeStampedCache;
30
31
32
33
34
35
36
37 public class CRD {
38
39
40 private List<String> comments;
41
42
43 private List<CRDDataBlock> dataBlocks;
44
45
46
47
48 public CRD() {
49
50 this.comments = new ArrayList<>();
51 this.dataBlocks = new ArrayList<>();
52 }
53
54
55
56
57
58 public void addDataBlock(final CRDDataBlock dataBlock) {
59 dataBlocks.add(dataBlock);
60 }
61
62
63
64
65
66 public List<String> getComments() {
67 return comments;
68 }
69
70
71
72
73
74 public List<CRDDataBlock> getDataBlocks() {
75 return Collections.unmodifiableList(dataBlocks);
76 }
77
78
79
80
81
82
83
84
85 public static class CRDDataBlock {
86
87
88 private CRDHeader header;
89
90
91 private CRDConfiguration configurationRecords;
92
93
94 private List<RangeMeasurement> rangeData;
95
96
97 private final SortedSet<MeteorologicalMeasurement> meteoData;
98
99
100 private List<AnglesMeasurement> anglesData;
101
102
103
104
105 public CRDDataBlock() {
106
107 this.rangeData = new ArrayList<>();
108 this.meteoData = new TreeSet<>(new ChronologicalComparator());
109 this.anglesData = new ArrayList<>();
110 }
111
112
113
114
115
116 public CRDHeader getHeader() {
117 return header;
118 }
119
120
121
122
123
124 public void setHeader(final CRDHeader header) {
125 this.header = header;
126 }
127
128
129
130
131
132 public CRDConfiguration getConfigurationRecords() {
133 return configurationRecords;
134 }
135
136
137
138
139
140 public void setConfigurationRecords(final CRDConfiguration configurationRecords) {
141 this.configurationRecords = configurationRecords;
142 }
143
144
145
146
147
148 public void addRangeData(final RangeMeasurement range) {
149 rangeData.add(range);
150 }
151
152
153
154
155
156 public void addMeteoData(final MeteorologicalMeasurement meteorologicalMeasurement) {
157 meteoData.add(meteorologicalMeasurement);
158 }
159
160
161
162
163
164 public void addAnglesData(final AnglesMeasurement angles) {
165 anglesData.add(angles);
166 }
167
168
169
170
171
172 public List<RangeMeasurement> getRangeData() {
173 return Collections.unmodifiableList(rangeData);
174 }
175
176
177
178
179
180 public List<AnglesMeasurement> getAnglesData() {
181 return Collections.unmodifiableList(anglesData);
182 }
183
184
185
186
187
188 public Meteo getMeteoData() {
189 return new Meteo(meteoData);
190 }
191
192 }
193
194
195 public static class RangeMeasurement implements TimeStamped {
196
197
198 private AbsoluteDate date;
199
200
201 private final double timeOfFlight;
202
203
204
205
206
207
208
209
210
211
212
213 private final int epochEvent;
214
215
216 private final double snr;
217
218
219
220
221
222
223
224 public RangeMeasurement(final AbsoluteDate date,
225 final double timeOfFlight,
226 final int epochEvent) {
227 this(date, timeOfFlight, epochEvent, Double.NaN);
228 }
229
230
231
232
233
234
235
236
237 public RangeMeasurement(final AbsoluteDate date,
238 final double timeOfFlight,
239 final int epochEvent, final double snr) {
240 this.date = date;
241 this.timeOfFlight = timeOfFlight;
242 this.epochEvent = epochEvent;
243 this.snr = snr;
244 }
245
246
247
248
249
250 public double getTimeOfFlight() {
251 return timeOfFlight;
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268 public int getEpochEvent() {
269 return epochEvent;
270 }
271
272
273
274
275
276 public double getSnr() {
277 return snr;
278 }
279
280
281 @Override
282 public AbsoluteDate getDate() {
283 return date;
284 }
285
286 }
287
288
289 public static class MeteorologicalMeasurement implements TimeStamped {
290
291
292 private AbsoluteDate date;
293
294
295 private final double pressure;
296
297
298 private final double temperature;
299
300
301 private final double humidity;
302
303
304
305
306
307
308
309
310 public MeteorologicalMeasurement(final AbsoluteDate date,
311 final double pressure, final double temperature,
312 final double humidity) {
313 this.date = date;
314 this.pressure = pressure;
315 this.temperature = temperature;
316 this.humidity = humidity;
317 }
318
319
320
321
322
323 public double getPressure() {
324 return pressure;
325 }
326
327
328
329
330
331 public double getTemperature() {
332 return temperature;
333 }
334
335
336
337
338
339 public double getHumidity() {
340 return humidity;
341 }
342
343
344 @Override
345 public AbsoluteDate getDate() {
346 return date;
347 }
348
349 }
350
351
352 public static class AnglesMeasurement implements TimeStamped {
353
354
355 private AbsoluteDate date;
356
357
358 private final double azimuth;
359
360
361 private final double elevation;
362
363
364 private final int directionFlag;
365
366
367
368
369
370
371
372 private final int originIndicator;
373
374
375 private final boolean refractionCorrected;
376
377
378 private final double azimuthRate;
379
380
381 private final double elevationRate;
382
383
384
385
386
387
388
389
390
391
392
393
394 public AnglesMeasurement(final AbsoluteDate date, final double azimuth,
395 final double elevation, final int directionFlag,
396 final int originIndicator,
397 final boolean refractionCorrected,
398 final double azimuthRate, final double elevationRate) {
399 this.date = date;
400 this.azimuth = azimuth;
401 this.elevation = elevation;
402 this.directionFlag = directionFlag;
403 this.originIndicator = originIndicator;
404 this.refractionCorrected = refractionCorrected;
405 this.azimuthRate = azimuthRate;
406 this.elevationRate = elevationRate;
407 }
408
409
410
411
412
413 public double getAzimuth() {
414 return azimuth;
415 }
416
417
418
419
420
421 public double getElevation() {
422 return elevation;
423 }
424
425
426
427
428
429 public int getDirectionFlag() {
430 return directionFlag;
431 }
432
433
434
435
436
437
438
439
440
441
442
443 public int getOriginIndicator() {
444 return originIndicator;
445 }
446
447
448
449
450
451 public boolean isRefractionCorrected() {
452 return refractionCorrected;
453 }
454
455
456
457
458
459
460
461
462 public double getAzimuthRate() {
463 return azimuthRate;
464 }
465
466
467
468
469
470
471
472
473 public double getElevationRate() {
474 return elevationRate;
475 }
476
477
478 @Override
479 public AbsoluteDate getDate() {
480 return date;
481 }
482
483 }
484
485
486 public static class Meteo {
487
488
489 private static final int N_NEIGHBORS = 2;
490
491
492 private final AbsoluteDate firstDate;
493
494
495 private final AbsoluteDate lastDate;
496
497
498 private transient MeteorologicalMeasurement previousParam;
499
500
501 private transient MeteorologicalMeasurement nextParam;
502
503
504 private final transient ImmutableTimeStampedCache<MeteorologicalMeasurement> meteo;
505
506
507
508
509
510 public Meteo(final SortedSet<MeteorologicalMeasurement> meteoData) {
511
512
513 final int neighborsSize = (meteoData.size() < 2) ? meteoData.size() : N_NEIGHBORS;
514
515
516 if (neighborsSize == 0) {
517
518
519 this.meteo = ImmutableTimeStampedCache.emptyCache();
520
521
522 this.firstDate = null;
523 this.lastDate = null;
524
525 } else {
526
527
528 this.meteo = new ImmutableTimeStampedCache<MeteorologicalMeasurement>(neighborsSize, meteoData);
529
530
531 this.firstDate = meteoData.first().getDate();
532 this.lastDate = meteoData.last().getDate();
533
534 }
535
536 }
537
538
539
540
541
542 public List<MeteorologicalMeasurement> getData() {
543 return meteo.getAll();
544 }
545
546
547
548
549
550
551
552 public MeteorologicalMeasurement getMeteo(final AbsoluteDate date) {
553
554
555 if (meteo.getNeighborsSize() == 0) {
556 return null;
557 }
558
559
560 bracketDate(date);
561 if (date.durationFrom(firstDate) <= 0 || date.durationFrom(lastDate) > 0) {
562
563 return previousParam;
564 } else {
565
566 final double pressure = getLinearInterpolation(date, previousParam.getPressure(), nextParam.getPressure());
567 final double temperature = getLinearInterpolation(date, previousParam.getTemperature(), nextParam.getTemperature());
568 final double humidity = getLinearInterpolation(date, previousParam.getHumidity(), nextParam.getHumidity());
569 return new MeteorologicalMeasurement(date, pressure, temperature, humidity);
570 }
571
572 }
573
574
575
576
577
578 private void bracketDate(final AbsoluteDate date) {
579
580
581 if (previousParam != null &&
582 date.durationFrom(previousParam.getDate()) > 0 &&
583 date.durationFrom(nextParam.getDate()) <= 0) {
584 return;
585 }
586
587
588 if (date.durationFrom(firstDate) <= 0) {
589
590 previousParam = meteo.getEarliest();
591 nextParam = previousParam;
592 } else if (date.durationFrom(lastDate) > 0) {
593
594 previousParam = meteo.getLatest();
595 nextParam = previousParam;
596 } else {
597
598 final List<MeteorologicalMeasurement> neighbors = meteo.getNeighbors(date).collect(Collectors.toList());
599 previousParam = neighbors.get(0);
600 nextParam = neighbors.get(1);
601 }
602
603 }
604
605
606
607
608
609
610
611
612
613 private double getLinearInterpolation(final AbsoluteDate date,
614 final double previousValue,
615 final double nextValue) {
616
617 final AbsoluteDate previousDate = previousParam.getDate();
618 final AbsoluteDate currentDate = nextParam.getDate();
619 final double dt = currentDate.durationFrom(previousDate);
620 final double previousWeight = currentDate.durationFrom(date) / dt;
621 final double nextWeight = date.durationFrom(previousDate) / dt;
622
623
624 return previousValue * previousWeight + nextValue * nextWeight;
625 }
626
627 }
628
629 }