1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.sp3;
18
19 import java.io.BufferedReader;
20 import java.io.FileInputStream;
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.InputStreamReader;
25 import java.util.Locale;
26 import java.util.Scanner;
27
28 import org.apache.commons.math3.exception.util.DummyLocalizable;
29 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
30 import org.orekit.errors.OrekitException;
31 import org.orekit.errors.OrekitMessages;
32 import org.orekit.files.general.OrbitFileParser;
33 import org.orekit.files.general.SatelliteInformation;
34 import org.orekit.files.general.SatelliteTimeCoordinate;
35 import org.orekit.files.general.OrbitFile.TimeSystem;
36 import org.orekit.files.sp3.SP3File.SP3FileType;
37 import org.orekit.files.sp3.SP3File.SP3OrbitType;
38 import org.orekit.time.AbsoluteDate;
39 import org.orekit.time.TimeScale;
40 import org.orekit.time.TimeScalesFactory;
41 import org.orekit.utils.PVCoordinates;
42
43
44
45
46
47
48
49
50
51
52
53 public class SP3Parser implements OrbitFileParser {
54
55
56 public SP3File parse(final String fileName) throws OrekitException {
57
58 InputStream stream = null;
59
60 try {
61 stream = new FileInputStream(fileName);
62 return parse(stream);
63 } catch (FileNotFoundException e) {
64 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, fileName);
65 } finally {
66 try {
67 if (stream != null) {
68 stream.close();
69 }
70 } catch (IOException e) {
71
72 }
73 }
74 }
75
76
77 public SP3File parse(final InputStream stream) throws OrekitException {
78 try {
79 return parseInternal(stream);
80 } catch (IOException e) {
81 throw new OrekitException(e, new DummyLocalizable(e.getMessage()));
82 }
83 }
84
85
86
87
88
89
90
91
92 private SP3File parseInternal(final InputStream stream)
93 throws OrekitException, IOException {
94
95 final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
96
97
98 final ParseInfo pi = new ParseInfo();
99
100 String line = null;
101 int lineNumber = 1;
102 try {
103 while (lineNumber < 23) {
104 line = reader.readLine();
105 if (line == null) {
106 throw new OrekitException(OrekitMessages.SP3_UNEXPECTED_END_OF_FILE, lineNumber - 1);
107 } else {
108 parseHeaderLine(lineNumber++, line, pi);
109 }
110 }
111
112
113
114 boolean done = false;
115 do {
116 line = reader.readLine();
117 if (line == null || "EOF".equalsIgnoreCase(line.trim())) {
118 done = true;
119 } else if (line.length() > 0) {
120 parseContentLine(line, pi);
121 }
122 } while (!done);
123 } finally {
124 try {
125 reader.close();
126 } catch (IOException e1) {
127
128 }
129 }
130
131 return pi.file;
132 }
133
134
135
136
137
138
139
140 private void parseHeaderLine(final int lineNumber, final String line, final ParseInfo pi)
141 throws OrekitException {
142
143 final SP3File file = pi.file;
144
145 Scanner scanner = null;
146 try {
147 scanner = new Scanner(line).useDelimiter("\\s+").useLocale(Locale.US);
148
149
150
151 switch (lineNumber) {
152
153
154 case 1: {
155 scanner.skip("#");
156 final String v = scanner.next();
157
158 final char version = v.substring(0, 1).toLowerCase().charAt(0);
159 if (version != 'a' && version != 'b' && version != 'c') {
160 throw new OrekitException(OrekitMessages.SP3_UNSUPPORTED_VERSION, version);
161 }
162
163 pi.hasVelocityEntries = "V".equals(v.substring(1, 2));
164
165 final int year = Integer.parseInt(v.substring(2));
166 final int month = scanner.nextInt();
167 final int day = scanner.nextInt();
168 final int hour = scanner.nextInt();
169 final int minute = scanner.nextInt();
170 final double second = scanner.nextDouble();
171
172 final AbsoluteDate epoch = new AbsoluteDate(year, month, day,
173 hour, minute, second,
174 TimeScalesFactory.getGPS());
175
176 file.setEpoch(epoch);
177
178 final int numEpochs = scanner.nextInt();
179 file.setNumberOfEpochs(numEpochs);
180
181
182 file.setDataUsed(scanner.next());
183
184 file.setCoordinateSystem(scanner.next());
185 file.setOrbitType(SP3OrbitType.parseType(scanner.next()));
186 file.setAgency(scanner.next());
187 break;
188 }
189
190
191 case 2: {
192 scanner.skip("##");
193
194
195 file.setGpsWeek(scanner.nextInt());
196
197 file.setSecondsOfWeek(scanner.nextDouble());
198
199 file.setEpochInterval(scanner.nextDouble());
200
201 file.setJulianDay(scanner.nextInt());
202
203 file.setDayFraction(scanner.nextDouble());
204 break;
205 }
206
207
208 case 3:
209 pi.maxSatellites = Integer.parseInt(line.substring(4, 6).trim());
210
211
212
213 case 4:
214 case 5:
215 case 6:
216 case 7: {
217 final int lineLength = line.length();
218 int count = file.getSatelliteCount();
219 int startIdx = 9;
220 while (count++ < pi.maxSatellites && (startIdx + 3) <= lineLength) {
221 final String satId = line.substring(startIdx, startIdx + 3).trim();
222 file.addSatellite(satId);
223 startIdx += 3;
224 }
225 break;
226 }
227
228
229 case 8:
230 case 9:
231 case 10:
232 case 11:
233 case 12: {
234 final int lineLength = line.length();
235 int satIdx = (lineNumber - 8) * 17;
236 int startIdx = 9;
237 while (satIdx < pi.maxSatellites && (startIdx + 3) <= lineLength) {
238 final SatelliteInformation satInfo = file.getSatellite(satIdx++);
239 final int exponent = Integer.parseInt(line.substring(startIdx, startIdx + 3).trim());
240
241
242 satInfo.setAccuracy((int) Math.pow(2d, exponent));
243 startIdx += 3;
244 }
245 break;
246 }
247
248 case 13: {
249 file.setType(getFileType(line.substring(3, 5).trim()));
250
251
252 final String tsStr = line.substring(9, 12).trim();
253 final TimeSystem ts;
254 if (tsStr.equalsIgnoreCase("ccc")) {
255 ts = TimeSystem.GPS;
256 } else {
257 ts = TimeSystem.valueOf(tsStr);
258 }
259 file.setTimeSystem(ts);
260
261 switch (ts) {
262 case GPS:
263 pi.timeScale = TimeScalesFactory.getGPS();
264 break;
265
266 case GAL:
267 pi.timeScale = TimeScalesFactory.getGST();
268 break;
269
270 case GLO:
271 pi.timeScale = TimeScalesFactory.getGLONASS();
272 break;
273
274 case QZS:
275 pi.timeScale = TimeScalesFactory.getQZSS();
276
277 case TAI:
278 pi.timeScale = TimeScalesFactory.getTAI();
279 break;
280
281 case UTC:
282 pi.timeScale = TimeScalesFactory.getUTC();
283 break;
284
285 default:
286 pi.timeScale = TimeScalesFactory.getGPS();
287 break;
288 }
289 break;
290 }
291
292 case 14:
293
294 break;
295
296
297
298 case 15: {
299
300
301
302
303
304
305
306
307
308
309
310 break;
311 }
312
313 case 16:
314 case 17:
315 case 18:
316
317 break;
318
319 case 19:
320 case 20:
321 case 21:
322 case 22:
323
324 break;
325 default:
326
327 break;
328 }
329
330
331
332 } finally {
333 if (scanner != null) {
334 scanner.close();
335 }
336 }
337
338 }
339
340
341
342
343
344 private void parseContentLine(final String line, final ParseInfo pi) {
345
346
347 final SP3File file = pi.file;
348
349 switch (line.charAt(0)) {
350 case '*': {
351 final int year = Integer.parseInt(line.substring(3, 7).trim());
352 final int month = Integer.parseInt(line.substring(8, 10).trim());
353 final int day = Integer.parseInt(line.substring(11, 13).trim());
354 final int hour = Integer.parseInt(line.substring(14, 16).trim());
355 final int minute = Integer.parseInt(line.substring(17, 19).trim());
356 final double second = Double.parseDouble(line.substring(20, 31).trim());
357
358 pi.latestEpoch = new AbsoluteDate(year, month, day,
359 hour, minute, second,
360 pi.timeScale);
361 break;
362 }
363
364 case 'P': {
365 final String satelliteId = line.substring(1, 4).trim();
366
367 if (!file.containsSatellite(satelliteId)) {
368 pi.latestPosition = null;
369 } else {
370 final double x = Double.parseDouble(line.substring(4, 18).trim());
371 final double y = Double.parseDouble(line.substring(18, 32).trim());
372 final double z = Double.parseDouble(line.substring(32, 46).trim());
373
374
375 pi.latestPosition = new Vector3D(x * 1000, y * 1000, z * 1000);
376
377
378 pi.latestClock = Double.parseDouble(line.substring(46, 60).trim());
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408 if (!pi.hasVelocityEntries) {
409 final SatelliteTimeCoordinate coord =
410 new SatelliteTimeCoordinate(pi.latestEpoch,
411 pi.latestPosition,
412 pi.latestClock);
413 file.addSatelliteCoordinate(satelliteId, coord);
414 }
415 }
416 break;
417 }
418
419 case 'V': {
420 final String satelliteId = line.substring(1, 4).trim();
421
422 if (file.containsSatellite(satelliteId)) {
423 final double xv = Double.parseDouble(line.substring(4, 18).trim());
424 final double yv = Double.parseDouble(line.substring(18, 32).trim());
425 final double zv = Double.parseDouble(line.substring(32, 46).trim());
426
427
428 final Vector3D velocity = new Vector3D(xv / 10d, yv / 10d, zv / 10d);
429
430 final double clockRateChange = Double.parseDouble(line.substring(46, 60).trim());
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449 final SatelliteTimeCoordinate coord =
450 new SatelliteTimeCoordinate(pi.latestEpoch,
451 new PVCoordinates(pi.latestPosition, velocity),
452 pi.latestClock,
453 clockRateChange);
454 file.addSatelliteCoordinate(satelliteId, coord);
455 }
456 break;
457 }
458
459 default:
460
461 break;
462 }
463 }
464
465
466
467
468
469 private SP3FileType getFileType(final String fileType) {
470 SP3FileType type = SP3FileType.UNDEFINED;
471 if ("G".equalsIgnoreCase(fileType)) {
472 type = SP3FileType.GPS;
473 } else if ("M".equalsIgnoreCase(fileType)) {
474 type = SP3FileType.MIXED;
475 } else if ("R".equalsIgnoreCase(fileType)) {
476 type = SP3FileType.GLONASS;
477 } else if ("L".equalsIgnoreCase(fileType)) {
478 type = SP3FileType.LEO;
479 } else if ("E".equalsIgnoreCase(fileType)) {
480 type = SP3FileType.GALILEO;
481 } else if ("C".equalsIgnoreCase(fileType)) {
482 type = SP3FileType.COMPASS;
483 } else if ("J".equalsIgnoreCase(fileType)) {
484 type = SP3FileType.QZSS;
485 }
486 return type;
487 }
488
489
490
491
492
493
494 private static class ParseInfo {
495
496
497 private SP3File file;
498
499
500 private AbsoluteDate latestEpoch;
501
502
503 private Vector3D latestPosition;
504
505
506 private double latestClock;
507
508
509 private boolean hasVelocityEntries;
510
511
512 private TimeScale timeScale;
513
514
515 private int maxSatellites;
516
517
518
519
520
521
522
523
524 protected ParseInfo() {
525 file = new SP3File();
526 latestEpoch = null;
527 latestPosition = null;
528 latestClock = 0.0d;
529 hasVelocityEntries = false;
530 timeScale = TimeScalesFactory.getGPS();
531 maxSatellites = 0;
532
533
534 }
535 }
536 }