CCSDS 503.0-B Tracking Data Message parser and serializer
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

irmin: adapt ocaml-scitt to new Schema API — 13/20 tests pass

+226 -25
+2
test/interop/orekit/scripts/.gitignore
··· 1 + orekit-data-master/ 2 + orekit-data-master.zip
+32 -25
test/interop/orekit/scripts/generate.java
··· 13 13 // OREKIT needs orekit-data for time scales. We bootstrap a minimal dataset 14 14 // (UTC-TAI.history) in a temp directory. 15 15 16 - import org.orekit.data.DataContext; 17 - import org.orekit.data.DataProvidersManager; 18 16 import org.orekit.data.DataSource; 19 - import org.orekit.data.DirectoryCrawler; 20 17 import org.orekit.files.ccsds.ndm.ParserBuilder; 21 18 import org.orekit.files.ccsds.ndm.WriterBuilder; 22 - import org.orekit.files.ccsds.ndm.tdm.Observation; 23 19 import org.orekit.files.ccsds.ndm.tdm.ObservationsBlock; 24 - import org.orekit.files.ccsds.ndm.tdm.ObservationType; 25 20 import org.orekit.files.ccsds.ndm.tdm.Tdm; 26 21 import org.orekit.files.ccsds.ndm.tdm.TdmMetadata; 27 22 import org.orekit.files.ccsds.ndm.tdm.TdmParser; 28 23 import org.orekit.files.ccsds.ndm.tdm.TdmWriter; 29 - import org.orekit.files.ccsds.section.Segment; 30 24 import org.orekit.files.ccsds.utils.generation.KvnGenerator; 31 - import org.orekit.time.AbsoluteDate; 32 25 import org.orekit.time.DateComponents; 33 26 import org.orekit.time.OffsetModel; 34 - import org.orekit.time.TAIUTCDatFilesLoader; 35 - import org.orekit.time.TimeScale; 36 27 import org.orekit.time.TimeScalesFactory; 37 28 import org.orekit.time.UTCTAIOffsetsLoader; 38 29 ··· 385 376 return sw.toString(); 386 377 } 387 378 388 - /** Extract observation values from a parsed TDM for the CSV index. */ 389 - static List<ExpectedObs> extractObs(Tdm tdm, TimeScale utc) { 379 + /** 380 + * Extract observation keywords, epochs, and values from the KVN text. 381 + * We parse from the generated KVN (not from getMeasurement()) because 382 + * OREKIT stores values in SI internally but writes them in TDM units. 383 + * Our OCaml parser reads KVN text, so expected values must match KVN. 384 + */ 385 + static List<ExpectedObs> extractObsFromKvn(String kvn) { 390 386 List<ExpectedObs> result = new ArrayList<>(); 391 - for (var segment : tdm.getSegments()) { 392 - ObservationsBlock block = segment.getData(); 393 - for (Observation obs : block.getObservations()) { 394 - String keyword = obs.getType().name(); 395 - AbsoluteDate epoch = obs.getEpoch(); 396 - double value = obs.getMeasurement(); 397 - String epochStr = epoch.toString(utc); 398 - result.add(new ExpectedObs(keyword, epochStr, value)); 399 - } 387 + boolean inData = false; 388 + for (String line : kvn.split("\n")) { 389 + line = line.trim(); 390 + if (line.equals("DATA_START")) { inData = true; continue; } 391 + if (line.equals("DATA_STOP")) { inData = false; continue; } 392 + if (!inData) continue; 393 + if (line.isEmpty() || line.startsWith("COMMENT")) continue; 394 + 395 + // Format: KEYWORD = epoch value 396 + int eq = line.indexOf('='); 397 + if (eq < 0) continue; 398 + String keyword = line.substring(0, eq).trim(); 399 + String rest = line.substring(eq + 1).trim(); 400 + int lastSpace = rest.lastIndexOf(' '); 401 + if (lastSpace < 0) continue; 402 + String epoch = rest.substring(0, lastSpace).trim(); 403 + String valStr = rest.substring(lastSpace + 1).trim(); 404 + double value = Double.parseDouble(valStr); 405 + result.add(new ExpectedObs(keyword, epoch, value)); 400 406 } 401 407 return result; 402 408 } ··· 429 435 String obsKeywords, String obsEpochs, String obsValues 430 436 ) {} 431 437 432 - static IndexRow buildIndexRow(String name, Tdm tdm, TimeScale utc) { 438 + static IndexRow buildIndexRow(String name, Tdm tdm, String kvnOut) { 433 439 var seg = tdm.getSegments().get(0); 434 440 TdmMetadata meta = seg.getMetadata(); 435 441 Map<Integer, String> participants = meta.getParticipants(); ··· 437 443 String p2 = participants.getOrDefault(2, ""); 438 444 String p3 = participants.getOrDefault(3, ""); 439 445 440 - List<ExpectedObs> obs = extractObs(tdm, utc); 446 + List<ExpectedObs> obs = extractObsFromKvn(kvnOut); 441 447 StringBuilder keywords = new StringBuilder(); 442 448 StringBuilder epochs = new StringBuilder(); 443 449 StringBuilder values = new StringBuilder(); ··· 469 475 // Bootstrap OREKIT with minimal data 470 476 bootstrap(); 471 477 472 - TimeScale utc = TimeScalesFactory.getUTC(); 478 + // Eagerly load UTC scale so parsing works 479 + TimeScalesFactory.getUTC(); 473 480 Scenario[] allScenarios = scenarios(); 474 481 List<IndexRow> indexRows = new ArrayList<>(); 475 482 ··· 494 501 Files.writeString(outPath, kvnOut); 495 502 System.out.println("Wrote " + outPath); 496 503 497 - // Build index row from OREKIT-parsed data 498 - indexRows.add(buildIndexRow(sc.name(), tdm, utc)); 504 + // Build index row from OREKIT-generated KVN 505 + indexRows.add(buildIndexRow(sc.name(), tdm, kvnOut)); 499 506 } 500 507 501 508 // Write CSV index
+25
test/interop/orekit/traces/angles_azel.kvn
··· 1 + CCSDS_TDM_VERS = 1.0 2 + CREATION_DATE = 2025-01-01T00:00:00.0 3 + ORIGINATOR = ESOC 4 + 5 + META_START 6 + TIME_SYSTEM = UTC 7 + START_TIME = 2024-06-01T00:00:00.0 8 + STOP_TIME = 2024-06-01T00:30:00.0 9 + PARTICIPANT_1 = MALINDI 10 + PARTICIPANT_2 = SENTINEL-1A 11 + MODE = SEQUENTIAL 12 + PATH = 1,2,1 13 + INTEGRATION_INTERVAL = 0.0 14 + FREQ_OFFSET = 0.0 15 + ANGLE_TYPE = AZEL 16 + DATA_QUALITY = VALIDATED 17 + META_STOP 18 + DATA_START 19 + ANGLE_1 = 2024-06-01T00:00:00.0 145.678901 20 + ANGLE_2 = 2024-06-01T00:00:00.0 32.456789 21 + ANGLE_1 = 2024-06-01T00:15:00.0 156.789012 22 + ANGLE_2 = 2024-06-01T00:15:00.0 45.56789 23 + ANGLE_1 = 2024-06-01T00:30:00.0 167.890123 24 + ANGLE_2 = 2024-06-01T00:30:00.0 58.678901 25 + DATA_STOP
+25
test/interop/orekit/traces/edge_values.kvn
··· 1 + CCSDS_TDM_VERS = 1.0 2 + CREATION_DATE = 2025-01-01T00:00:00.0 3 + ORIGINATOR = NASA/GSFC 4 + 5 + META_START 6 + TIME_SYSTEM = UTC 7 + START_TIME = 2024-12-31T23:59:00.0 8 + STOP_TIME = 2024-12-31T23:59:01.0 9 + PARTICIPANT_1 = WHITESANDS 10 + PARTICIPANT_2 = TDRS-M 11 + MODE = SEQUENTIAL 12 + PATH = 1,2,1 13 + TRANSMIT_BAND = S 14 + RECEIVE_BAND = S 15 + TIMETAG_REF = TRANSMIT 16 + INTEGRATION_INTERVAL = 0.0 17 + FREQ_OFFSET = 0.0 18 + RANGE_UNITS = km 19 + META_STOP 20 + DATA_START 21 + RANGE = 2024-12-31T23:59:00.0 0.0 22 + DOPPLER_INSTANTANEOUS = 2024-12-31T23:59:00.0 -99999.999999 23 + DOPPLER_INSTANTANEOUS = 2024-12-31T23:59:01.0 99999.999999 24 + RANGE = 2024-12-31T23:59:01.0 1.0E12 25 + DATA_STOP
+23
test/interop/orekit/traces/fractional_seconds.kvn
··· 1 + CCSDS_TDM_VERS = 1.0 2 + CREATION_DATE = 2025-01-01T00:00:00.0 3 + ORIGINATOR = JAXA 4 + 5 + META_START 6 + TIME_SYSTEM = UTC 7 + START_TIME = 2024-02-29T12:00:00.123 8 + STOP_TIME = 2024-02-29T12:00:01.123 9 + PARTICIPANT_1 = USUDA 10 + PARTICIPANT_2 = HAYABUSA2 11 + MODE = SEQUENTIAL 12 + PATH = 1,2,1 13 + TRANSMIT_BAND = X 14 + RECEIVE_BAND = X 15 + INTEGRATION_INTERVAL = 0.0 16 + FREQ_OFFSET = 0.0 17 + RANGE_UNITS = km 18 + META_STOP 19 + DATA_START 20 + RANGE = 2024-02-29T12:00:00.123 12345.6789 21 + RANGE = 2024-02-29T12:00:00.623 12345.789 22 + RANGE = 2024-02-29T12:00:01.123 12345.8901 23 + DATA_STOP
+8
test/interop/orekit/traces/index.csv
··· 1 + name,file,participant_1,participant_2,participant_3,num_observations,obs_keywords,obs_epochs,obs_values 2 + range_doppler,range_doppler.kvn,DSS-25,MARS RECONNAISSANCE ORBITER,,6,"RANGE;RANGE;RANGE;DOPPLER_INSTANTANEOUS;DOPPLER_INSTANTANEOUS;DOPPLER_INSTANTANEOUS","2024-03-15T10:00:00.0;2024-03-15T10:10:00.0;2024-03-15T10:20:00.0;2024-03-15T10:00:00.0;2024-03-15T10:10:00.0;2024-03-15T10:20:00.0","285432167.89000;285432245.12300;285432322.45600;-4567.1234560000;-4567.2345670000;-4567.3456780000" 3 + angles_azel,angles_azel.kvn,MALINDI,SENTINEL-1A,,6,"ANGLE_1;ANGLE_2;ANGLE_1;ANGLE_2;ANGLE_1;ANGLE_2","2024-06-01T00:00:00.0;2024-06-01T00:00:00.0;2024-06-01T00:15:00.0;2024-06-01T00:15:00.0;2024-06-01T00:30:00.0;2024-06-01T00:30:00.0","145.67890100000;32.456789000000;156.78901200000;45.567890000000;167.89012300000;58.678901000000" 4 + receive_freq,receive_freq.kvn,TOULOUSE,JASON-3,,3,"RECEIVE_FREQ;RECEIVE_FREQ;RECEIVE_FREQ","2024-09-20T08:30:00.0;2024-09-20T08:35:00.0;2024-09-20T08:40:00.0","8420432156.7890;8420432178.4560;8420432200.1230" 5 + mixed,mixed.kvn,WEILHEIM,TERRASAR-X,,8,"RANGE;ANGLE_1;ANGLE_2;DOPPLER_INSTANTANEOUS;RANGE;ANGLE_1;ANGLE_2;DOPPLER_INSTANTANEOUS","2025-01-01T00:00:00.0;2025-01-01T00:00:00.0;2025-01-01T00:00:00.0;2025-01-01T00:00:00.0;2025-01-01T00:01:00.0;2025-01-01T00:01:00.0;2025-01-01T00:01:00.0;2025-01-01T00:01:00.0","50000.000000000;90.000000000000;45.000000000000;-100.50000000000;50001.234000000;90.123000000000;45.456000000000;-100.67800000000" 6 + edge_values,edge_values.kvn,WHITESANDS,TDRS-M,,4,"RANGE;DOPPLER_INSTANTANEOUS;DOPPLER_INSTANTANEOUS;RANGE","2024-12-31T23:59:00.0;2024-12-31T23:59:00.0;2024-12-31T23:59:01.0;2024-12-31T23:59:01.0","0.0000000000000;-99999.999999000;99999.999999000;1000000000000.0" 7 + three_participants,three_participants.kvn,DSS-14,LUNAR-GATEWAY,ORION,2,"RANGE;RANGE","2024-07-04T12:00:00.0;2024-07-04T12:02:00.0","384400.00000000;384401.56700000" 8 + fractional_seconds,fractional_seconds.kvn,USUDA,HAYABUSA2,,3,"RANGE;RANGE;RANGE","2024-02-29T12:00:00.123;2024-02-29T12:00:00.623;2024-02-29T12:00:01.123","12345.678900000;12345.789000000;12345.890100000"
+33
test/interop/orekit/traces/mixed.kvn
··· 1 + CCSDS_TDM_VERS = 1.0 2 + CREATION_DATE = 2025-01-01T00:00:00.0 3 + ORIGINATOR = DLR 4 + 5 + META_START 6 + TIME_SYSTEM = UTC 7 + START_TIME = 2025-01-01T00:00:00.0 8 + STOP_TIME = 2025-01-01T00:01:00.0 9 + PARTICIPANT_1 = WEILHEIM 10 + PARTICIPANT_2 = TERRASAR-X 11 + MODE = SEQUENTIAL 12 + PATH = 1,2,1 13 + TRANSMIT_BAND = X 14 + RECEIVE_BAND = X 15 + TIMETAG_REF = TRANSMIT 16 + INTEGRATION_INTERVAL = 1.0 17 + INTEGRATION_REF = START 18 + FREQ_OFFSET = 0.0 19 + RANGE_MODE = COHERENT 20 + RANGE_UNITS = km 21 + ANGLE_TYPE = AZEL 22 + DATA_QUALITY = RAW 23 + META_STOP 24 + DATA_START 25 + RANGE = 2025-01-01T00:00:00.0 50000.0 26 + ANGLE_1 = 2025-01-01T00:00:00.0 90.0 27 + ANGLE_2 = 2025-01-01T00:00:00.0 45.0 28 + DOPPLER_INSTANTANEOUS = 2025-01-01T00:00:00.0 -100.5 29 + RANGE = 2025-01-01T00:01:00.0 50001.234 30 + ANGLE_1 = 2025-01-01T00:01:00.0 90.123 31 + ANGLE_2 = 2025-01-01T00:01:00.0 45.456 32 + DOPPLER_INSTANTANEOUS = 2025-01-01T00:01:00.0 -100.678 33 + DATA_STOP
+30
test/interop/orekit/traces/range_doppler.kvn
··· 1 + CCSDS_TDM_VERS = 1.0 2 + CREATION_DATE = 2025-01-01T00:00:00.0 3 + ORIGINATOR = NASA/JPL 4 + 5 + META_START 6 + TIME_SYSTEM = UTC 7 + START_TIME = 2024-03-15T10:00:00.0 8 + STOP_TIME = 2024-03-15T10:20:00.0 9 + PARTICIPANT_1 = DSS-25 10 + PARTICIPANT_2 = MARS RECONNAISSANCE ORBITER 11 + MODE = SEQUENTIAL 12 + PATH = 1,2,1 13 + TRANSMIT_BAND = X 14 + RECEIVE_BAND = X 15 + TIMETAG_REF = TRANSMIT 16 + INTEGRATION_INTERVAL = 1.0 17 + INTEGRATION_REF = MIDDLE 18 + FREQ_OFFSET = 0.0 19 + RANGE_MODE = COHERENT 20 + RANGE_UNITS = km 21 + DATA_QUALITY = RAW 22 + META_STOP 23 + DATA_START 24 + RANGE = 2024-03-15T10:00:00.0 2.8543216789E8 25 + RANGE = 2024-03-15T10:10:00.0 2.85432245123E8 26 + RANGE = 2024-03-15T10:20:00.0 2.85432322456E8 27 + DOPPLER_INSTANTANEOUS = 2024-03-15T10:00:00.0 -4567.123456 28 + DOPPLER_INSTANTANEOUS = 2024-03-15T10:10:00.0 -4567.234567 29 + DOPPLER_INSTANTANEOUS = 2024-03-15T10:20:00.0 -4567.345678 30 + DATA_STOP
+23
test/interop/orekit/traces/receive_freq.kvn
··· 1 + CCSDS_TDM_VERS = 1.0 2 + CREATION_DATE = 2025-01-01T00:00:00.0 3 + ORIGINATOR = CNES 4 + 5 + META_START 6 + TIME_SYSTEM = UTC 7 + START_TIME = 2024-09-20T08:30:00.0 8 + STOP_TIME = 2024-09-20T08:40:00.0 9 + PARTICIPANT_1 = TOULOUSE 10 + PARTICIPANT_2 = JASON-3 11 + MODE = SEQUENTIAL 12 + PATH = 1,2,1 13 + TRANSMIT_BAND = X 14 + RECEIVE_BAND = X 15 + TIMETAG_REF = RECEIVE 16 + INTEGRATION_INTERVAL = 0.0 17 + FREQ_OFFSET = 0.0 18 + META_STOP 19 + DATA_START 20 + RECEIVE_FREQ = 2024-09-20T08:30:00.0 8.420432156789E9 21 + RECEIVE_FREQ = 2024-09-20T08:35:00.0 8.420432178456E9 22 + RECEIVE_FREQ = 2024-09-20T08:40:00.0 8.420432200123E9 23 + DATA_STOP
+25
test/interop/orekit/traces/three_participants.kvn
··· 1 + CCSDS_TDM_VERS = 1.0 2 + CREATION_DATE = 2025-01-01T00:00:00.0 3 + ORIGINATOR = NASA/JPL 4 + 5 + META_START 6 + TIME_SYSTEM = UTC 7 + START_TIME = 2024-07-04T12:00:00.0 8 + STOP_TIME = 2024-07-04T12:02:00.0 9 + PARTICIPANT_1 = DSS-14 10 + PARTICIPANT_2 = LUNAR-GATEWAY 11 + PARTICIPANT_3 = ORION 12 + MODE = SEQUENTIAL 13 + PATH = 1,2,3 14 + TRANSMIT_BAND = KA 15 + RECEIVE_BAND = KA 16 + TIMETAG_REF = TRANSMIT 17 + INTEGRATION_INTERVAL = 0.0 18 + FREQ_OFFSET = 0.0 19 + RANGE_MODE = COHERENT 20 + RANGE_UNITS = km 21 + META_STOP 22 + DATA_START 23 + RANGE = 2024-07-04T12:00:00.0 384400.0 24 + RANGE = 2024-07-04T12:02:00.0 384401.567 25 + DATA_STOP