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