1 /* Copyright 2002-2024 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.files.ilrs;
18
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.regex.Pattern;
22
23 import org.orekit.annotation.DefaultDataContext;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitMessages;
26 import org.orekit.time.DateComponents;
27 import org.orekit.time.TimeScale;
28 import org.orekit.time.TimeScalesFactory;
29
30 /**
31 * Container for Consolidated laser ranging Data Format (CDR) header.
32 * @author Bryan Cazabonne
33 * @author Rongwang Li
34 * @since 10.3
35 */
36 public class CRDHeader extends ILRSHeader {
37
38 /** String delimiter regex of datetime. */
39 private static final String DATETIME_DELIMITER_REGEX = "[-:T]";
40
41 /** Space. */
42 private static final String SPACE = " ";
43
44 /** Pattern of delimiter of datetime. */
45 public static final Pattern PATTERN_DATETIME_DELIMITER_REGEX = Pattern.compile(DATETIME_DELIMITER_REGEX);
46
47 /** Station name from official list. */
48 private String stationName;
49
50 /** System identifier: Crustal Dynamics Project (CDP) Pad Identifier for SLR. */
51 private int systemIdentifier;
52
53 /** System number: Crustal Dynamics Project (CDP) 2-digit system number for SLR. */
54 private int systemNumber;
55
56 /** System occupancy: Crustal Dynamics Project (CDP) 2-digit occupancy sequence number for SLR. */
57 private int systemOccupancy;
58
59 /** Station Epoch Time Scale. */
60 private int epochIdentifier;
61
62 /** Station network. */
63 private String stationNetword;
64
65 /** Spacecraft Epoch Time Scale (transponders only). */
66 private int spacecraftEpochTimeScale;
67
68 /** Data type. */
69 private int dataType;
70
71 /** A flag to indicate the data release. */
72 private int dataReleaseFlag;
73
74 /** Tropospheric refraction correction applied indicator. */
75 private boolean isTroposphericRefractionApplied;
76
77 /** Center of mass correction applied indicator. */
78 private boolean isCenterOfMassCorrectionApplied;
79
80 /** Receive amplitude correction applied indicator. */
81 private boolean isReceiveAmplitudeCorrectionApplied;
82
83 /** Station system delay applied indicator. */
84 private boolean isStationSystemDelayApplied;
85
86 /** Spacecraft system delay applied (transponders) indicator. */
87 private boolean isTransponderDelayApplied;
88
89 /** Range type. */
90 private RangeType rangeType;
91
92 /** Data quality indicator. */
93 private int qualityIndicator;
94
95 /** Prediction type (CPF or TLE). */
96 private int predictionType;
97
98 /** Year of century from CPF or TLE. */
99 private int yearOfCentury;
100
101 /**
102 * Date and time.
103 * CPF starting date and hour (MMDDHH) from CPF H2 record or
104 * TLE epoch day/fractional day.
105 */
106 private String dateAndTime;
107
108 /** Prediction provider (CPF provider in H1 record or TLE source). */
109 private String predictionProvider;
110
111 /** Empty constructor.
112 * <p>
113 * This constructor is not strictly necessary, but it prevents spurious
114 * javadoc warnings with JDK 18 and later.
115 * </p>
116 * @since 12.0
117 */
118 public CRDHeader() {
119 // nothing to do
120 }
121
122 /**
123 * Get the station name from official list.
124 * @return the station name from official list
125 */
126 public String getStationName() {
127 return stationName;
128 }
129
130 /**
131 * Set the station name from official list.
132 * @param stationName the station name to set
133 */
134 public void setStationName(final String stationName) {
135 this.stationName = stationName;
136 }
137
138 /**
139 * Get the system identifier.
140 * @return the system identifier
141 */
142 public int getSystemIdentifier() {
143 return systemIdentifier;
144 }
145
146 /**
147 * Set the system identifier.
148 * @param systemIdentifier the system identifier to set
149 */
150 public void setSystemIdentifier(final int systemIdentifier) {
151 this.systemIdentifier = systemIdentifier;
152 }
153
154 /**
155 * Get the system number.
156 * @return the system number
157 */
158 public int getSystemNumber() {
159 return systemNumber;
160 }
161
162 /**
163 * Set the system number.
164 * @param systemNumber the system number to set
165 */
166 public void setSystemNumber(final int systemNumber) {
167 this.systemNumber = systemNumber;
168 }
169
170 /**
171 * Get the system occupancy.
172 * @return the system occupancy
173 */
174 public int getSystemOccupancy() {
175 return systemOccupancy;
176 }
177
178 /**
179 * Set the system occupancy.
180 * @param systemOccupancy the system occupancy to set
181 */
182 public void setSystemOccupancy(final int systemOccupancy) {
183 this.systemOccupancy = systemOccupancy;
184 }
185
186 /**
187 * Get the epoch identifier.
188 * <p>
189 * 3 = UTC (UNSO) ; 4 = UTC (GPS) ; 7 = UTC (BIPM) ; 10 = UTC (Station Time Scale)
190 * </p>
191 * @return the epoch identifier
192 */
193 public int getEpochIdentifier() {
194 return epochIdentifier;
195 }
196
197 /**
198 * Set the epoch identifier.
199 * @param epochIdentifier the epoch identifier to set
200 */
201 public void setEpochIdentifier(final int epochIdentifier) {
202 this.epochIdentifier = epochIdentifier;
203 }
204
205 /**
206 * Get the station network.
207 * @return the station network
208 */
209 public String getStationNetword() {
210 return stationNetword;
211 }
212
213 /**
214 * Set the station network.
215 * @param stationNetword the station network to set
216 */
217 public void setStationNetword(final String stationNetword) {
218 this.stationNetword = stationNetword;
219 }
220
221 /**
222 * Get the spacecraft epoch time scale.
223 * @return the spacecraft epoch time scale
224 */
225 public int getSpacecraftEpochTimeScale() {
226 return spacecraftEpochTimeScale;
227 }
228
229 /**
230 * Set the spacecraft epoch time scale.
231 * @param spacecraftEpochTimeScale the spacecraft epoch time scale to set
232 */
233 public void setSpacecraftEpochTimeScale(final int spacecraftEpochTimeScale) {
234 this.spacecraftEpochTimeScale = spacecraftEpochTimeScale;
235 }
236
237 /**
238 * Get the data type.
239 * <p>
240 * 0 = full rate ; 1 = normal point ; 2 = sampled engineering
241 * </p>
242 * @return the data type
243 */
244 public int getDataType() {
245 return dataType;
246 }
247
248 /**
249 * Set the data type.
250 * @param dataType the data type to set
251 */
252 public void setDataType(final int dataType) {
253 this.dataType = dataType;
254 }
255
256 /**
257 * Get the flag indicating the data release.
258 * @return the flag indicating the data release
259 */
260 public int getDataReleaseFlag() {
261 return dataReleaseFlag;
262 }
263
264 /**
265 * Set the flag indicating the data release.
266 * @param dataReleaseFlag the flag to set
267 */
268 public void setDataReleaseFlag(final int dataReleaseFlag) {
269 this.dataReleaseFlag = dataReleaseFlag;
270 }
271
272 /**
273 * Get the tropospheric refraction correction applied indicator.
274 * @return true if tropospheric refraction correction is applied
275 */
276 public boolean isTroposphericRefractionApplied() {
277 return isTroposphericRefractionApplied;
278 }
279
280 /**
281 * Set the tropospheric refraction correction applied indicator.
282 * @param isTroposphericRefractionApplied true if tropospheric refraction correction is applied
283 */
284 public void setIsTroposphericRefractionApplied(final boolean isTroposphericRefractionApplied) {
285 this.isTroposphericRefractionApplied = isTroposphericRefractionApplied;
286 }
287
288 /**
289 * Get the center of mass correction applied indicator.
290 * @return true if center of mass correction is applied
291 */
292 public boolean isCenterOfMassCorrectionApplied() {
293 return isCenterOfMassCorrectionApplied;
294 }
295
296 /**
297 * Set the center of mass correction applied indicator.
298 * @param isCenterOfMassCorrectionApplied true if center of mass correction is applied
299 */
300 public void setIsCenterOfMassCorrectionApplied(final boolean isCenterOfMassCorrectionApplied) {
301 this.isCenterOfMassCorrectionApplied = isCenterOfMassCorrectionApplied;
302 }
303
304 /**
305 * Get the receive amplitude correction applied indicator.
306 * @return true if receive amplitude correction is applied
307 */
308 public boolean isReceiveAmplitudeCorrectionApplied() {
309 return isReceiveAmplitudeCorrectionApplied;
310 }
311
312 /**
313 * Set the receive amplitude correction applied indicator.
314 * @param isReceiveAmplitudeCorrectionApplied true if receive amplitude correction is applied
315 */
316 public void setIsReceiveAmplitudeCorrectionApplied(final boolean isReceiveAmplitudeCorrectionApplied) {
317 this.isReceiveAmplitudeCorrectionApplied = isReceiveAmplitudeCorrectionApplied;
318 }
319
320 /**
321 * Get the station system delay applied indicator.
322 * @return true if station system delay is applied
323 */
324 public boolean isStationSystemDelayApplied() {
325 return isStationSystemDelayApplied;
326 }
327
328 /**
329 * Set the station system delay applied indicator.
330 * @param isStationSystemDelayApplied true if station system delay is applied
331 */
332 public void setIsStationSystemDelayApplied(final boolean isStationSystemDelayApplied) {
333 this.isStationSystemDelayApplied = isStationSystemDelayApplied;
334 }
335
336 /**
337 * Get the spacecraft system delay applied (transponders) indicator.
338 * @return true if transponder delay is applied
339 */
340 public boolean isTransponderDelayApplied() {
341 return isTransponderDelayApplied;
342 }
343
344 /**
345 * Set the spacecraft system delay applied (transponders) indicator.
346 * @param isTransponderDelayApplied true if transponder delay is applied
347 */
348 public void setIsTransponderDelayApplied(final boolean isTransponderDelayApplied) {
349 this.isTransponderDelayApplied = isTransponderDelayApplied;
350 }
351
352 /**
353 * Get the range type.
354 * @return the range type
355 */
356 public RangeType getRangeType() {
357 return rangeType;
358 }
359
360 /**
361 * Set the range type indicator.
362 * @param indicator range type indicator
363 */
364 public void setRangeType(final int indicator) {
365 this.rangeType = RangeType.getRangeType(indicator);
366 }
367
368 /**
369 * Get the data quality indicator.
370 * @return the data quality indicator
371 */
372 public int getQualityIndicator() {
373 return qualityIndicator;
374 }
375
376 /**
377 * Set the data quality indicator.
378 * @param qualityIndicator the indicator to set
379 */
380 public void setQualityIndicator(final int qualityIndicator) {
381 this.qualityIndicator = qualityIndicator;
382 }
383
384 /**
385 * Get the prediction type (CPF or TLE).
386 * @return the prediction type
387 */
388 public int getPredictionType() {
389 return predictionType;
390 }
391
392 /**
393 * Set the prediction type.
394 * @param predictionType the prediction type to set
395 */
396 public void setPredictionType(final int predictionType) {
397 this.predictionType = predictionType;
398 }
399
400 /**
401 * Get the year of century from CPF or TLE.
402 * @return the year of century from CPF or TLE
403 */
404 public int getYearOfCentury() {
405 return yearOfCentury;
406 }
407
408 /**
409 * Set the year of century from CPF or TLE.
410 * @param yearOfCentury the year of century to set
411 */
412 public void setYearOfCentury(final int yearOfCentury) {
413 this.yearOfCentury = yearOfCentury;
414 }
415
416
417 /**
418 * Get the date and time as the string value.
419 * <p>
420 * Depending the prediction type, this value can represent the
421 * CPF starting date and hour (MMDDHH) from CPF H2 record or
422 * TLE epoch day/fractional day
423 * </p>
424 * @return the date and time as the string value
425 */
426 public String getDateAndTime() {
427 return dateAndTime;
428 }
429
430 /**
431 * Set the string value of date and time.
432 * @param dateAndTime the date and time to set
433 */
434 public void setDateAndTime(final String dateAndTime) {
435 this.dateAndTime = dateAndTime;
436 }
437
438 /**
439 * Get the prediction provider.
440 * @return the preditction provider
441 */
442 public String getPredictionProvider() {
443 return predictionProvider;
444 }
445
446 /**
447 * Set the prediction provider.
448 * @param predictionProvider the prediction provider to set
449 */
450 public void setPredictionProvider(final String predictionProvider) {
451 this.predictionProvider = predictionProvider;
452 }
453
454 /**
455 * Get a string representation of the H1 in the CRD format.
456 * @return a string representation of the H1, in the CRD format.
457 * @since 12.0
458 */
459 public String getH1CrdString() {
460 final DateComponents dc = getProductionEpoch();
461 return String.format("H1 %3s %2d %04d %02d %02d %02d", getFormat(),
462 getVersion(), dc.getYear(), dc.getMonth(), dc.getDay(),
463 getProductionHour());
464 }
465
466 /**
467 * Get a string representation of the H2 in the CRD format.
468 * @return a string representation of the H2, in the CRD format.
469 * @since 12.0
470 */
471 public String getH2CrdString() {
472 return String.format("H2 %s %4d %02d %02d %2d %s", stationName,
473 systemIdentifier, systemNumber, systemOccupancy,
474 epochIdentifier, stationNetword);
475 }
476
477 /**
478 * Get a string representation of the H3 in the CRD format.
479 * @return a string representation of the H3, in the CRD format.
480 * @since 12.0
481 */
482 public String getH3CrdString() {
483 final int targetLocation = getTargetLocation();
484 return String.format("H3 %s %7s %4s %5s %1d %1d %2s", getName(),
485 getIlrsSatelliteId(), getSic(), getNoradId(),
486 getSpacecraftEpochTimeScale(), getTargetClass(),
487 CRD.formatIntegerOrNaN(targetLocation, -1));
488 }
489
490 /**
491 * Get a string representation of the H4 in the CRD format.
492 * @return a string representation of the H4, in the CRD format.
493 * @since 12.0
494 */
495 @DefaultDataContext
496 public String getH4CrdString() {
497 // "2006-11-13T15:23:52" -- > "2006 11 13 15 23 52"
498 final TimeScale utc = TimeScalesFactory.getUTC();
499 final String startEpoch = getStartEpoch().toStringWithoutUtcOffset(utc, 0);
500 final String endEpoch = getEndEpoch().toStringWithoutUtcOffset(utc, 0);
501 return String.format("H4 %2d %s %s %d %d %d %d %d %d %d %d", getDataType(),
502 PATTERN_DATETIME_DELIMITER_REGEX.matcher(startEpoch).replaceAll(SPACE),
503 PATTERN_DATETIME_DELIMITER_REGEX.matcher(endEpoch).replaceAll(SPACE),
504 dataReleaseFlag, isTroposphericRefractionApplied ? 1 : 0,
505 isCenterOfMassCorrectionApplied ? 1 : 0,
506 isReceiveAmplitudeCorrectionApplied ? 1 : 0,
507 isStationSystemDelayApplied ? 1 : 0,
508 isTransponderDelayApplied ? 1 : 0, rangeType.getIndicator(),
509 qualityIndicator);
510 }
511
512 /**
513 * Get a string representation of the H5 in the CRD format.
514 * @return a string representation of the H5, in the CRD format.
515 * @since 12.0
516 */
517 public String getH5CrdString() {
518 return String.format("H5 %2d %02d %s %3s %5d", getPredictionType(), getYearOfCentury(),
519 getDateAndTime(), getPredictionProvider(), getSequenceNumber());
520 }
521
522 /** Range type for SLR data. */
523 public enum RangeType {
524
525 /** No ranges (i.e. transmit time only). */
526 NO_RANGES(0),
527
528 /** One-way ranging. */
529 ONE_WAY(1),
530
531 /** Two-way ranging. */
532 TWO_WAY(2),
533
534 /** Received times only. */
535 RECEIVED_ONLY(3),
536
537 /** Mixed. */
538 MIXED(4);
539
540 /** Codes map. */
541 private static final Map<Integer, RangeType> CODES_MAP = new HashMap<>();
542 static {
543 for (final RangeType type : values()) {
544 CODES_MAP.put(type.getIndicator(), type);
545 }
546 }
547
548 /** range type indicator. */
549 private final int indicator;
550
551 /**
552 * Constructor.
553 * @param indicator range type indicator
554 */
555 RangeType(final int indicator) {
556 this.indicator = indicator;
557 }
558
559 /**
560 * Get the range type indicator.
561 * @return the range type indicator
562 */
563 public int getIndicator() {
564 return indicator;
565 }
566
567 /**
568 * Get the range type for the given indicator.
569 * @param id indicator
570 * @return the range type corresponding to the indicator
571 */
572 public static RangeType getRangeType(final int id) {
573 final RangeType type = CODES_MAP.get(id);
574 if (type == null) {
575 // Invalid value. An exception is thrown
576 throw new OrekitException(OrekitMessages.INVALID_RANGE_INDICATOR_IN_CRD_FILE, id);
577 }
578 return type;
579 }
580
581 }
582
583 /** Data type for CRD data.
584 * @since 12.0
585 */
586 public enum DataType {
587
588 /** Full rate. */
589 FULL_RATE(0),
590
591 /** Normal point. */
592 NORMAL_POINT(1),
593
594 /** Sampled engineering. */
595 SAMPLED_ENGIEERING(2);
596
597 /** Codes map. */
598 private static final Map<Integer, DataType> CODES_MAP = new HashMap<>();
599 static {
600 for (final DataType type : values()) {
601 CODES_MAP.put(type.getIndicator(), type);
602 }
603 }
604
605 /** data type indicator. */
606 private final int indicator;
607
608 /**
609 * Constructor.
610 * @param indicator data type indicator
611 */
612 DataType(final int indicator) {
613 this.indicator = indicator;
614 }
615
616 /**
617 * Get the data type indicator.
618 * @return the data type indicator
619 */
620 public int getIndicator() {
621 return indicator;
622 }
623
624 /**
625 * Get the data type for the given indicator.
626 * @param id indicator
627 * @return the data type corresponding to the indicator
628 */
629 public static DataType getDataType(final int id) {
630 final DataType type = CODES_MAP.get(id);
631 if (type == null) {
632 // Invalid value. An exception is thrown
633 throw new RuntimeException(String.format("Invalid data type indicator {0} in CRD file header", id));
634 }
635 return type;
636 }
637
638 }
639
640 }