1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.gnss.navigation;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.Reader;
22 import java.util.Arrays;
23 import java.util.HashMap;
24 import java.util.InputMismatchException;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Optional;
28 import java.util.regex.Pattern;
29 import java.util.stream.Stream;
30
31 import org.hipparchus.util.FastMath;
32 import org.orekit.annotation.DefaultDataContext;
33 import org.orekit.data.DataContext;
34 import org.orekit.data.DataSource;
35 import org.orekit.errors.OrekitException;
36 import org.orekit.errors.OrekitMessages;
37 import org.orekit.gnss.SatelliteSystem;
38 import org.orekit.gnss.TimeSystem;
39 import org.orekit.gnss.navigation.RinexNavigation.TimeSystemCorrection;
40 import org.orekit.propagation.analytical.gnss.data.BeidouNavigationMessage;
41 import org.orekit.propagation.analytical.gnss.data.GLONASSNavigationMessage;
42 import org.orekit.propagation.analytical.gnss.data.GPSNavigationMessage;
43 import org.orekit.propagation.analytical.gnss.data.GalileoNavigationMessage;
44 import org.orekit.propagation.analytical.gnss.data.IRNSSNavigationMessage;
45 import org.orekit.propagation.analytical.gnss.data.QZSSNavigationMessage;
46 import org.orekit.propagation.analytical.gnss.data.SBASNavigationMessage;
47 import org.orekit.time.AbsoluteDate;
48 import org.orekit.time.DateComponents;
49 import org.orekit.time.GNSSDate;
50 import org.orekit.time.TimeComponents;
51 import org.orekit.time.TimeScale;
52 import org.orekit.time.TimeScales;
53 import org.orekit.utils.Constants;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class RinexNavigationParser {
71
72
73 private static final List<Double> HANDLED_VERSIONS = Arrays.asList(3.01, 3.02, 3.03, 3.04, 3.05);
74
75
76 private static final String FILE_TYPE = "N";
77
78
79 private static final Double SEC_TO_MILLI = 1000.0;
80
81
82 private static final Double KM_TO_M = 1000.0;
83
84
85 private final TimeScales timeScales;
86
87
88
89
90
91
92
93 @DefaultDataContext
94 public RinexNavigationParser() {
95 this(DataContext.getDefault().getTimeScales());
96 }
97
98
99
100
101
102 public RinexNavigationParser(final TimeScales timeScales) {
103 this.timeScales = timeScales;
104 }
105
106
107
108
109
110
111
112 public RinexNavigation parse(final DataSource source) throws IOException {
113
114
115 final ParseInfo pi = new ParseInfo();
116
117 int lineNumber = 0;
118 Stream<LineParser> candidateParsers = Stream.of(LineParser.HEADER_VERSION);
119 try (Reader reader = source.getOpener().openReaderOnce();
120 BufferedReader br = new BufferedReader(reader)) {
121 for (String line = br.readLine(); line != null; line = br.readLine()) {
122 ++lineNumber;
123 final String l = line;
124 final Optional<LineParser> selected = candidateParsers.filter(p -> p.canHandle(l)).findFirst();
125 if (selected.isPresent()) {
126 try {
127 selected.get().parse(line, pi);
128 } catch (StringIndexOutOfBoundsException | NumberFormatException | InputMismatchException e) {
129 throw new OrekitException(e,
130 OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
131 lineNumber, source.getName(), line);
132 }
133 candidateParsers = selected.get().allowedNext();
134 } else {
135 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
136 lineNumber, source.getName(), line);
137 }
138 }
139 }
140
141 return pi.file;
142
143 }
144
145
146
147
148
149
150
151
152 private static double parseDouble(final String line, final int startIndex, final int size) {
153 return Double.parseDouble(line.substring(startIndex, startIndex + size).replace('D', 'E').trim());
154 }
155
156
157
158
159
160
161
162
163 private static int parseInt(final String line, final int startIndex, final int size) {
164 return Integer.parseInt(line.substring(startIndex, startIndex + size).trim());
165 }
166
167
168
169
170
171
172
173
174 private static String parseString(final String line, final int startIndex, final int size) {
175 return line.substring(startIndex, startIndex + size).trim();
176 }
177
178
179 private class ParseInfo {
180
181
182 private final TimeScales timeScales;
183
184
185 private RinexNavigation file;
186
187
188 private double version;
189
190
191 private boolean isIonosphereAlphaInitialized;
192
193
194 private SatelliteSystemLineParser systemLineParser;
195
196
197 private int lineNumber;
198
199
200 private GPSNavigationMessage gpsNav;
201
202
203 private GalileoNavigationMessage galileoNav;
204
205
206 private BeidouNavigationMessage beidouNav;
207
208
209 private QZSSNavigationMessage qzssNav;
210
211
212 private IRNSSNavigationMessage irnssNav;
213
214
215 private GLONASSNavigationMessage glonassNav;
216
217
218 private SBASNavigationMessage sbasNav;
219
220
221 ParseInfo() {
222
223 this.timeScales = RinexNavigationParser.this.timeScales;
224 this.version = 1.0;
225 this.isIonosphereAlphaInitialized = false;
226 this.file = new RinexNavigation();
227 this.systemLineParser = SatelliteSystemLineParser.GPS;
228 this.lineNumber = 0;
229 this.gpsNav = new GPSNavigationMessage();
230 this.galileoNav = new GalileoNavigationMessage();
231 this.beidouNav = new BeidouNavigationMessage();
232 this.qzssNav = new QZSSNavigationMessage();
233 this.irnssNav = new IRNSSNavigationMessage();
234 this.glonassNav = new GLONASSNavigationMessage();
235 this.sbasNav = new SBASNavigationMessage();
236 }
237
238 }
239
240
241 private enum LineParser {
242
243
244 HEADER_VERSION("^.+RINEX VERSION / TYPE( )*$") {
245
246
247 @Override
248 public void parse(final String line, final ParseInfo pi) {
249
250
251 pi.version = parseDouble(line, 0, 9);
252
253
254 if (!HANDLED_VERSIONS.contains(pi.version)) {
255 throw new OrekitException(OrekitMessages.NAVIGATION_FILE_UNSUPPORTED_VERSION, pi.version);
256 }
257 pi.file.setFormatVersion(pi.version);
258
259
260 pi.file.setFileType(FILE_TYPE);
261
262
263 final SatelliteSystem system = SatelliteSystem.parseSatelliteSystem(parseString(line, 40, 1));
264 pi.file.setSatelliteSystem(system);
265
266 }
267
268
269 @Override
270 public Stream<LineParser> allowedNext() {
271 return Stream.of(HEADER_PROGRAM);
272 }
273
274 },
275
276
277 HEADER_PROGRAM("^.+PGM / RUN BY / DATE( )*$") {
278
279
280 @Override
281 public void parse(final String line, final ParseInfo pi) {
282
283
284 final String programName = parseString(line, 0, 20);
285 pi.file.setProgramName(programName);
286
287
288 final String agencyName = parseString(line, 20, 20);
289 pi.file.setAgencyName(agencyName);
290
291
292 final String date = parseString(line, 40, 8);
293 final String time = parseString(line, 49, 6);
294 final String timeZone = parseString(line, 56, 4);
295 pi.file.setCreationDateString(date);
296 pi.file.setCreationTimeString(time);
297 pi.file.setCreationTimeZoneString(timeZone);
298
299
300 final DateComponents dateComponents = new DateComponents(parseInt(date, 0, 4),
301 parseInt(date, 4, 2),
302 parseInt(date, 6, 2));
303 final TimeComponents timeComponents = new TimeComponents(parseInt(time, 0, 2),
304 parseInt(time, 2, 2),
305 parseInt(time, 4, 2));
306 pi.file.setCreationDate(new AbsoluteDate(dateComponents,
307 timeComponents,
308 TimeSystem.parseTimeSystem(timeZone).getTimeScale(pi.timeScales)));
309
310 }
311
312
313 @Override
314 public Stream<LineParser> allowedNext() {
315 return Stream.of(HEADER_COMMENT, HEADER_IONOSPHERIC, HEADER_TIME, HEADER_LEAP_SECONDS, HEADER_END);
316 }
317
318 },
319
320
321 HEADER_COMMENT("^.+COMMENT( )*$") {
322
323
324 @Override
325 public void parse(final String line, final ParseInfo pi) {
326 pi.file.addComment(parseString(line, 0, 60));
327 }
328
329
330 @Override
331 public Stream<LineParser> allowedNext() {
332 return Stream.of(HEADER_COMMENT, HEADER_IONOSPHERIC, HEADER_TIME, HEADER_LEAP_SECONDS, HEADER_END);
333 }
334
335 },
336
337
338 HEADER_IONOSPHERIC("^.+IONOSPHERIC CORR( )*$") {
339
340
341 @Override
342 public void parse(final String line, final ParseInfo pi) {
343
344
345 final String ionoType = parseString(line, 0, 3);
346 pi.file.setIonosphericCorrectionType(ionoType);
347
348
349 final double[] parameters = new double[4];
350 parameters[0] = parseDouble(line, 5, 12);
351 parameters[1] = parseDouble(line, 17, 12);
352 parameters[2] = parseDouble(line, 29, 12);
353 parameters[3] = parseDouble(line, 41, 12);
354
355
356 if ("GAL".equals(ionoType)) {
357
358
359 pi.file.setNeQuickAlpha(parameters);
360
361 } else {
362
363
364
365 if (pi.isIonosphereAlphaInitialized) {
366
367
368 pi.file.setKlobucharBeta(parameters);
369
370 } else {
371
372
373 pi.file.setKlobucharAlpha(parameters);
374
375
376 pi.isIonosphereAlphaInitialized = true;
377
378 }
379
380 }
381
382 }
383
384
385 @Override
386 public Stream<LineParser> allowedNext() {
387 return Stream.of(HEADER_COMMENT, HEADER_IONOSPHERIC, HEADER_TIME, HEADER_LEAP_SECONDS, HEADER_END);
388 }
389
390 },
391
392
393 HEADER_TIME("^.+TIME SYSTEM CORR( )*$") {
394
395
396 @Override
397 public void parse(final String line, final ParseInfo pi) {
398
399
400 final String type = parseString(line, 0, 4);
401 final double a0 = parseDouble(line, 5, 17);
402 final double a1 = parseDouble(line, 22, 16);
403 final int refTime = parseInt(line, 38, 7);
404 final int refWeek = parseInt(line, 46, 5);
405
406
407 final TimeSystemCorrection tsc = new TimeSystemCorrection(type, a0, a1, refTime, refWeek);
408 pi.file.addTimeSystemCorrections(tsc);
409
410 }
411
412
413 @Override
414 public Stream<LineParser> allowedNext() {
415 return Stream.of(HEADER_COMMENT, HEADER_TIME, HEADER_LEAP_SECONDS, HEADER_END);
416 }
417
418 },
419
420
421 HEADER_LEAP_SECONDS("^.+LEAP SECONDS( )*$") {
422
423
424 @Override
425 public void parse(final String line, final ParseInfo pi) {
426
427 pi.file.setNumberOfLeapSeconds(parseInt(line, 0, 6));
428 }
429
430
431 @Override
432 public Stream<LineParser> allowedNext() {
433 return Stream.of(HEADER_COMMENT, HEADER_IONOSPHERIC, HEADER_TIME, HEADER_END);
434 }
435
436 },
437
438
439 HEADER_END("^.+END OF HEADER( )*$") {
440
441
442 @Override
443 public void parse(final String line, final ParseInfo pi) {
444
445 }
446
447
448 @Override
449 public Stream<LineParser> allowedNext() {
450 return Stream.of(NAVIGATION_MESSAGE_FIRST);
451 }
452
453 },
454
455
456 NAVIGATION_MESSAGE_FIRST("(^G|^R|^E|^C|^I|^J|^S).+$") {
457
458
459 @Override
460 public void parse(final String line, final ParseInfo pi) {
461
462
463 pi.lineNumber = 0;
464
465
466 final String key = parseString(line, 0, 1);
467
468
469 pi.systemLineParser = SatelliteSystemLineParser.getSatelliteSystemLineParser(key);
470
471
472 pi.systemLineParser.parseFirstLine(line, pi);
473
474 }
475
476
477 @Override
478 public Stream<LineParser> allowedNext() {
479 return Stream.of(NAVIGATION_BROADCAST_ORBIT);
480 }
481
482 },
483
484
485 NAVIGATION_BROADCAST_ORBIT("^ .+") {
486
487
488 @Override
489 public void parse(final String line, final ParseInfo pi) {
490
491
492 pi.lineNumber++;
493
494
495 if (pi.lineNumber == 1) {
496
497 pi.systemLineParser.parseFirstBroadcastOrbit(line, pi);
498 } else if (pi.lineNumber == 2) {
499
500 pi.systemLineParser.parseSecondBroadcastOrbit(line, pi);
501 } else if (pi.lineNumber == 3) {
502
503 pi.systemLineParser.parseThirdBroadcastOrbit(line, pi);
504 } else if (pi.lineNumber == 4) {
505
506 pi.systemLineParser.parseFourthBroadcastOrbit(line, pi);
507 } else if (pi.lineNumber == 5) {
508
509 pi.systemLineParser.parseFifthBroadcastOrbit(line, pi);
510 } else if (pi.lineNumber == 6) {
511
512 pi.systemLineParser.parseSixthBroadcastOrbit(line, pi);
513 } else {
514
515 pi.systemLineParser.parseSeventhBroadcastOrbit(line, pi);
516 }
517
518 }
519
520
521 @Override
522 public Stream<LineParser> allowedNext() {
523 return Stream.of(NAVIGATION_MESSAGE_FIRST, NAVIGATION_BROADCAST_ORBIT);
524 }
525
526 };
527
528
529 private final Pattern pattern;
530
531
532
533
534 LineParser(final String lineRegexp) {
535 pattern = Pattern.compile(lineRegexp);
536 }
537
538
539
540
541
542 public abstract void parse(String line, ParseInfo pi);
543
544
545
546
547 public abstract Stream<LineParser> allowedNext();
548
549
550
551
552
553 public boolean canHandle(final String line) {
554 return pattern.matcher(line).matches();
555 }
556
557 }
558
559
560 private enum SatelliteSystemLineParser {
561
562
563 GPS("G") {
564
565
566 @Override
567 public void parseFirstLine(final String line, final ParseInfo pi) {
568
569 pi.gpsNav.setPRN(parseInt(line, 1, 2));
570
571
572 final int gpsTocYear = parseInt(line, 4, 4);
573 final int gpsTocMonth = parseInt(line, 9, 2);
574 final int gpsTocDay = parseInt(line, 12, 2);
575 final int gpsTocHours = parseInt(line, 15, 2);
576 final int gpsTocMin = parseInt(line, 18, 2);
577 final int gpsTocSec = parseInt(line, 21, 2);
578 pi.gpsNav.setEpochToc(new AbsoluteDate(gpsTocYear, gpsTocMonth, gpsTocDay, gpsTocHours,
579 gpsTocMin, gpsTocSec, pi.timeScales.getGPS()));
580
581
582 pi.gpsNav.setAf0(parseDouble(line, 23, 19));
583 pi.gpsNav.setAf1(parseDouble(line, 42, 19));
584 pi.gpsNav.setAf2(parseDouble(line, 61, 19));
585 }
586
587
588 @Override
589 public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
590
591 pi.gpsNav.setIODE(parseDouble(line, 4, 19));
592
593 pi.gpsNav.setCrs(parseDouble(line, 23, 19));
594
595 pi.gpsNav.setDeltaN(parseDouble(line, 42, 19));
596
597 pi.gpsNav.setM0(parseDouble(line, 61, 19));
598 }
599
600
601 @Override
602 public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
603
604 pi.gpsNav.setCuc(parseDouble(line, 4, 19));
605
606 pi.gpsNav.setE(parseDouble(line, 23, 19));
607
608 pi.gpsNav.setCus(parseDouble(line, 42, 19));
609
610 pi.gpsNav.setSqrtA(parseDouble(line, 61, 19));
611 }
612
613
614 @Override
615 public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
616
617 pi.gpsNav.setTime(parseDouble(line, 4, 19));
618
619 pi.gpsNav.setCic(parseDouble(line, 23, 19));
620
621 pi.gpsNav.setOmega0(parseDouble(line, 42, 19));
622
623 pi.gpsNav.setCis(parseDouble(line, 61, 19));
624 }
625
626
627 @Override
628 public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
629
630 pi.gpsNav.setI0(parseDouble(line, 4, 19));
631
632 pi.gpsNav.setCrc(parseDouble(line, 23, 19));
633
634 pi.gpsNav.setPa(parseDouble(line, 42, 19));
635
636 pi.gpsNav.setOmegaDot(parseDouble(line, 61, 19));
637 }
638
639
640 @Override
641 public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
642
643 pi.gpsNav.setIDot(parseDouble(line, 4, 19));
644
645
646
647 pi.gpsNav.setWeek((int) parseDouble(line, 42, 19));
648 pi.gpsNav.setDate(new GNSSDate(pi.gpsNav.getWeek(),
649 SEC_TO_MILLI * pi.gpsNav.getTime(),
650 SatelliteSystem.GPS,
651 pi.timeScales).getDate());
652 }
653
654
655 @Override
656 public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
657
658 pi.gpsNav.setSvAccuracy(parseDouble(line, 4, 19));
659
660 pi.gpsNav.setSvHealth(parseDouble(line, 23, 19));
661
662 pi.gpsNav.setTGD(parseDouble(line, 42, 19));
663
664 pi.gpsNav.setIODC(parseDouble(line, 61, 19));
665 }
666
667
668 @Override
669 public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
670
671 pi.file.addGPSNavigationMessage(pi.gpsNav);
672
673 pi.gpsNav = new GPSNavigationMessage();
674 }
675
676 },
677
678
679 GALILEO("E") {
680
681
682 @Override
683 public void parseFirstLine(final String line, final ParseInfo pi) {
684
685 pi.galileoNav.setPRN(parseInt(line, 1, 2));
686
687
688 final int galileoTocYear = parseInt(line, 4, 4);
689 final int galileoTocMonth = parseInt(line, 9, 2);
690 final int galileoTocDay = parseInt(line, 12, 2);
691 final int galileoTocHours = parseInt(line, 15, 2);
692 final int galileoTocMin = parseInt(line, 18, 2);
693 final int galileoTocSec = parseInt(line, 21, 2);
694 pi.galileoNav.setEpochToc(new AbsoluteDate(galileoTocYear, galileoTocMonth, galileoTocDay, galileoTocHours,
695 galileoTocMin, galileoTocSec, pi.timeScales.getGST()));
696
697
698 pi.galileoNav.setAf0(parseDouble(line, 23, 19));
699 pi.galileoNav.setAf1(parseDouble(line, 42, 19));
700 pi.galileoNav.setAf2(parseDouble(line, 61, 19));
701 }
702
703
704 @Override
705 public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
706
707 pi.galileoNav.setIODNav(parseDouble(line, 4, 19));
708
709 pi.galileoNav.setCrs(parseDouble(line, 23, 19));
710
711 pi.galileoNav.setDeltaN(parseDouble(line, 42, 19));
712
713 pi.galileoNav.setM0(parseDouble(line, 61, 19));
714 }
715
716
717 @Override
718 public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
719
720 pi.galileoNav.setCuc(parseDouble(line, 4, 19));
721
722 pi.galileoNav.setE(parseDouble(line, 23, 19));
723
724 pi.galileoNav.setCus(parseDouble(line, 42, 19));
725
726 pi.galileoNav.setSqrtA(parseDouble(line, 61, 19));
727 }
728
729
730 @Override
731 public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
732
733 pi.galileoNav.setTime(parseDouble(line, 4, 19));
734
735 pi.galileoNav.setCic(parseDouble(line, 23, 19));
736
737 pi.galileoNav.setOmega0(parseDouble(line, 42, 19));
738
739 pi.galileoNav.setCis(parseDouble(line, 61, 19));
740 }
741
742
743 @Override
744 public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
745
746 pi.galileoNav.setI0(parseDouble(line, 4, 19));
747
748 pi.galileoNav.setCrc(parseDouble(line, 23, 19));
749
750 pi.galileoNav.setPa(parseDouble(line, 42, 19));
751
752 pi.galileoNav.setOmegaDot(parseDouble(line, 61, 19));
753 }
754
755
756 @Override
757 public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
758
759 pi.galileoNav.setIDot(parseDouble(line, 4, 19));
760
761
762
763 pi.galileoNav.setWeek((int) parseDouble(line, 42, 19));
764 pi.galileoNav.setDate(new GNSSDate(pi.galileoNav.getWeek(),
765 SEC_TO_MILLI * pi.galileoNav.getTime(),
766 SatelliteSystem.GALILEO,
767 pi.timeScales).getDate());
768 }
769
770
771 @Override
772 public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
773
774 pi.galileoNav.setSisa(parseDouble(line, 4, 19));
775
776 pi.galileoNav.setSvHealth(parseDouble(line, 23, 19));
777
778 pi.galileoNav.setBGDE1E5a(parseDouble(line, 42, 19));
779
780 pi.galileoNav.setBGDE5bE1(parseDouble(line, 61, 19));
781 }
782
783
784 @Override
785 public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
786
787 pi.file.addGalileoNavigationMessage(pi.galileoNav);
788
789 pi.galileoNav = new GalileoNavigationMessage();
790 }
791
792 },
793
794
795 BEIDOU("C") {
796
797
798 @Override
799 public void parseFirstLine(final String line, final ParseInfo pi) {
800
801 pi.beidouNav.setPRN(parseInt(line, 1, 2));
802
803
804 final int beidouTocYear = parseInt(line, 4, 4);
805 final int beidouTocMonth = parseInt(line, 9, 2);
806 final int beidouTocDay = parseInt(line, 12, 2);
807 final int beidouTocHours = parseInt(line, 15, 2);
808 final int beidouTocMin = parseInt(line, 18, 2);
809 final int beidouTocSec = parseInt(line, 21, 2);
810 pi.beidouNav.setEpochToc(new AbsoluteDate(beidouTocYear, beidouTocMonth, beidouTocDay, beidouTocHours,
811 beidouTocMin, beidouTocSec, pi.timeScales.getBDT()));
812
813
814 pi.beidouNav.setAf0(parseDouble(line, 23, 19));
815 pi.beidouNav.setAf1(parseDouble(line, 42, 19));
816 pi.beidouNav.setAf2(parseDouble(line, 61, 19));
817 }
818
819
820 @Override
821 public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
822
823 pi.beidouNav.setAODE(parseDouble(line, 4, 19));
824
825 pi.beidouNav.setCrs(parseDouble(line, 23, 19));
826
827 pi.beidouNav.setDeltaN(parseDouble(line, 42, 19));
828
829 pi.beidouNav.setM0(parseDouble(line, 61, 19));
830 }
831
832
833 @Override
834 public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
835
836 pi.beidouNav.setCuc(parseDouble(line, 4, 19));
837
838 pi.beidouNav.setE(parseDouble(line, 23, 19));
839
840 pi.beidouNav.setCus(parseDouble(line, 42, 19));
841
842 pi.beidouNav.setSqrtA(parseDouble(line, 61, 19));
843 }
844
845
846 @Override
847 public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
848
849 pi.beidouNav.setTime(parseDouble(line, 4, 19));
850
851 pi.beidouNav.setCic(parseDouble(line, 23, 19));
852
853 pi.beidouNav.setOmega0(parseDouble(line, 42, 19));
854
855 pi.beidouNav.setCis(parseDouble(line, 61, 19));
856 }
857
858
859 @Override
860 public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
861
862 pi.beidouNav.setI0(parseDouble(line, 4, 19));
863
864 pi.beidouNav.setCrc(parseDouble(line, 23, 19));
865
866 pi.beidouNav.setPa(parseDouble(line, 42, 19));
867
868 pi.beidouNav.setOmegaDot(parseDouble(line, 61, 19));
869 }
870
871
872 @Override
873 public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
874
875 pi.beidouNav.setIDot(parseDouble(line, 4, 19));
876
877 pi.beidouNav.setWeek((int) parseDouble(line, 42, 19));
878 pi.beidouNav.setDate(new GNSSDate(pi.beidouNav.getWeek(),
879 SEC_TO_MILLI * pi.beidouNav.getTime(),
880 SatelliteSystem.BEIDOU,
881 pi.timeScales).getDate());
882 }
883
884
885 @Override
886 public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
887
888 pi.beidouNav.setSvAccuracy(parseDouble(line, 4, 19));
889
890
891
892 pi.beidouNav.setTGD1(parseDouble(line, 42, 19));
893
894 pi.beidouNav.setTGD2(parseDouble(line, 61, 19));
895 }
896
897
898 @Override
899 public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
900
901
902
903 pi.beidouNav.setAODC(parseDouble(line, 23, 19));
904
905 pi.file.addBeidouNavigationMessage(pi.beidouNav);
906
907 pi.beidouNav = new BeidouNavigationMessage();
908
909 }
910
911 },
912
913
914 QZSS("J") {
915
916
917 @Override
918 public void parseFirstLine(final String line, final ParseInfo pi) {
919
920 pi.qzssNav.setPRN(parseInt(line, 1, 2));
921
922
923 final int qzssTocYear = parseInt(line, 4, 4);
924 final int qzssTocMonth = parseInt(line, 9, 2);
925 final int qzssTocDay = parseInt(line, 12, 2);
926 final int qzssTocHours = parseInt(line, 15, 2);
927 final int qzssTocMin = parseInt(line, 18, 2);
928 final int qzssTocSec = parseInt(line, 21, 2);
929 pi.qzssNav.setEpochToc(new AbsoluteDate(qzssTocYear, qzssTocMonth, qzssTocDay, qzssTocHours,
930 qzssTocMin, qzssTocSec, pi.timeScales.getQZSS()));
931
932
933 pi.qzssNav.setAf0(parseDouble(line, 23, 19));
934 pi.qzssNav.setAf1(parseDouble(line, 42, 19));
935 pi.qzssNav.setAf2(parseDouble(line, 61, 19));
936 }
937
938
939 @Override
940 public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
941
942 pi.qzssNav.setIODE(parseDouble(line, 4, 19));
943
944 pi.qzssNav.setCrs(parseDouble(line, 23, 19));
945
946 pi.qzssNav.setDeltaN(parseDouble(line, 42, 19));
947
948 pi.qzssNav.setM0(parseDouble(line, 61, 19));
949 }
950
951
952 @Override
953 public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
954
955 pi.qzssNav.setCuc(parseDouble(line, 4, 19));
956
957 pi.qzssNav.setE(parseDouble(line, 23, 19));
958
959 pi.qzssNav.setCus(parseDouble(line, 42, 19));
960
961 pi.qzssNav.setSqrtA(parseDouble(line, 61, 19));
962 }
963
964
965 @Override
966 public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
967
968 pi.qzssNav.setTime(parseDouble(line, 4, 19));
969
970 pi.qzssNav.setCic(parseDouble(line, 23, 19));
971
972 pi.qzssNav.setOmega0(parseDouble(line, 42, 19));
973
974 pi.qzssNav.setCis(parseDouble(line, 61, 19));
975 }
976
977
978 @Override
979 public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
980
981 pi.qzssNav.setI0(parseDouble(line, 4, 19));
982
983 pi.qzssNav.setCrc(parseDouble(line, 23, 19));
984
985 pi.qzssNav.setPa(parseDouble(line, 42, 19));
986
987 pi.qzssNav.setOmegaDot(parseDouble(line, 61, 19));
988 }
989
990
991 @Override
992 public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
993
994 pi.qzssNav.setIDot(parseDouble(line, 4, 19));
995
996
997
998 pi.qzssNav.setWeek((int) parseDouble(line, 42, 19));
999 pi.qzssNav.setDate(new GNSSDate(pi.qzssNav.getWeek(),
1000 SEC_TO_MILLI * pi.qzssNav.getTime(),
1001 SatelliteSystem.QZSS,
1002 pi.timeScales).getDate());
1003 }
1004
1005
1006 @Override
1007 public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
1008
1009 pi.qzssNav.setSvAccuracy(parseDouble(line, 4, 19));
1010
1011 pi.qzssNav.setSvHealth(parseDouble(line, 23, 19));
1012
1013 pi.qzssNav.setTGD(parseDouble(line, 42, 19));
1014
1015 pi.qzssNav.setIODC(parseDouble(line, 61, 19));
1016 }
1017
1018
1019 @Override
1020 public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
1021
1022 pi.file.addQZSSNavigationMessage(pi.qzssNav);
1023
1024 pi.qzssNav = new QZSSNavigationMessage();
1025 }
1026
1027 },
1028
1029
1030 IRNSS("I") {
1031
1032
1033 @Override
1034 public void parseFirstLine(final String line, final ParseInfo pi) {
1035
1036 pi.irnssNav.setPRN(parseInt(line, 1, 2));
1037
1038
1039 final int irnssTocYear = parseInt(line, 4, 4);
1040 final int irnssTocMonth = parseInt(line, 9, 2);
1041 final int irnssTocDay = parseInt(line, 12, 2);
1042 final int irnssTocHours = parseInt(line, 15, 2);
1043 final int irnssTocMin = parseInt(line, 18, 2);
1044 final int irnssTocSec = parseInt(line, 21, 2);
1045 pi.irnssNav.setEpochToc(new AbsoluteDate(irnssTocYear, irnssTocMonth, irnssTocDay, irnssTocHours,
1046 irnssTocMin, irnssTocSec, pi.timeScales.getIRNSS()));
1047
1048
1049 pi.irnssNav.setAf0(parseDouble(line, 23, 19));
1050 pi.irnssNav.setAf1(parseDouble(line, 42, 19));
1051 pi.irnssNav.setAf2(parseDouble(line, 61, 19));
1052 }
1053
1054
1055 @Override
1056 public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
1057
1058 pi.irnssNav.setIODEC(parseDouble(line, 4, 19));
1059
1060 pi.irnssNav.setCrs(parseDouble(line, 23, 19));
1061
1062 pi.irnssNav.setDeltaN(parseDouble(line, 42, 19));
1063
1064 pi.irnssNav.setM0(parseDouble(line, 61, 19));
1065 }
1066
1067
1068 @Override
1069 public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
1070
1071 pi.irnssNav.setCuc(parseDouble(line, 4, 19));
1072
1073 pi.irnssNav.setE(parseDouble(line, 23, 19));
1074
1075 pi.irnssNav.setCus(parseDouble(line, 42, 19));
1076
1077 pi.irnssNav.setSqrtA(parseDouble(line, 61, 19));
1078 }
1079
1080
1081 @Override
1082 public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
1083
1084 pi.irnssNav.setTime(parseDouble(line, 4, 19));
1085
1086 pi.irnssNav.setCic(parseDouble(line, 23, 19));
1087
1088 pi.irnssNav.setOmega0(parseDouble(line, 42, 19));
1089
1090 pi.irnssNav.setCis(parseDouble(line, 61, 19));
1091 }
1092
1093
1094 @Override
1095 public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
1096
1097 pi.irnssNav.setI0(parseDouble(line, 4, 19));
1098
1099 pi.irnssNav.setCrc(parseDouble(line, 23, 19));
1100
1101 pi.irnssNav.setPa(parseDouble(line, 42, 19));
1102
1103 pi.irnssNav.setOmegaDot(parseDouble(line, 61, 19));
1104 }
1105
1106
1107 @Override
1108 public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
1109
1110 pi.irnssNav.setIDot(parseDouble(line, 4, 19));
1111
1112 pi.irnssNav.setWeek((int) parseDouble(line, 42, 19));
1113 pi.irnssNav.setDate(new GNSSDate(pi.irnssNav.getWeek(),
1114 SEC_TO_MILLI * pi.irnssNav.getTime(),
1115 SatelliteSystem.IRNSS,
1116 pi.timeScales).getDate());
1117 }
1118
1119
1120 @Override
1121 public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
1122
1123 pi.irnssNav.setURA(parseDouble(line, 4, 19));
1124
1125 pi.irnssNav.setSvHealth(parseDouble(line, 23, 19));
1126
1127 pi.irnssNav.setTGD(parseDouble(line, 42, 19));
1128 }
1129
1130
1131 @Override
1132 public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
1133
1134 pi.file.addIRNSSNavigationMessage(pi.irnssNav);
1135
1136 pi.irnssNav = new IRNSSNavigationMessage();
1137
1138 }
1139
1140 },
1141
1142
1143 GLONASS("R") {
1144
1145
1146 @Override
1147 public void parseFirstLine(final String line, final ParseInfo pi) {
1148
1149 pi.glonassNav.setPRN(parseInt(line, 1, 2));
1150
1151
1152 final int glonassTocYear = parseInt(line, 4, 4);
1153 final int glonassTocMonth = parseInt(line, 9, 2);
1154 final int glonassTocDay = parseInt(line, 12, 2);
1155 final int glonassTocHours = parseInt(line, 15, 2);
1156 final int glonassTocMin = parseInt(line, 18, 2);
1157 final int glonassTocSec = parseInt(line, 21, 2);
1158 final AbsoluteDate date = new AbsoluteDate(glonassTocYear, glonassTocMonth, glonassTocDay, glonassTocHours,
1159 glonassTocMin, glonassTocSec, pi.timeScales.getUTC());
1160
1161
1162 final GNSSDate gpsEpoch = new GNSSDate(date, SatelliteSystem.GPS, pi.timeScales);
1163
1164
1165 final double secInWeek = FastMath.floor((0.001 * gpsEpoch.getMilliInWeek() + 450.0) / 900.0) * 900.0;
1166 final AbsoluteDate rounded = new GNSSDate(gpsEpoch.getWeekNumber(),
1167 SEC_TO_MILLI * secInWeek,
1168 SatelliteSystem.GPS, pi.timeScales).getDate();
1169
1170 pi.glonassNav.setEpochToc(rounded);
1171
1172
1173 pi.glonassNav.setTauN(-parseDouble(line, 23, 19));
1174 pi.glonassNav.setGammaN(parseDouble(line, 42, 19));
1175
1176
1177 pi.glonassNav.setDate(rounded);
1178
1179
1180 pi.glonassNav.setTime(fmod(parseDouble(line, 61, 19), Constants.JULIAN_DAY));
1181
1182 }
1183
1184
1185 @Override
1186 public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
1187
1188 pi.glonassNav.setX(parseDouble(line, 4, 19) * KM_TO_M);
1189
1190 pi.glonassNav.setXDot(parseDouble(line, 23, 19) * KM_TO_M);
1191
1192 pi.glonassNav.setXDotDot(parseDouble(line, 42, 19) * KM_TO_M);
1193
1194 pi.glonassNav.setHealth(parseDouble(line, 61, 19));
1195 }
1196
1197
1198 @Override
1199 public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
1200
1201 pi.glonassNav.setY(parseDouble(line, 4, 19) * KM_TO_M);
1202
1203 pi.glonassNav.setYDot(parseDouble(line, 23, 19) * KM_TO_M);
1204
1205 pi.glonassNav.setYDotDot(parseDouble(line, 42, 19) * KM_TO_M);
1206
1207 pi.glonassNav.setFrequencyNumber(parseDouble(line, 61, 19));
1208 }
1209
1210
1211 @Override
1212 public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
1213
1214 pi.glonassNav.setZ(parseDouble(line, 4, 19) * KM_TO_M);
1215
1216 pi.glonassNav.setZDot(parseDouble(line, 23, 19) * KM_TO_M);
1217
1218 pi.glonassNav.setZDotDot(parseDouble(line, 42, 19) * KM_TO_M);
1219
1220
1221 pi.file.addGlonassNavigationMessage(pi.glonassNav);
1222
1223 pi.glonassNav = new GLONASSNavigationMessage();
1224 }
1225
1226
1227 @Override
1228 public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
1229
1230 }
1231
1232
1233 @Override
1234 public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
1235
1236 }
1237
1238
1239 @Override
1240 public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
1241
1242 }
1243
1244
1245 @Override
1246 public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
1247
1248 }
1249
1250 },
1251
1252
1253 SBAS("S") {
1254
1255
1256 @Override
1257 public void parseFirstLine(final String line, final ParseInfo pi) {
1258
1259 pi.sbasNav.setPRN(parseInt(line, 1, 2));
1260
1261
1262 final int sbasTocYear = parseInt(line, 4, 4);
1263 final int sbasTocMonth = parseInt(line, 9, 2);
1264 final int sbasTocDay = parseInt(line, 12, 2);
1265 final int sbasTocHours = parseInt(line, 15, 2);
1266 final int sbasTocMin = parseInt(line, 18, 2);
1267 final int sbasTocSec = parseInt(line, 21, 2);
1268
1269 final TimeScale timeScale = ((int) pi.version * 100 == 301) ? pi.timeScales.getUTC() : pi.timeScales.getGPS();
1270 final AbsoluteDate refEpoch = new AbsoluteDate(sbasTocYear, sbasTocMonth, sbasTocDay, sbasTocHours,
1271 sbasTocMin, sbasTocSec, timeScale);
1272 pi.sbasNav.setEpochToc(refEpoch);
1273
1274
1275 pi.sbasNav.setAGf0(parseDouble(line, 23, 19));
1276 pi.sbasNav.setAGf1(parseDouble(line, 42, 19));
1277 pi.sbasNav.setTime(parseDouble(line, 61, 19));
1278
1279
1280 pi.sbasNav.setDate(refEpoch);
1281 }
1282
1283
1284 @Override
1285 public void parseFirstBroadcastOrbit(final String line, final ParseInfo pi) {
1286
1287 pi.sbasNav.setX(parseDouble(line, 4, 19) * KM_TO_M);
1288
1289 pi.sbasNav.setXDot(parseDouble(line, 23, 19) * KM_TO_M);
1290
1291 pi.sbasNav.setXDotDot(parseDouble(line, 42, 19) * KM_TO_M);
1292
1293 pi.sbasNav.setHealth(parseDouble(line, 61, 19));
1294 }
1295
1296
1297 @Override
1298 public void parseSecondBroadcastOrbit(final String line, final ParseInfo pi) {
1299
1300 pi.sbasNav.setY(parseDouble(line, 4, 19) * KM_TO_M);
1301
1302 pi.sbasNav.setYDot(parseDouble(line, 23, 19) * KM_TO_M);
1303
1304 pi.sbasNav.setYDotDot(parseDouble(line, 42, 19) * KM_TO_M);
1305
1306 pi.sbasNav.setURA(parseDouble(line, 61, 19));
1307 }
1308
1309
1310 @Override
1311 public void parseThirdBroadcastOrbit(final String line, final ParseInfo pi) {
1312
1313 pi.sbasNav.setZ(parseDouble(line, 4, 19) * KM_TO_M);
1314
1315 pi.sbasNav.setZDot(parseDouble(line, 23, 19) * KM_TO_M);
1316
1317 pi.sbasNav.setZDotDot(parseDouble(line, 42, 19) * KM_TO_M);
1318
1319 pi.sbasNav.setIODN(parseDouble(line, 61, 19));
1320
1321
1322 pi.file.addSBASNavigationMessage(pi.sbasNav);
1323
1324
1325 pi.sbasNav = new SBASNavigationMessage();
1326
1327 }
1328
1329
1330 @Override
1331 public void parseFourthBroadcastOrbit(final String line, final ParseInfo pi) {
1332
1333 }
1334
1335
1336 @Override
1337 public void parseFifthBroadcastOrbit(final String line, final ParseInfo pi) {
1338
1339 }
1340
1341
1342 @Override
1343 public void parseSixthBroadcastOrbit(final String line, final ParseInfo pi) {
1344
1345 }
1346
1347
1348 @Override
1349 public void parseSeventhBroadcastOrbit(final String line, final ParseInfo pi) {
1350
1351 }
1352
1353 };
1354
1355
1356 private static final Map<String, SatelliteSystemLineParser> KEYS_MAP = new HashMap<>();
1357 static {
1358 for (final SatelliteSystemLineParser satelliteSystem : values()) {
1359 KEYS_MAP.put(satelliteSystem.getKey(), satelliteSystem);
1360 }
1361 }
1362
1363
1364 private String key;
1365
1366
1367
1368
1369
1370 SatelliteSystemLineParser(final String key) {
1371 this.key = key;
1372 }
1373
1374
1375
1376
1377
1378 public String getKey() {
1379 return key;
1380 }
1381
1382
1383
1384
1385
1386
1387
1388
1389 public static SatelliteSystemLineParser getSatelliteSystemLineParser(final String s) {
1390 return KEYS_MAP.get(s);
1391 }
1392
1393
1394
1395
1396
1397
1398 public abstract void parseFirstLine(String line, ParseInfo pi);
1399
1400
1401
1402
1403
1404
1405 public abstract void parseFirstBroadcastOrbit(String line, ParseInfo pi);
1406
1407
1408
1409
1410
1411
1412 public abstract void parseSecondBroadcastOrbit(String line, ParseInfo pi);
1413
1414
1415
1416
1417
1418
1419 public abstract void parseThirdBroadcastOrbit(String line, ParseInfo pi);
1420
1421
1422
1423
1424
1425
1426 public abstract void parseFourthBroadcastOrbit(String line, ParseInfo pi);
1427
1428
1429
1430
1431
1432
1433 public abstract void parseFifthBroadcastOrbit(String line, ParseInfo pi);
1434
1435
1436
1437
1438
1439
1440 public abstract void parseSixthBroadcastOrbit(String line, ParseInfo pi);
1441
1442
1443
1444
1445
1446
1447 public abstract void parseSeventhBroadcastOrbit(String line, ParseInfo pi);
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459 private static double fmod(final double a, final double b) {
1460 final double x = (int) (a / b);
1461 return a - x * b;
1462 }
1463
1464 }
1465
1466 }