1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds;
18
19 import org.hipparchus.util.FastMath;
20 import org.orekit.errors.OrekitException;
21 import org.orekit.errors.OrekitInternalError;
22 import org.orekit.errors.OrekitMessages;
23 import org.orekit.files.general.OrbitFile;
24 import org.orekit.time.AbsoluteDate;
25 import org.orekit.time.DateTimeComponents;
26 import org.orekit.time.TimeScalesFactory;
27 import org.orekit.utils.Constants;
28 import org.orekit.utils.IERSConventions;
29
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.util.List;
35 import java.util.regex.Matcher;
36 import java.util.regex.Pattern;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public abstract class ODMParser {
54
55
56 private static final Pattern INTERNATIONAL_DESIGNATOR = Pattern.compile("(\\p{Digit}{4})-(\\p{Digit}{3})(\\p{Upper}{1,3})");
57
58
59 private final AbsoluteDate missionReferenceDate;
60
61
62 private final double mu;
63
64
65 private final IERSConventions conventions;
66
67
68 private final boolean simpleEOP;
69
70
71 private int launchYear;
72
73
74 private int launchNumber;
75
76
77 private String launchPiece;
78
79
80
81
82
83
84
85
86
87
88 protected ODMParser(final AbsoluteDate missionReferenceDate, final double mu,
89 final IERSConventions conventions, final boolean simpleEOP,
90 final int launchYear, final int launchNumber, final String launchPiece) {
91 this.missionReferenceDate = missionReferenceDate;
92 this.mu = mu;
93 this.conventions = conventions;
94 this.simpleEOP = simpleEOP;
95 this.launchYear = launchYear;
96 this.launchNumber = launchNumber;
97 this.launchPiece = launchPiece;
98 }
99
100
101
102
103
104
105 public abstract ODMParser withMissionReferenceDate(final AbsoluteDate newMissionReferenceDate);
106
107
108
109
110
111 public AbsoluteDate getMissionReferenceDate() {
112 return missionReferenceDate;
113 }
114
115
116
117
118
119
120 public abstract ODMParser withMu(final double newMu);
121
122
123
124
125
126 public double getMu() {
127 return mu;
128 }
129
130
131
132
133
134
135 public abstract ODMParser withConventions(final IERSConventions newConventions);
136
137
138
139
140
141 public IERSConventions getConventions() {
142 return conventions;
143 }
144
145
146
147
148
149
150 public abstract ODMParser withSimpleEOP(final boolean newSimpleEOP);
151
152
153
154
155
156 public boolean isSimpleEOP() {
157 return simpleEOP;
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 public abstract ODMParser withInternationalDesignator(final int newLaunchYear,
174 final int newLaunchNumber,
175 final String newLaunchPiece);
176
177
178
179
180 public int getLaunchYear() {
181 return launchYear;
182 }
183
184
185
186
187 public int getLaunchNumber() {
188 return launchNumber;
189 }
190
191
192
193
194 public String getLaunchPiece() {
195 return launchPiece;
196 }
197
198
199
200
201
202
203 public ODMFile parse(final String fileName)
204 throws OrekitException {
205
206 InputStream stream = null;
207
208 try {
209 stream = new FileInputStream(fileName);
210 return parse(stream, fileName);
211 } catch (FileNotFoundException e) {
212 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, fileName);
213 } finally {
214 try {
215 if (stream != null) {
216 stream.close();
217 }
218 } catch (IOException e) {
219
220 }
221 }
222
223 }
224
225
226
227
228
229
230 public ODMFile parse(final InputStream stream)
231 throws OrekitException {
232 return parse(stream, "<unknown>");
233 }
234
235
236
237
238
239
240
241 public abstract ODMFile parse(final InputStream stream, final String fileName)
242 throws OrekitException;
243
244
245
246
247
248
249 protected boolean parseComment(final KeyValue keyValue, final List<String> comment) {
250 if (keyValue.getKeyword() == Keyword.COMMENT) {
251 comment.add(keyValue.getValue());
252 return true;
253 } else {
254 return false;
255 }
256 }
257
258
259
260
261
262
263
264
265 protected boolean parseHeaderEntry(final KeyValue keyValue,
266 final ODMFile odmFile, final List<String> comment)
267 throws OrekitException {
268 switch (keyValue.getKeyword()) {
269
270 case CREATION_DATE:
271 if (!comment.isEmpty()) {
272 odmFile.setHeaderComment(comment);
273 comment.clear();
274 }
275 odmFile.setCreationDate(new AbsoluteDate(keyValue.getValue(), TimeScalesFactory.getUTC()));
276 return true;
277
278 case ORIGINATOR:
279 odmFile.setOriginator(keyValue.getValue());
280 return true;
281
282 default:
283 return false;
284
285 }
286
287 }
288
289
290
291
292
293
294
295
296 protected boolean parseMetaDataEntry(final KeyValue keyValue,
297 final ODMMetaData metaData, final List<String> comment)
298 throws OrekitException {
299 switch (keyValue.getKeyword()) {
300 case OBJECT_NAME:
301 if (!comment.isEmpty()) {
302 metaData.setComment(comment);
303 comment.clear();
304 }
305 metaData.setObjectName(keyValue.getValue());
306 return true;
307
308 case OBJECT_ID: {
309 metaData.setObjectID(keyValue.getValue());
310 final Matcher matcher = INTERNATIONAL_DESIGNATOR.matcher(keyValue.getValue());
311 if (matcher.matches()) {
312 metaData.setLaunchYear(Integer.parseInt(matcher.group(1)));
313 metaData.setLaunchNumber(Integer.parseInt(matcher.group(2)));
314 metaData.setLaunchPiece(matcher.group(3));
315 }
316 return true;
317 }
318
319 case CENTER_NAME:
320 metaData.setCenterName(keyValue.getValue());
321 final String canonicalValue;
322 if (keyValue.getValue().equals("SOLAR SYSTEM BARYCENTER") || keyValue.getValue().equals("SSB")) {
323 canonicalValue = "SOLAR_SYSTEM_BARYCENTER";
324 } else if (keyValue.getValue().equals("EARTH MOON BARYCENTER") || keyValue.getValue().equals("EARTH-MOON BARYCENTER") ||
325 keyValue.getValue().equals("EARTH BARYCENTER") || keyValue.getValue().equals("EMB")) {
326 canonicalValue = "EARTH_MOON";
327 } else {
328 canonicalValue = keyValue.getValue();
329 }
330 for (final CenterName c : CenterName.values()) {
331 if (c.name().equals(canonicalValue)) {
332 metaData.setHasCreatableBody(true);
333 metaData.setCenterBody(c.getCelestialBody());
334 metaData.getODMFile().setMuCreated(c.getCelestialBody().getGM());
335 }
336 }
337 return true;
338
339 case REF_FRAME:
340 metaData.setRefFrame(parseCCSDSFrame(keyValue.getValue()).getFrame(getConventions(), isSimpleEOP()));
341 return true;
342
343 case REF_FRAME_EPOCH:
344 metaData.setFrameEpochString(keyValue.getValue());
345 return true;
346
347 case TIME_SYSTEM:
348 final OrbitFile.TimeSystem timeSystem = OrbitFile.TimeSystem.valueOf(keyValue.getValue());
349 metaData.setTimeSystem(timeSystem);
350 if (metaData.getFrameEpochString() != null) {
351 metaData.setFrameEpoch(parseDate(metaData.getFrameEpochString(), timeSystem));
352 }
353 return true;
354
355 default:
356 return false;
357 }
358 }
359
360
361
362
363
364
365
366
367 protected boolean parseGeneralStateDataEntry(final KeyValue keyValue,
368 final OGMFile general, final List<String> comment)
369 throws OrekitException {
370 switch (keyValue.getKeyword()) {
371
372 case EPOCH:
373 general.setEpochComment(comment);
374 comment.clear();
375 general.setEpoch(parseDate(keyValue.getValue(), general.getTimeSystem()));
376 return true;
377
378 case SEMI_MAJOR_AXIS:
379 general.setKeplerianElementsComment(comment);
380 comment.clear();
381 general.setA(keyValue.getDoubleValue() * 1000);
382 general.setHasKeplerianElements(true);
383 return true;
384
385 case ECCENTRICITY:
386 general.setE(keyValue.getDoubleValue());
387 return true;
388
389 case INCLINATION:
390 general.setI(FastMath.toRadians(keyValue.getDoubleValue()));
391 return true;
392
393 case RA_OF_ASC_NODE:
394 general.setRaan(FastMath.toRadians(keyValue.getDoubleValue()));
395 return true;
396
397 case ARG_OF_PERICENTER:
398 general.setPa(FastMath.toRadians(keyValue.getDoubleValue()));
399 return true;
400
401 case TRUE_ANOMALY:
402 general.setAnomalyType("TRUE");
403 general.setAnomaly(FastMath.toRadians(keyValue.getDoubleValue()));
404 return true;
405
406 case MEAN_ANOMALY:
407 general.setAnomalyType("MEAN");
408 general.setAnomaly(FastMath.toRadians(keyValue.getDoubleValue()));
409 return true;
410
411 case GM:
412 general.setMuParsed(keyValue.getDoubleValue() * 1e9);
413 return true;
414
415 case MASS:
416 comment.addAll(0, general.getSpacecraftComment());
417 general.setSpacecraftComment(comment);
418 comment.clear();
419 general.setMass(keyValue.getDoubleValue());
420 return true;
421
422 case SOLAR_RAD_AREA:
423 comment.addAll(0, general.getSpacecraftComment());
424 general.setSpacecraftComment(comment);
425 comment.clear();
426 general.setSolarRadArea(keyValue.getDoubleValue());
427 return true;
428
429 case SOLAR_RAD_COEFF:
430 comment.addAll(0, general.getSpacecraftComment());
431 general.setSpacecraftComment(comment);
432 comment.clear();
433 general.setSolarRadCoeff(keyValue.getDoubleValue());
434 return true;
435
436 case DRAG_AREA:
437 comment.addAll(0, general.getSpacecraftComment());
438 general.setSpacecraftComment(comment);
439 comment.clear();
440 general.setDragArea(keyValue.getDoubleValue());
441 return true;
442
443 case DRAG_COEFF:
444 comment.addAll(0, general.getSpacecraftComment());
445 general.setSpacecraftComment(comment);
446 comment.clear();
447 general.setDragCoeff(keyValue.getDoubleValue());
448 return true;
449
450 case COV_REF_FRAME:
451 general.setCovarianceComment(comment);
452 comment.clear();
453 final CCSDSFrame covFrame = parseCCSDSFrame(keyValue.getValue());
454 if (covFrame.isLof()) {
455 general.setCovRefLofType(covFrame.getLofType());
456 } else {
457 general.setCovRefFrame(covFrame.getFrame(getConventions(), isSimpleEOP()));
458 }
459 return true;
460
461 case CX_X:
462 general.createCovarianceMatrix();
463 general.setCovarianceMatrixEntry(0, 0, keyValue.getDoubleValue() * 1.0e6);
464 return true;
465
466 case CY_X:
467 general.setCovarianceMatrixEntry(0, 1, keyValue.getDoubleValue() * 1.0e6);
468 return true;
469
470 case CY_Y:
471 general.setCovarianceMatrixEntry(1, 1, keyValue.getDoubleValue() * 1.0e6);
472 return true;
473
474 case CZ_X:
475 general.setCovarianceMatrixEntry(0, 2, keyValue.getDoubleValue() * 1.0e6);
476 return true;
477
478 case CZ_Y:
479 general.setCovarianceMatrixEntry(1, 2, keyValue.getDoubleValue() * 1.0e6);
480 return true;
481
482 case CZ_Z:
483 general.setCovarianceMatrixEntry(2, 2, keyValue.getDoubleValue() * 1.0e6);
484 return true;
485
486 case CX_DOT_X:
487 general.setCovarianceMatrixEntry(0, 3, keyValue.getDoubleValue() * 1.0e6);
488 return true;
489
490 case CX_DOT_Y:
491 general.setCovarianceMatrixEntry(1, 3, keyValue.getDoubleValue() * 1.0e6);
492 return true;
493
494 case CX_DOT_Z:
495 general.setCovarianceMatrixEntry(2, 3, keyValue.getDoubleValue() * 1.0e6);
496 return true;
497
498 case CX_DOT_X_DOT:
499 general.setCovarianceMatrixEntry(3, 3, keyValue.getDoubleValue() * 1.0e6);
500 return true;
501
502 case CY_DOT_X:
503 general.setCovarianceMatrixEntry(0, 4, keyValue.getDoubleValue() * 1.0e6);
504 return true;
505
506 case CY_DOT_Y:
507 general.setCovarianceMatrixEntry(1, 4, keyValue.getDoubleValue() * 1.0e6);
508 return true;
509
510 case CY_DOT_Z:
511 general.setCovarianceMatrixEntry(2, 4, keyValue.getDoubleValue() * 1.0e6);
512 return true;
513
514 case CY_DOT_X_DOT:
515 general.setCovarianceMatrixEntry(3, 4, keyValue.getDoubleValue() * 1.0e6);
516 return true;
517
518 case CY_DOT_Y_DOT:
519 general.setCovarianceMatrixEntry(4, 4, keyValue.getDoubleValue() * 1.0e6);
520 return true;
521
522 case CZ_DOT_X:
523 general.setCovarianceMatrixEntry(0, 5, keyValue.getDoubleValue() * 1.0e6);
524 return true;
525
526 case CZ_DOT_Y:
527 general.setCovarianceMatrixEntry(1, 5, keyValue.getDoubleValue() * 1.0e6);
528 return true;
529
530 case CZ_DOT_Z:
531 general.setCovarianceMatrixEntry(2, 5, keyValue.getDoubleValue() * 1.0e6);
532 return true;
533
534 case CZ_DOT_X_DOT:
535 general.setCovarianceMatrixEntry(3, 5, keyValue.getDoubleValue() * 1.0e6);
536 return true;
537
538 case CZ_DOT_Y_DOT:
539 general.setCovarianceMatrixEntry(4, 5, keyValue.getDoubleValue() * 1.0e6);
540 return true;
541
542 case CZ_DOT_Z_DOT:
543 general.setCovarianceMatrixEntry(5, 5, keyValue.getDoubleValue() * 1.0e6);
544 return true;
545
546 case USER_DEFINED_X:
547 general.setUserDefinedParameters(keyValue.getKey(), keyValue.getValue());
548 return true;
549
550 default:
551 return false;
552 }
553 }
554
555
556
557
558
559 protected CCSDSFrame parseCCSDSFrame(final String frameName) {
560 return CCSDSFrame.valueOf(frameName.replaceAll("-", ""));
561 }
562
563
564
565
566
567
568
569 protected AbsoluteDate parseDate(final String date, final OrbitFile.TimeSystem timeSystem)
570 throws OrekitException {
571 switch (timeSystem) {
572 case GMST:
573 return new AbsoluteDate(date, TimeScalesFactory.getGMST(conventions, false));
574 case GPS:
575 return new AbsoluteDate(date, TimeScalesFactory.getGPS());
576 case TAI:
577 return new AbsoluteDate(date, TimeScalesFactory.getTAI());
578 case TCB:
579 return new AbsoluteDate(date, TimeScalesFactory.getTCB());
580 case TDB:
581 return new AbsoluteDate(date, TimeScalesFactory.getTDB());
582 case TCG:
583 return new AbsoluteDate(date, TimeScalesFactory.getTCG());
584 case TT:
585 return new AbsoluteDate(date, TimeScalesFactory.getTT());
586 case UT1:
587 return new AbsoluteDate(date, TimeScalesFactory.getUT1(conventions, false));
588 case UTC:
589 return new AbsoluteDate(date, TimeScalesFactory.getUTC());
590 case MET: {
591 final DateTimeComponents clock = DateTimeComponents.parseDateTime(date);
592 final double offset = clock.getDate().getYear() * Constants.JULIAN_YEAR +
593 clock.getDate().getDayOfYear() * Constants.JULIAN_DAY +
594 clock.getTime().getSecondsInUTCDay();
595 return missionReferenceDate.shiftedBy(offset);
596 }
597 case MRT: {
598 final DateTimeComponents clock = DateTimeComponents.parseDateTime(date);
599 final double offset = clock.getDate().getYear() * Constants.JULIAN_YEAR +
600 clock.getDate().getDayOfYear() * Constants.JULIAN_DAY +
601 clock.getTime().getSecondsInUTCDay();
602 return missionReferenceDate.shiftedBy(offset);
603 }
604 default:
605 throw new OrekitInternalError(null);
606 }
607 }
608
609 }