1   /* Copyright 2002-2025 CS GROUP
2    * Licensed to CS Systèmes d'Information (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.files.ccsds.ndm.odm.ocm;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.hipparchus.util.FastMath;
21  import org.junit.jupiter.api.Assertions;
22  import org.junit.jupiter.api.BeforeEach;
23  import org.junit.jupiter.api.Test;
24  import org.orekit.Utils;
25  import org.orekit.data.DataContext;
26  import org.orekit.data.DataSource;
27  import org.orekit.errors.OrekitException;
28  import org.orekit.errors.OrekitMessages;
29  import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
30  import org.orekit.files.ccsds.definitions.CenterName;
31  import org.orekit.files.ccsds.definitions.DutyCycleType;
32  import org.orekit.files.ccsds.definitions.OdMethodType;
33  import org.orekit.files.ccsds.definitions.OnOff;
34  import org.orekit.files.ccsds.definitions.OrbitRelativeFrame;
35  import org.orekit.files.ccsds.definitions.SpacecraftBodyFrame;
36  import org.orekit.files.ccsds.definitions.TimeSystem;
37  import org.orekit.files.ccsds.definitions.Units;
38  import org.orekit.files.ccsds.ndm.ParserBuilder;
39  import org.orekit.files.ccsds.ndm.WriterBuilder;
40  import org.orekit.files.ccsds.ndm.odm.UserDefined;
41  import org.orekit.files.ccsds.ndm.odm.oem.InterpolationMethod;
42  import org.orekit.files.ccsds.utils.generation.Generator;
43  import org.orekit.files.ccsds.utils.generation.KvnGenerator;
44  import org.orekit.files.ccsds.utils.lexical.KvnLexicalAnalyzer;
45  import org.orekit.files.ccsds.utils.lexical.XmlLexicalAnalyzer;
46  import org.orekit.time.AbsoluteDate;
47  import org.orekit.time.TimeOffset;
48  import org.orekit.time.TimeScale;
49  import org.orekit.time.TimeScalesFactory;
50  import org.orekit.utils.Constants;
51  import org.orekit.utils.IERSConventions;
52  import org.orekit.utils.TimeStampedPVCoordinates;
53  import org.orekit.utils.units.Unit;
54  
55  import java.io.ByteArrayInputStream;
56  import java.io.CharArrayWriter;
57  import java.io.IOException;
58  import java.io.InputStreamReader;
59  import java.nio.charset.StandardCharsets;
60  import java.util.List;
61  import java.util.Locale;
62  
63  public class OcmParserTest {
64  
65      @BeforeEach
66      public void setUp() {
67          Utils.setDataRoot("regular-data");
68      }
69  
70      @Test
71      public void testNonExistentKvnFile() {
72          final String realName = "/ccsds/odm/ocm/OCMExample1.txt";
73          final String wrongName = realName + "xxxxx";
74          final DataSource source = new DataSource(wrongName, () -> getClass().getResourceAsStream(wrongName));
75          try {
76              new KvnLexicalAnalyzer(source).accept(new ParserBuilder().buildOcmParser());
77              Assertions.fail("an exception should have been thrown");
78          } catch (OrekitException oe) {
79              Assertions.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
80              Assertions.assertEquals(wrongName, oe.getParts()[0]);
81          }
82      }
83  
84      @Test
85      public void testNonExistentXmlFile() {
86          final String realName = "/ccsds/odm/ocm/OCMExample1.txt";
87          final String wrongName = realName + "xxxxx";
88          final DataSource source = new DataSource(wrongName, () -> getClass().getResourceAsStream(wrongName));
89          try {
90              new XmlLexicalAnalyzer(source).accept(new ParserBuilder().buildOcmParser());
91              Assertions.fail("an exception should have been thrown");
92          } catch (OrekitException oe) {
93              Assertions.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
94              Assertions.assertEquals(wrongName, oe.getParts()[0]);
95          }
96      }
97  
98      @Test
99      public void testMissingT0() {
100         final String name = "/ccsds/odm/ocm/OCM-missing-t0.txt";
101         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
102         try {
103             new ParserBuilder().
104             withMu(Constants.EIGEN5C_EARTH_MU).
105             buildOcmParser().
106             parseMessage(source);
107             Assertions.fail("an exception should have been thrown");
108         } catch (OrekitException oe) {
109             Assertions.assertEquals(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, oe.getSpecifier());
110             Assertions.assertEquals(OcmMetadataKey.EPOCH_TZERO.name(), oe.getParts()[0]);
111         }
112     }
113 
114     @Test
115     public void testMissingManeuverTime() {
116         final String name = "/ccsds/odm/ocm/OCM-missing-maneuver-time.txt";
117         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
118         try {
119             new ParserBuilder().
120             withMu(Constants.EIGEN5C_EARTH_MU).
121             buildOcmParser().
122             parseMessage(source);
123             Assertions.fail("an exception should have been thrown");
124         } catch (OrekitException oe) {
125             Assertions.assertEquals(OrekitMessages.CCSDS_MANEUVER_MISSING_TIME, oe.getSpecifier());
126             Assertions.assertEquals("MAN-45", oe.getParts()[0]);
127         }
128     }
129 
130     @Test
131     public void testWrongTimeSpan() {
132         final String name = "/ccsds/odm/ocm/OCM-wrong-time-span.txt";
133         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
134         try {
135             new ParserBuilder().
136             withMu(Constants.EIGEN5C_EARTH_MU).
137             buildOcmParser().
138             parseMessage(source);
139             Assertions.fail("an exception should have been thrown");
140         } catch (OrekitException oe) {
141             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_ELEMENT_IN_FILE, oe.getSpecifier());
142             Assertions.assertEquals("TIME_SPAN", oe.getParts()[0]);
143             Assertions.assertEquals(11, ((Integer) oe.getParts()[1]).intValue());
144             Assertions.assertTrue(((String) oe.getParts()[2]).endsWith("OCM-wrong-time-span.txt"));
145         }
146     }
147 
148     @Test
149     public void testMissingRevnumBasis() {
150         final String name = "/ccsds/odm/ocm/OCM-missing-revnum-basis.txt";
151         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
152         try {
153             new ParserBuilder().
154             withMu(Constants.EIGEN5C_EARTH_MU).
155             buildOcmParser().
156             parseMessage(source);
157             Assertions.fail("an exception should have been thrown");
158         } catch (OrekitException oe) {
159             Assertions.assertEquals(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, oe.getSpecifier());
160             Assertions.assertEquals(TrajectoryStateHistoryMetadataKey.ORB_REVNUM_BASIS.name(), oe.getParts()[0]);
161         }
162     }
163 
164     @Test
165     public void testSpuriousMetaDataSection() {
166         final String name = "/ccsds/odm/ocm/OCM-spurious-metadata-section.txt";
167         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
168         try {
169             new ParserBuilder().
170             withMu(Constants.EIGEN5C_EARTH_MU).
171             buildOcmParser().
172             parseMessage(source);
173             Assertions.fail("an exception should have been thrown");
174         } catch (OrekitException oe) {
175             Assertions.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
176             Assertions.assertEquals(13, ((Integer) oe.getParts()[0]).intValue());
177             Assertions.assertEquals("META", oe.getParts()[2]);
178         }
179     }
180 
181     @Test
182     public void testIncompatibleUnitsDimension() {
183         final String name = "/ccsds/odm/ocm/OCM-incompatible-units-dimension.txt";
184         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
185         try {
186             new ParserBuilder().
187             withMu(Constants.EIGEN5C_EARTH_MU).
188             buildOcmParser().
189             parseMessage(source);
190             Assertions.fail("an exception should have been thrown");
191         } catch (OrekitException oe) {
192             Assertions.assertEquals(OrekitMessages.INCOMPATIBLE_UNITS, oe.getSpecifier());
193             Assertions.assertEquals("km²/s", oe.getParts()[0]);
194             Assertions.assertEquals("m", oe.getParts()[1]);
195         }
196     }
197 
198     @Test
199     public void testIncompatibleUnitsScale() {
200         final String name = "/ccsds/odm/ocm/OCM-incompatible-units-scale.txt";
201         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
202         try {
203             new ParserBuilder().
204             withMu(Constants.EIGEN5C_EARTH_MU).
205             buildOcmParser().
206             parseMessage(source);
207             Assertions.fail("an exception should have been thrown");
208         } catch (OrekitException oe) {
209             Assertions.assertEquals(OrekitMessages.INCOMPATIBLE_UNITS, oe.getSpecifier());
210             Assertions.assertEquals("km", oe.getParts()[0]);
211             Assertions.assertEquals("m", oe.getParts()[1]);
212         }
213     }
214 
215     @Test
216     public void testWrongNbElements() {
217         final String name = "/ccsds/odm/ocm/OCM-wrong-nb-elements.txt";
218         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
219         try {
220             new ParserBuilder().
221             withMu(Constants.EIGEN5C_EARTH_MU).
222             buildOcmParser().
223             parseMessage(source);
224             Assertions.fail("an exception should have been thrown");
225         } catch (OrekitException oe) {
226             Assertions.assertEquals(OrekitMessages.WRONG_NB_COMPONENTS, oe.getSpecifier());
227             Assertions.assertEquals(OrbitElementsType.CARTP.toString(), oe.getParts()[0]);
228             Assertions.assertEquals(3, ((Integer) oe.getParts()[1]).intValue());
229             Assertions.assertEquals(6, ((Integer) oe.getParts()[2]).intValue());
230         }
231     }
232 
233     @Test
234     public void testUnknownFrame() {
235         final String name = "/ccsds/odm/ocm/OCM-unknown-frame.txt";
236         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
237         final Ocm    ocm    = new ParserBuilder().
238                                   withMu(Constants.EIGEN5C_EARTH_MU).
239                                   buildOcmParser().
240                                   parseMessage(source);
241         Assertions.assertEquals("CS GROUP", ocm.getHeader().getOriginator());
242         Assertions.assertEquals("728b0d2a-01fc-4d0e-9f0a-370c6930ea84", ocm.getHeader().getMessageId().toLowerCase(Locale.US));
243         final TrajectoryStateHistory h = ocm.getData().getTrajectoryBlocks().get(0);
244         Assertions.assertEquals("ZZRF", h.getMetadata().getTrajReferenceFrame().getName());
245         List<TimeStampedPVCoordinates> l = h.getCoordinates();
246         Assertions.assertEquals( 3.0e6, l.get(0).getPosition().getX(), 1.0e-9);
247         Assertions.assertEquals( 4.0e6, l.get(0).getPosition().getY(), 1.0e-9);
248         Assertions.assertEquals( 5.0e6, l.get(0).getPosition().getZ(), 1.0e-9);
249         Assertions.assertEquals(-1.0e3, l.get(0).getVelocity().getX(), 1.0e-12);
250         Assertions.assertEquals(-2.0e3, l.get(0).getVelocity().getY(), 1.0e-12);
251         Assertions.assertEquals(-3.0e3, l.get(0).getVelocity().getZ(), 1.0e-1);
252         try {
253             ocm.getData().getTrajectoryBlocks().get(0).getFrame();
254             Assertions.fail("an exception should have been thrown");
255         } catch (OrekitException oe) {
256             Assertions.assertEquals(OrekitMessages.CCSDS_INVALID_FRAME, oe.getSpecifier());
257             Assertions.assertEquals("ZZRF", oe.getParts()[0]);
258         }
259     }
260 
261     @Test
262     public void testUserDefined() {
263         final String name = "/ccsds/odm/ocm/OCM-user-defined.txt";
264         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
265         final Ocm    ocm    = new ParserBuilder().
266                                   withMu(Constants.EIGEN5C_EARTH_MU).
267                                   buildOcmParser().
268                                   parseMessage(source);
269         Assertions.assertEquals("CS GROUP", ocm.getHeader().getOriginator());
270         Assertions.assertEquals("b77d785c-f7a8-4a80-a9b1-a540eac19d7a", ocm.getHeader().getMessageId().toLowerCase(Locale.US));
271         Assertions.assertNull(ocm.getData().getTrajectoryBlocks());
272         Assertions.assertEquals(1, ocm.getData().getUserDefinedBlock().getComments().size());
273         Assertions.assertEquals("some user data", ocm.getData().getUserDefinedBlock().getComments().get(0));
274         Assertions.assertEquals(1, ocm.getData().getUserDefinedBlock().getParameters().size());
275         Assertions.assertEquals("OREKIT", ocm.getData().getUserDefinedBlock().getParameters().get("GENERATOR"));
276     }
277 
278     @Test
279     public void testParseOCM1() {
280         final String   name  = "/ccsds/odm/ocm/OCMExample1.txt";
281         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
282         final Ocm file = new ParserBuilder().
283                              withMu(Constants.EIGEN5C_EARTH_MU).
284                              buildOcmParser().
285                              parseMessage(source);
286 
287         // check the default values that are not set in this simple file
288         Assertions.assertEquals(1.0, file.getMetadata().getSclkSecPerSISec(), 1.0e-15);
289 
290         // Check Header Block;
291         Assertions.assertEquals(3.0, file.getHeader().getFormatVersion(), 1.0e-10);
292         Assertions.assertEquals(new AbsoluteDate(1998, 11, 6, 9, 23, 57, TimeScalesFactory.getUTC()),
293                             file.getHeader().getCreationDate());
294 
295         // OCM is the only message for which OBJECT_NAME is not mandatory, it is not present in this minimal file
296         Assertions.assertNull(file.getMetadata().getObjectName());
297 
298         Assertions.assertEquals("JAXA", file.getHeader().getOriginator());
299 
300         final AbsoluteDate t0 = new AbsoluteDate(1998, 12, 18, 14, 28, new TimeOffset(15, TimeOffset.SECOND, 117200, TimeOffset.MICROSECOND),
301                                                  TimeScalesFactory.getUTC());
302         Assertions.assertEquals(t0, file.getMetadata().getEpochT0());
303         Assertions.assertEquals(TimeSystem.UTC, file.getMetadata().getTimeSystem());
304 
305         // trajectory data
306         Assertions.assertEquals(1, file.getData().getTrajectoryBlocks().size());
307         TrajectoryStateHistory history = file.getData().getTrajectoryBlocks().get(0);
308         Assertions.assertEquals("intervening data records omitted between DT=20.0 and DT=500.0",
309                             history.getMetadata().getComments().get(0));
310         Assertions.assertEquals("OSCULATING", history.getMetadata().getOrbAveraging());
311         Assertions.assertEquals("EARTH", history.getMetadata().getCenter().getName());
312         Assertions.assertEquals(CelestialBodyFrame.ITRF2000, history.getMetadata().getTrajReferenceFrame().asCelestialBodyFrame());
313         Assertions.assertEquals(OrbitElementsType.CARTPV, history.getMetadata().getTrajType());
314         Assertions.assertEquals(0.0, file.getMetadata().getEpochT0().durationFrom(t0), 1.0e-15);
315         List<TrajectoryState> states = history.getTrajectoryStates();
316         Assertions.assertEquals(4, states.size());
317 
318         Assertions.assertEquals(0.0, states.get(0).getDate().durationFrom(t0), 1.0e-15);
319         Assertions.assertEquals(6, states.get(0).getElements().length);
320         Assertions.assertEquals( 2789600.0, states.get(0).getElements()[0], 1.0e-15);
321         Assertions.assertEquals( -280000.0, states.get(0).getElements()[1], 1.0e-15);
322         Assertions.assertEquals(-1746800.0, states.get(0).getElements()[2], 1.0e-15);
323         Assertions.assertEquals(    4730.0, states.get(0).getElements()[3], 1.0e-15);
324         Assertions.assertEquals(   -2500.0, states.get(0).getElements()[4], 1.0e-15);
325         Assertions.assertEquals(   -1040.0, states.get(0).getElements()[5], 1.0e-15);
326 
327         Assertions.assertEquals(10.0, states.get(1).getDate().durationFrom(t0), 1.0e-15);
328         Assertions.assertEquals(6, states.get(1).getElements().length);
329         Assertions.assertEquals( 2783400.0, states.get(1).getElements()[0], 1.0e-15);
330         Assertions.assertEquals( -308100.0, states.get(1).getElements()[1], 1.0e-15);
331         Assertions.assertEquals(-1877100.0, states.get(1).getElements()[2], 1.0e-15);
332         Assertions.assertEquals(    5190.0, states.get(1).getElements()[3], 1.0e-15);
333         Assertions.assertEquals(   -2420.0, states.get(1).getElements()[4], 1.0e-15);
334         Assertions.assertEquals(   -2000.0, states.get(1).getElements()[5], 1.0e-15);
335 
336         Assertions.assertEquals(20.0, states.get(2).getDate().durationFrom(t0), 1.0e-15);
337         Assertions.assertEquals(6, states.get(2).getElements().length);
338         Assertions.assertEquals( 2776000.0, states.get(2).getElements()[0], 1.0e-15);
339         Assertions.assertEquals( -336900.0, states.get(2).getElements()[1], 1.0e-15);
340         Assertions.assertEquals(-2008700.0, states.get(2).getElements()[2], 1.0e-15);
341         Assertions.assertEquals(    5640.0, states.get(2).getElements()[3], 1.0e-15);
342         Assertions.assertEquals(   -2340.0, states.get(2).getElements()[4], 1.0e-15);
343         Assertions.assertEquals(   -1950.0, states.get(2).getElements()[5], 1.0e-15);
344 
345         Assertions.assertEquals(500.0, states.get(3).getDate().durationFrom(t0), 1.0e-15);
346         Assertions.assertEquals(6, states.get(3).getElements().length);
347         Assertions.assertEquals( 2164375.0,  states.get(3).getElements()[0], 1.0e-15);
348         Assertions.assertEquals( 1115811.0,  states.get(3).getElements()[1], 1.0e-15);
349         Assertions.assertEquals( -688131.0,  states.get(3).getElements()[2], 1.0e-15);
350         Assertions.assertEquals(   -3533.28, states.get(3).getElements()[3], 1.0e-15);
351         Assertions.assertEquals(   -2884.52, states.get(3).getElements()[4], 1.0e-15);
352         Assertions.assertEquals(     885.35, states.get(3).getElements()[5], 1.0e-15);
353 
354         Assertions.assertEquals(1, file.getSatellites().size());
355         Assertions.assertEquals("UNKNOWN", file.getSatellites().entrySet().iterator().next().getKey());
356 
357     }
358 
359     @Test
360     public void testParseOCM2KVN() {
361         final String  name = "/ccsds/odm/ocm/OCMExample2.txt";
362         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
363         final Ocm file = new ParserBuilder().
364                              withMu(Constants.EIGEN5C_EARTH_MU).
365                              buildOcmParser().
366                              parseMessage(source);
367 
368         // Check Header Block;
369         Assertions.assertEquals(3.0, file.getHeader().getFormatVersion(), 1.0e-10);
370         Assertions.assertEquals("This OCM reflects the latest conditions post-maneuver A67Z",
371                             file.getHeader().getComments().get(0));
372         Assertions.assertEquals("This example shows the specification of multiple comment lines",
373                             file.getHeader().getComments().get(1));
374         Assertions.assertEquals(new AbsoluteDate(1998, 11, 6, 9, 23, 57, TimeScalesFactory.getUTC()),
375                             file.getHeader().getCreationDate());
376         Assertions.assertEquals("JAXA", file.getHeader().getOriginator());
377         Assertions.assertEquals("OCM 201113719185", file.getHeader().getMessageId());
378 
379         // Check metadata
380         Assertions.assertEquals("OSPREY 5",                                           file.getMetadata().getObjectName());
381         Assertions.assertEquals("1998-999A",                                          file.getMetadata().getInternationalDesignator());
382         Assertions.assertEquals("R. Rabbit",                                          file.getMetadata().getOriginatorPOC());
383         Assertions.assertEquals("Flight Dynamics Mission Design Lead",                file.getMetadata().getOriginatorPosition());
384         Assertions.assertEquals("(719)555-1234",                                      file.getMetadata().getOriginatorPhone());
385         Assertions.assertEquals("R.Rabbit@example.net",                               file.getMetadata().getOriginatorEmail());
386         Assertions.assertEquals("5040 Spaceflight Ave., Cocoa Beach, FL, USA, 12345", file.getMetadata().getOriginatorAddress());
387         Assertions.assertEquals("Mr. Rodgers",                                        file.getMetadata().getTechPOC());
388         Assertions.assertEquals("(719)555-4321",                                      file.getMetadata().getTechPhone());
389         Assertions.assertEquals("Rodgers@elsewhere.org",                              file.getMetadata().getTechEmail());
390         Assertions.assertEquals("125 CCSDS Road, Easter Island",                      file.getMetadata().getTechAddress());
391         Assertions.assertEquals(TimeSystem.UT1, file.getMetadata().getTimeSystem());
392         TimeScale ts = DataContext.getDefault().getTimeScales().getUT1(IERSConventions.IERS_2010, false);
393         Assertions.assertEquals(0.0,
394                             file.getMetadata().getEpochT0().durationFrom(new AbsoluteDate(1998, 12, 18, ts)),
395                             1.0e-10);
396         Assertions.assertEquals(36.0,                                  file.getMetadata().getTaimutcT0(),       1.0e-15);
397         Assertions.assertEquals(0.0,
398                             file.getMetadata().getNextLeapEpoch().
399                             durationFrom(new AbsoluteDate(2016, 12, 31, 23, 59, 60.0, TimeScalesFactory.getUTC())),
400                             3.0e-5);
401         Assertions.assertEquals(37.0,                                  file.getMetadata().getNextLeapTaimutc(), 1.0e-15);
402         Assertions.assertEquals(0.357,                                 file.getMetadata().getUt1mutcT0(),       1.0e-15);
403 
404         // check trajectory data
405         Assertions.assertEquals(1, file.getData().getTrajectoryBlocks().size());
406         final TrajectoryStateHistory orb = file.getData().getTrajectoryBlocks().get(0);
407         Assertions.assertEquals(2, orb.getMetadata().getComments().size());
408         Assertions.assertEquals("GEOCENTRIC, CARTESIAN, EARTH FIXED", orb.getMetadata().getComments().get(0));
409         Assertions.assertEquals("THIS IS MY SECOND COMMENT LINE",     orb.getMetadata().getComments().get(1));
410         Assertions.assertEquals("PREDICTED", orb.getMetadata().getTrajBasis());
411         Assertions.assertEquals("EFG", orb.getMetadata().getTrajReferenceFrame().getName());
412         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asFrame());
413         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asCelestialBodyFrame());
414         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asOrbitRelativeFrame());
415         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asSpacecraftBodyFrame());
416         Assertions.assertEquals(OrbitElementsType.CARTPV, orb.getMetadata().getTrajType());
417         Assertions.assertEquals(6, orb.getMetadata().getTrajUnits().size());
418         Assertions.assertEquals("km",   orb.getMetadata().getTrajUnits().get(0).getName());
419         Assertions.assertEquals("km",   orb.getMetadata().getTrajUnits().get(1).getName());
420         Assertions.assertEquals("km",   orb.getMetadata().getTrajUnits().get(2).getName());
421         Assertions.assertEquals("km/s", orb.getMetadata().getTrajUnits().get(3).getName());
422         Assertions.assertEquals("km/s", orb.getMetadata().getTrajUnits().get(4).getName());
423         Assertions.assertEquals("km/s", orb.getMetadata().getTrajUnits().get(5).getName());
424         Assertions.assertEquals(1, orb.getTrajectoryStates().size());
425         Assertions.assertEquals(new AbsoluteDate(1998, 12, 18, 14, 28, new TimeOffset(25L, 117200000000000000L), ts),
426                                 orb.getTrajectoryStates().get(0).getDate());
427         Assertions.assertEquals( 2854533.0, orb.getTrajectoryStates().get(0).getElements()[0], 1.0e-10);
428         Assertions.assertEquals(-2916187.0, orb.getTrajectoryStates().get(0).getElements()[1], 1.0e-10);
429         Assertions.assertEquals(-5360774.0, orb.getTrajectoryStates().get(0).getElements()[2], 1.0e-10);
430         Assertions.assertEquals(    5688.0, orb.getTrajectoryStates().get(0).getElements()[3], 1.0e-10);
431         Assertions.assertEquals(    4652.0, orb.getTrajectoryStates().get(0).getElements()[4], 1.0e-10);
432         Assertions.assertEquals(     520.0, orb.getTrajectoryStates().get(0).getElements()[5], 1.0e-10);
433 
434         // check physical data
435         OrbitPhysicalProperties phys = file.getData().getPhysicBlock();
436         Assertions.assertEquals(1, phys.getComments().size());
437         Assertions.assertEquals("S/C Physical Characteristics:", phys.getComments().get(0));
438         Assertions.assertEquals(100.0,   phys.getWetMass(),                  1.0e-10);
439         Assertions.assertEquals(0.03123, phys.getOebQ().getQ1(),             1.0e-10);
440         Assertions.assertEquals(0.78543, phys.getOebQ().getQ2(),             1.0e-10);
441         Assertions.assertEquals(0.39158, phys.getOebQ().getQ3(),             1.0e-10);
442         Assertions.assertEquals(0.47832, phys.getOebQ().getQ0(),             1.0e-10);
443         Assertions.assertEquals(2.0,     phys.getOebMax(),                   1.0e-10);
444         Assertions.assertEquals(1.0,     phys.getOebIntermediate(),          1.0e-10);
445         Assertions.assertEquals(0.5,     phys.getOebMin(),                   1.0e-10);
446         Assertions.assertEquals(0.15,    phys.getOebAreaAlongMax(),          1.0e-10);
447         Assertions.assertEquals(0.30,    phys.getOebAreaAlongIntermediate(), 1.0e-10);
448         Assertions.assertEquals(0.50,    phys.getOebAreaAlongMin(),          1.0e-10);
449 
450         // check no covariance
451         Assertions.assertNull(file.getData().getCovarianceBlocks());
452 
453         // check no maneuvers
454         Assertions.assertNull(file.getData().getManeuverBlocks());
455 
456         // check perturbation data
457         Perturbations perts = file.getData().getPerturbationsBlock();
458         Assertions.assertEquals(1, perts.getComments().size());
459         Assertions.assertEquals("Perturbations Specification:", perts.getComments().get(0));
460         Assertions.assertEquals("NRLMSIS00", perts.getAtmosphericModel());
461         Assertions.assertEquals("EGM-96", perts.getGravityModel());
462         Assertions.assertEquals(36, perts.getGravityDegree());
463         Assertions.assertEquals(36, perts.getGravityOrder());
464         Assertions.assertEquals(2, perts.getNBodyPerturbations().size());
465         Assertions.assertEquals("MOON", perts.getNBodyPerturbations().get(0).getName());
466         Assertions.assertEquals("SUN",  perts.getNBodyPerturbations().get(1).getName());
467         Assertions.assertEquals( 12.0, Units.NANO_TESLA.fromSI(perts.getFixedGeomagneticKp()), 1.0e-10);
468         Assertions.assertEquals(105.0, Unit.SOLAR_FLUX_UNIT.fromSI(perts.getFixedF10P7()),     1.0e-10);
469         Assertions.assertEquals(120.0, Unit.SOLAR_FLUX_UNIT.fromSI(perts.getFixedF10P7Mean()), 1.0e-10);
470 
471         // check no orbit determination
472         Assertions.assertNull(file.getData().getOrbitDeterminationBlock());
473 
474         // check user data
475         UserDefined user = file.getData().getUserDefinedBlock();
476         Assertions.assertTrue(user.getComments().isEmpty());
477         Assertions.assertEquals(1, user.getParameters().size());
478         Assertions.assertEquals("MAXWELL RAFERTY", user.getParameters().get("CONSOLE_POC"));
479 
480         Assertions.assertEquals(1, file.getSatellites().size());
481         Assertions.assertEquals("OSPREY 5", file.getSatellites().entrySet().iterator().next().getKey());
482 
483     }
484 
485     @Test
486     public void testParseOCM2XMLBinary() {
487         final String  name = "/ccsds/odm/ocm/OCMExample2.xml";
488         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
489         validateOCM2XML(new ParserBuilder().
490                         withMu(Constants.EIGEN5C_EARTH_MU).
491                         buildOcmParser().
492                         parseMessage(source));
493     }
494 
495     @Test
496     public void testParseOCM2XMLCharacter() {
497         final String  name = "/ccsds/odm/ocm/OCMExample2.xml";
498         final DataSource source = new DataSource(name, () -> new InputStreamReader(getClass().getResourceAsStream(name), StandardCharsets.UTF_8));
499         validateOCM2XML(new ParserBuilder().
500                         withMu(Constants.EIGEN5C_EARTH_MU).
501                         buildOcmParser().
502                         parseMessage(source));
503     }
504 
505     @Test
506     public void testWriteOCM2() throws IOException {
507         final String name = "/ccsds/odm/ocm/OCMExample2.xml";
508         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
509         OcmParser parser = new ParserBuilder(). withMu(Constants.EIGEN5C_EARTH_MU).buildOcmParser();
510         final Ocm original = parser.parseMessage(source);
511 
512         // write the parsed file back to a characters array
513         final CharArrayWriter caw = new CharArrayWriter();
514         final Generator generator = new KvnGenerator(caw, OcmWriter.KVN_PADDING_WIDTH, "dummy",
515                                                      Constants.JULIAN_DAY, 60);
516         new WriterBuilder().buildOcmWriter().writeMessage(generator, original);
517 
518         // reparse the written file
519         final byte[]     bytes   = caw.toString().getBytes(StandardCharsets.UTF_8);
520         final DataSource source2 = new DataSource(name, () -> new ByteArrayInputStream(bytes));
521         final Ocm    rebuilt = new ParserBuilder().buildOcmParser().parseMessage(source2);
522         validateOCM2XML(rebuilt);
523 
524     }
525 
526     private void validateOCM2XML(final Ocm file) {
527 
528         // Check Header Block;
529         Assertions.assertEquals(3.0, file.getHeader().getFormatVersion(), 1.0e-10);
530         Assertions.assertEquals("ODM V.3 Example G-2",
531                             file.getHeader().getComments().get(0));
532         Assertions.assertEquals("OCM example with space object characteristics and perturbations.",
533                             file.getHeader().getComments().get(1));
534         Assertions.assertEquals("This OCM reflects the latest conditions post-maneuver A67Z",
535                             file.getHeader().getComments().get(2));
536         Assertions.assertEquals("This example shows the specification of multiple comment lines",
537                             file.getHeader().getComments().get(3));
538         Assertions.assertEquals(new AbsoluteDate(1998, 11, 6, 9, 23, 57, TimeScalesFactory.getUTC()),
539                             file.getHeader().getCreationDate());
540         Assertions.assertEquals("JAXA", file.getHeader().getOriginator());
541         Assertions.assertEquals("OCM 201113719185", file.getHeader().getMessageId());
542 
543         // Check metadata
544         Assertions.assertNull(file.getMetadata().getObjectName());
545         Assertions.assertNull(file.getMetadata().getObjectDesignator());
546         Assertions.assertEquals("1998-999A",                           file.getMetadata().getInternationalDesignator());
547         Assertions.assertEquals("R. Rabbit",                           file.getMetadata().getOriginatorPOC());
548         Assertions.assertEquals("Flight Dynamics Mission Design Lead", file.getMetadata().getOriginatorPosition());
549         Assertions.assertEquals("(719)555-1234",                       file.getMetadata().getOriginatorPhone());
550         Assertions.assertEquals("Mr. Rodgers",                         file.getMetadata().getTechPOC());
551         Assertions.assertEquals("(719)555-1234",                       file.getMetadata().getTechPhone());
552         Assertions.assertEquals("email@email.XXX",                     file.getMetadata().getTechAddress());
553         Assertions.assertEquals(TimeSystem.UT1, file.getMetadata().getTimeSystem());
554         TimeScale ts = DataContext.getDefault().getTimeScales().getUT1(IERSConventions.IERS_2010, false);
555         Assertions.assertEquals(0.0,
556                             file.getMetadata().getEpochT0().durationFrom(new AbsoluteDate(1998, 12, 18, ts)),
557                             1.0e-10);
558         Assertions.assertEquals(36.0,                                  file.getMetadata().getTaimutcT0(), 1.0e-15);
559         Assertions.assertEquals(0.357,                                 file.getMetadata().getUt1mutcT0(), 1.0e-15);
560 
561         // check trajectory data
562         Assertions.assertEquals(1, file.getData().getTrajectoryBlocks().size());
563         final TrajectoryStateHistory orb = file.getData().getTrajectoryBlocks().get(0);
564         Assertions.assertEquals(2, orb.getMetadata().getComments().size());
565         Assertions.assertEquals("GEOCENTRIC, CARTESIAN, EARTH FIXED", orb.getMetadata().getComments().get(0));
566         Assertions.assertEquals("THIS IS MY SECOND COMMENT LINE",     orb.getMetadata().getComments().get(1));
567         Assertions.assertEquals("PREDICTED", orb.getMetadata().getTrajBasis());
568         Assertions.assertEquals("EFG", orb.getMetadata().getTrajReferenceFrame().getName());
569         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asFrame());
570         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asCelestialBodyFrame());
571         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asOrbitRelativeFrame());
572         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asSpacecraftBodyFrame());
573         Assertions.assertEquals(OrbitElementsType.CARTPVA, orb.getMetadata().getTrajType());
574         Assertions.assertNull(orb.getMetadata().getTrajUnits());
575         Assertions.assertEquals(1, orb.getTrajectoryStates().size());
576         Assertions.assertEquals(new AbsoluteDate(1998, 12, 18, 0, 0, 0.0, ts),
577                             orb.getTrajectoryStates().get(0).getDate());
578         Assertions.assertEquals( 2854500.0, orb.getTrajectoryStates().get(0).getElements()[0], 1.0e-10);
579         Assertions.assertEquals(-2916200.0, orb.getTrajectoryStates().get(0).getElements()[1], 1.0e-10);
580         Assertions.assertEquals(-5360700.0, orb.getTrajectoryStates().get(0).getElements()[2], 1.0e-10);
581         Assertions.assertEquals(    5900.0, orb.getTrajectoryStates().get(0).getElements()[3], 1.0e-10);
582         Assertions.assertEquals(    4860.0, orb.getTrajectoryStates().get(0).getElements()[4], 1.0e-10);
583         Assertions.assertEquals(     520.0, orb.getTrajectoryStates().get(0).getElements()[5], 1.0e-10);
584         Assertions.assertEquals(       3.7, orb.getTrajectoryStates().get(0).getElements()[6], 1.0e-10);
585         Assertions.assertEquals(      -3.8, orb.getTrajectoryStates().get(0).getElements()[7], 1.0e-10);
586         Assertions.assertEquals(      -7.0, orb.getTrajectoryStates().get(0).getElements()[8], 1.0e-10);
587 
588         // check physical data
589         OrbitPhysicalProperties phys = file.getData().getPhysicBlock();
590         Assertions.assertEquals(1, phys.getComments().size());
591         Assertions.assertEquals("Spacecraft Physical Characteristics", phys.getComments().get(0));
592         Assertions.assertEquals(100.0,   phys.getWetMass(),                  1.0e-10);
593         Assertions.assertEquals(0.03123, phys.getOebQ().getQ1(),             1.0e-10);
594         Assertions.assertEquals(0.78543, phys.getOebQ().getQ2(),             1.0e-10);
595         Assertions.assertEquals(0.39158, phys.getOebQ().getQ3(),             1.0e-10);
596         Assertions.assertEquals(0.47832, phys.getOebQ().getQ0(),             1.0e-10);
597         Assertions.assertEquals(2.0,     phys.getOebMax(),                   1.0e-10);
598         Assertions.assertEquals(1.0,     phys.getOebIntermediate(),          1.0e-10);
599         Assertions.assertEquals(0.5,     phys.getOebMin(),                   1.0e-10);
600         Assertions.assertEquals(0.15,    phys.getOebAreaAlongMax(),          1.0e-10);
601         Assertions.assertEquals(0.30,    phys.getOebAreaAlongIntermediate(), 1.0e-10);
602         Assertions.assertEquals(0.50,    phys.getOebAreaAlongMin(),          1.0e-10);
603 
604         // check no covariance
605         Assertions.assertNull(file.getData().getCovarianceBlocks());
606 
607         // check no maneuvers
608         Assertions.assertNull(file.getData().getManeuverBlocks());
609 
610         // check perturbation data
611         Perturbations perts = file.getData().getPerturbationsBlock();
612         Assertions.assertEquals(1, perts.getComments().size());
613         Assertions.assertEquals("Perturbations Specification", perts.getComments().get(0));
614         Assertions.assertEquals("NRLMSIS00", perts.getAtmosphericModel());
615         Assertions.assertEquals("EGM-96", perts.getGravityModel());
616         Assertions.assertEquals(36, perts.getGravityDegree());
617         Assertions.assertEquals(36, perts.getGravityOrder());
618         Assertions.assertEquals(36, perts.getGravityOrder());
619         Assertions.assertEquals(3.986004415e14, perts.getGm(), 1.0);
620         Assertions.assertEquals("MOON", perts.getNBodyPerturbations().get(0).getName());
621         Assertions.assertEquals("SUN",  perts.getNBodyPerturbations().get(1).getName());
622         Assertions.assertEquals( 12.0, Units.NANO_TESLA.fromSI(perts.getFixedGeomagneticKp()), 1.0e-10);
623         Assertions.assertEquals(105.0, Unit.SOLAR_FLUX_UNIT.fromSI(perts.getFixedF10P7()),     1.0e-10);
624         Assertions.assertEquals(120.0, Unit.SOLAR_FLUX_UNIT.fromSI(perts.getFixedF10P7Mean()), 1.0e-10);
625 
626         // check no orbit determination
627         Assertions.assertNull(file.getData().getOrbitDeterminationBlock());
628 
629         // check user data
630         UserDefined user = file.getData().getUserDefinedBlock();
631         Assertions.assertTrue(user.getComments().isEmpty());
632         Assertions.assertEquals(1, user.getParameters().size());
633         Assertions.assertEquals("WGS-84", user.getParameters().get("EARTH_MODEL"));
634 
635         Assertions.assertEquals(1, file.getSatellites().size());
636         Assertions.assertEquals("1998-999A", file.getSatellites().entrySet().iterator().next().getKey());
637     }
638 
639     @Test
640     public void testParseOCM3() {
641         final String   name  = "/ccsds/odm/ocm/OCMExample3.txt";
642         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
643         final Ocm file = new ParserBuilder().
644                              withMu(Constants.EIGEN5C_EARTH_MU).
645                              buildOcmParser().
646                              parse(source); // using EphemerisFileParser API here
647 
648         // Check Header Block;
649         TimeScale utc = TimeScalesFactory.getUTC();
650         Assertions.assertEquals(3.0, file.getHeader().getFormatVersion(), 1.0e-10);
651         Assertions.assertEquals(0, file.getMetadata().getComments().size());
652         Assertions.assertEquals(new AbsoluteDate(1998, 11, 6, 9, 23, 57, utc),
653                             file.getHeader().getCreationDate());
654 
655         final AbsoluteDate t0 = new AbsoluteDate(1998, 12, 18, 14, 28, new TimeOffset(15, TimeOffset.SECOND, 117200, TimeOffset.MICROSECOND), utc);
656         Assertions.assertEquals(t0, file.getMetadata().getEpochT0());
657         Assertions.assertEquals("UTC", file.getMetadata().getTimeSystem().name());
658 
659         // check trajectory data
660         Assertions.assertEquals(1, file.getData().getTrajectoryBlocks().size());
661         final TrajectoryStateHistory orb = file.getData().getTrajectoryBlocks().get(0);
662         Assertions.assertEquals(2, orb.getMetadata().getComments().size());
663         Assertions.assertEquals("ORBIT EPHEMERIS INCORPORATING DEPLOYMENTS AND MANEUVERS (BELOW)", orb.getMetadata().getComments().get(0));
664         Assertions.assertEquals("intervening data records omitted after DT=20.0",     orb.getMetadata().getComments().get(1));
665         // TRAJ_BASIS has no default in 502.0-B-3 (p. 6-16, Table 6-4)
666         Assertions.assertEquals(null, orb.getMetadata().getTrajBasis()); // not present in the file
667         Assertions.assertEquals("TOD", orb.getMetadata().getTrajReferenceFrame().getName());
668         Assertions.assertNotNull(orb.getMetadata().getTrajReferenceFrame().asFrame());
669         Assertions.assertEquals(CelestialBodyFrame.TOD, orb.getMetadata().getTrajReferenceFrame().asCelestialBodyFrame());
670         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asOrbitRelativeFrame());
671         Assertions.assertNull(orb.getMetadata().getTrajReferenceFrame().asSpacecraftBodyFrame());
672         Assertions.assertEquals(t0, orb.getMetadata().getTrajFrameEpoch());
673         Assertions.assertEquals(OrbitElementsType.CARTPVA, orb.getMetadata().getTrajType());
674         Assertions.assertEquals(9, orb.getMetadata().getTrajUnits().size());
675         Assertions.assertEquals("km",      orb.getMetadata().getTrajUnits().get(0).getName());
676         Assertions.assertEquals("km",      orb.getMetadata().getTrajUnits().get(1).getName());
677         Assertions.assertEquals("km",      orb.getMetadata().getTrajUnits().get(2).getName());
678         Assertions.assertEquals("km/s",    orb.getMetadata().getTrajUnits().get(3).getName());
679         Assertions.assertEquals("km/s",    orb.getMetadata().getTrajUnits().get(4).getName());
680         Assertions.assertEquals("km/s",    orb.getMetadata().getTrajUnits().get(5).getName());
681         Assertions.assertEquals("km/s**2", orb.getMetadata().getTrajUnits().get(6).getName());
682         Assertions.assertEquals("km/s**2", orb.getMetadata().getTrajUnits().get(7).getName());
683         Assertions.assertEquals("km/s**2", orb.getMetadata().getTrajUnits().get(8).getName());
684         Assertions.assertEquals(4, orb.getTrajectoryStates().size());
685         Assertions.assertEquals(       0.0,  orb.getTrajectoryStates().get(0).getDate().durationFrom(t0), 1.0e-10);
686         Assertions.assertEquals( 2789600.0,  orb.getTrajectoryStates().get(0).getElements()[0], 1.0e-10);
687         Assertions.assertEquals( -280000.0,  orb.getTrajectoryStates().get(0).getElements()[1], 1.0e-10);
688         Assertions.assertEquals(-1746800.0,  orb.getTrajectoryStates().get(0).getElements()[2], 1.0e-10);
689         Assertions.assertEquals(    4730.0,  orb.getTrajectoryStates().get(0).getElements()[3], 1.0e-10);
690         Assertions.assertEquals(   -2500.0,  orb.getTrajectoryStates().get(0).getElements()[4], 1.0e-10);
691         Assertions.assertEquals(   -1040.0,  orb.getTrajectoryStates().get(0).getElements()[5], 1.0e-10);
692         Assertions.assertEquals(       8.0,  orb.getTrajectoryStates().get(0).getElements()[6], 1.0e-10);
693         Assertions.assertEquals(       1.0,  orb.getTrajectoryStates().get(0).getElements()[7], 1.0e-10);
694         Assertions.assertEquals(    -159.0,  orb.getTrajectoryStates().get(0).getElements()[8], 1.0e-10);
695         Assertions.assertEquals(      10.0,  orb.getTrajectoryStates().get(1).getDate().durationFrom(t0), 1.0e-10);
696         Assertions.assertEquals( 2783400.0,  orb.getTrajectoryStates().get(1).getElements()[0], 1.0e-10);
697         Assertions.assertEquals( -308100.0,  orb.getTrajectoryStates().get(1).getElements()[1], 1.0e-10);
698         Assertions.assertEquals(-1877100.0,  orb.getTrajectoryStates().get(1).getElements()[2], 1.0e-10);
699         Assertions.assertEquals(    5190.0,  orb.getTrajectoryStates().get(1).getElements()[3], 1.0e-10);
700         Assertions.assertEquals(   -2420.0,  orb.getTrajectoryStates().get(1).getElements()[4], 1.0e-10);
701         Assertions.assertEquals(   -2000.0,  orb.getTrajectoryStates().get(1).getElements()[5], 1.0e-10);
702         Assertions.assertEquals(       8.0,  orb.getTrajectoryStates().get(1).getElements()[6], 1.0e-10);
703         Assertions.assertEquals(       1.0,  orb.getTrajectoryStates().get(1).getElements()[7], 1.0e-10);
704         Assertions.assertEquals(       1.0,  orb.getTrajectoryStates().get(1).getElements()[8], 1.0e-10);
705         Assertions.assertEquals(      20.0,  orb.getTrajectoryStates().get(2).getDate().durationFrom(t0), 1.0e-10);
706         Assertions.assertEquals( 2776000.0,  orb.getTrajectoryStates().get(2).getElements()[0], 1.0e-10);
707         Assertions.assertEquals( -336900.0,  orb.getTrajectoryStates().get(2).getElements()[1], 1.0e-10);
708         Assertions.assertEquals(-2008700.0,  orb.getTrajectoryStates().get(2).getElements()[2], 1.0e-10);
709         Assertions.assertEquals(    5640.0,  orb.getTrajectoryStates().get(2).getElements()[3], 1.0e-10);
710         Assertions.assertEquals(   -2340.0,  orb.getTrajectoryStates().get(2).getElements()[4], 1.0e-10);
711         Assertions.assertEquals(   -1950.0,  orb.getTrajectoryStates().get(2).getElements()[5], 1.0e-10);
712         Assertions.assertEquals(       8.0,  orb.getTrajectoryStates().get(2).getElements()[6], 1.0e-10);
713         Assertions.assertEquals(       1.0,  orb.getTrajectoryStates().get(2).getElements()[7], 1.0e-10);
714         Assertions.assertEquals(     159.0,  orb.getTrajectoryStates().get(2).getElements()[8], 1.0e-10);
715         Assertions.assertEquals(     500.0,  orb.getTrajectoryStates().get(3).getDate().durationFrom(t0), 1.0e-10);
716         Assertions.assertEquals( 2164375.0,  orb.getTrajectoryStates().get(3).getElements()[0], 1.0e-10);
717         Assertions.assertEquals( 1115811.0,  orb.getTrajectoryStates().get(3).getElements()[1], 1.0e-10);
718         Assertions.assertEquals( -688131.0,  orb.getTrajectoryStates().get(3).getElements()[2], 1.0e-10);
719         Assertions.assertEquals(   -3533.28, orb.getTrajectoryStates().get(3).getElements()[3], 1.0e-10);
720         Assertions.assertEquals(   -2884.52, orb.getTrajectoryStates().get(3).getElements()[4], 1.0e-10);
721         Assertions.assertEquals(     885.35, orb.getTrajectoryStates().get(3).getElements()[5], 1.0e-10);
722         Assertions.assertEquals(       0.0,  orb.getTrajectoryStates().get(3).getElements()[6], 1.0e-10);
723         Assertions.assertEquals(       0.0,  orb.getTrajectoryStates().get(3).getElements()[7], 1.0e-10);
724         Assertions.assertEquals(       0.0,  orb.getTrajectoryStates().get(3).getElements()[8], 1.0e-10);
725 
726         // check physical data
727         OrbitPhysicalProperties phys = file.getData().getPhysicBlock();
728         Assertions.assertEquals(1, phys.getComments().size());
729         Assertions.assertEquals("S/C Physical Characteristics:", phys.getComments().get(0));
730         Assertions.assertEquals(10.0,    phys.getDragConstantArea(),         1.0e-10);
731         Assertions.assertEquals(2.3,     phys.getDragCoefficient(),   1.0e-10);
732         Assertions.assertEquals(100.0,   phys.getWetMass(),                  1.0e-10);
733         Assertions.assertEquals(4.0,     phys.getSrpConstantArea(),          1.0e-10);
734         Assertions.assertEquals(1.3,     phys.getSrpCoefficient(),    1.0e-10);
735 
736         // check no covariance
737         Assertions.assertNull(file.getData().getCovarianceBlocks());
738 
739         // check maneuvers
740         List<OrbitManeuverHistory> man = file.getData().getManeuverBlocks();
741         Assertions.assertEquals(2, man.size());
742 
743         Assertions.assertEquals(2, man.get(0).getMetadata().getComments().size());
744         Assertions.assertEquals("Ten 1kg objects deployed from 200kg host over 100 s timespan", man.get(0).getMetadata().getComments().get(0));
745         Assertions.assertEquals("20 deg off of back-track direction", man.get(0).getMetadata().getComments().get(1));
746         Assertions.assertEquals("CUBESAT_DEPLOY", man.get(0).getMetadata().getManID());
747         Assertions.assertEquals(ManBasis.CANDIDATE, man.get(0).getMetadata().getManBasis());
748         Assertions.assertEquals("DEPLOY",           man.get(0).getMetadata().getManDeviceID());
749         Assertions.assertEquals(1,                  man.get(0).getMetadata().getManPurpose().size());
750         Assertions.assertEquals("DEPLOY",           man.get(0).getMetadata().getManPurpose().get(0));
751         Assertions.assertEquals("RSW_ROTATING",     man.get(0).getMetadata().getManReferenceFrame().getName());
752         Assertions.assertNull(man.get(0).getMetadata().getManReferenceFrame().asFrame());
753         Assertions.assertNull(man.get(0).getMetadata().getManReferenceFrame().asCelestialBodyFrame());
754         Assertions.assertEquals(OrbitRelativeFrame.RSW_ROTATING, man.get(0).getMetadata().getManReferenceFrame().asOrbitRelativeFrame());
755         Assertions.assertNull(man.get(0).getMetadata().getManReferenceFrame().asSpacecraftBodyFrame());
756         Assertions.assertEquals(9, man.get(0).getMetadata().getManComposition().size());
757         Assertions.assertEquals(ManeuverFieldType.TIME_RELATIVE,   man.get(0).getMetadata().getManComposition().get(0));
758         Assertions.assertEquals(ManeuverFieldType.DEPLOY_ID,       man.get(0).getMetadata().getManComposition().get(1));
759         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_X,     man.get(0).getMetadata().getManComposition().get(2));
760         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_Y,     man.get(0).getMetadata().getManComposition().get(3));
761         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_Z,     man.get(0).getMetadata().getManComposition().get(4));
762         Assertions.assertEquals(ManeuverFieldType.DEPLOY_MASS,     man.get(0).getMetadata().getManComposition().get(5));
763         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_SIGMA, man.get(0).getMetadata().getManComposition().get(6));
764         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_RATIO, man.get(0).getMetadata().getManComposition().get(7));
765         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_CDA,   man.get(0).getMetadata().getManComposition().get(8));
766         Assertions.assertEquals(8, man.get(0).getMetadata().getManUnits().size());
767         Assertions.assertEquals("n/a",  man.get(0).getMetadata().getManUnits().get(0).getName());
768         Assertions.assertEquals("km/s", man.get(0).getMetadata().getManUnits().get(1).getName());
769         Assertions.assertEquals("km/s", man.get(0).getMetadata().getManUnits().get(2).getName());
770         Assertions.assertEquals("km/s", man.get(0).getMetadata().getManUnits().get(3).getName());
771         Assertions.assertEquals("kg",   man.get(0).getMetadata().getManUnits().get(4).getName());
772         Assertions.assertEquals("%",    man.get(0).getMetadata().getManUnits().get(5).getName());
773         Assertions.assertEquals("n/a",  man.get(0).getMetadata().getManUnits().get(6).getName());
774         Assertions.assertEquals("m**2", man.get(0).getMetadata().getManUnits().get(7).getName());
775         Assertions.assertEquals(10, man.get(0).getManeuvers().size());
776         Assertions.assertEquals(500.0,        man.get(0).getManeuvers().get(0).getDate().durationFrom(t0), 1.0e-10);
777         Assertions.assertEquals("CUBESAT_10", man.get(0).getManeuvers().get(0).getDeployId());
778         Assertions.assertEquals( 2.8773E-1,   man.get(0).getManeuvers().get(0).getDeployDv().getX(), 1.0e-10);
779         Assertions.assertEquals(-9.3969E-1,   man.get(0).getManeuvers().get(0).getDeployDv().getY(), 1.0e-10);
780         Assertions.assertEquals( 1.8491E-1,   man.get(0).getManeuvers().get(0).getDeployDv().getZ(), 1.0e-10);
781         Assertions.assertEquals(-1.0,         man.get(0).getManeuvers().get(0).getDeployMass(), 1.0e-10);
782         Assertions.assertEquals( 0.05,        man.get(0).getManeuvers().get(0).getDeployDvSigma(), 1.0e-10);
783         Assertions.assertEquals(-0.005025,    man.get(0).getManeuvers().get(0).getDeployDvRatio(), 1.0e-10);
784         Assertions.assertEquals( 0.033,       man.get(0).getManeuvers().get(0).getDeployDvCda(), 1.0e-10);
785         Assertions.assertEquals(510.0,        man.get(0).getManeuvers().get(1).getDate().durationFrom(t0), 1.0e-10);
786         Assertions.assertEquals("CUBESAT_11", man.get(0).getManeuvers().get(1).getDeployId());
787         Assertions.assertEquals( 1.4208E-1,   man.get(0).getManeuvers().get(1).getDeployDv().getX(), 1.0e-10);
788         Assertions.assertEquals(-9.3969E-1,   man.get(0).getManeuvers().get(1).getDeployDv().getY(), 1.0e-10);
789         Assertions.assertEquals( 3.1111E-1,   man.get(0).getManeuvers().get(1).getDeployDv().getZ(), 1.0e-10);
790         Assertions.assertEquals(-1.0,         man.get(0).getManeuvers().get(1).getDeployMass(), 1.0e-10);
791         Assertions.assertEquals( 0.05,        man.get(0).getManeuvers().get(1).getDeployDvSigma(), 1.0e-10);
792         Assertions.assertEquals(-0.005051,    man.get(0).getManeuvers().get(1).getDeployDvRatio(), 1.0e-10);
793         Assertions.assertEquals( 0.033,       man.get(0).getManeuvers().get(1).getDeployDvCda(), 1.0e-10);
794 
795         Assertions.assertEquals(1, man.get(1).getMetadata().getComments().size());
796         Assertions.assertEquals("100 s of 0.5N +in-track thrust w/effic η=0.95, Isp=300s, 5% 1-sigma error", man.get(1).getMetadata().getComments().get(0));
797         Assertions.assertEquals("E_W_20160305B",    man.get(1).getMetadata().getManID());
798         Assertions.assertEquals(ManBasis.CANDIDATE, man.get(1).getMetadata().getManBasis());
799         Assertions.assertEquals("THR_01",           man.get(1).getMetadata().getManDeviceID());
800         Assertions.assertEquals(1,                  man.get(1).getMetadata().getManPurpose().size());
801         Assertions.assertEquals("ORBIT",            man.get(1).getMetadata().getManPurpose().get(0));
802         Assertions.assertEquals("RSW_ROTATING",     man.get(1).getMetadata().getManReferenceFrame().getName());
803         Assertions.assertNull(man.get(1).getMetadata().getManReferenceFrame().asFrame());
804         Assertions.assertNull(man.get(1).getMetadata().getManReferenceFrame().asCelestialBodyFrame());
805         Assertions.assertEquals(OrbitRelativeFrame.RSW_ROTATING, man.get(1).getMetadata().getManReferenceFrame().asOrbitRelativeFrame());
806         Assertions.assertEquals(11,                              man.get(1).getMetadata().getManComposition().size());
807         Assertions.assertEquals(ManeuverFieldType.TIME_ABSOLUTE, man.get(1).getMetadata().getManComposition().get( 0));
808         Assertions.assertEquals(ManeuverFieldType.TIME_RELATIVE, man.get(1).getMetadata().getManComposition().get( 1));
809         Assertions.assertEquals(ManeuverFieldType.MAN_DURA,      man.get(1).getMetadata().getManComposition().get( 2));
810         Assertions.assertEquals(ManeuverFieldType.THR_X,         man.get(1).getMetadata().getManComposition().get( 3));
811         Assertions.assertEquals(ManeuverFieldType.THR_Y,         man.get(1).getMetadata().getManComposition().get( 4));
812         Assertions.assertEquals(ManeuverFieldType.THR_Z,         man.get(1).getMetadata().getManComposition().get( 5));
813         Assertions.assertEquals(ManeuverFieldType.THR_MAG_SIGMA, man.get(1).getMetadata().getManComposition().get( 6));
814         Assertions.assertEquals(ManeuverFieldType.THR_DIR_SIGMA, man.get(1).getMetadata().getManComposition().get( 7));
815         Assertions.assertEquals(ManeuverFieldType.THR_INTERP,    man.get(1).getMetadata().getManComposition().get( 8));
816         Assertions.assertEquals(ManeuverFieldType.THR_ISP,       man.get(1).getMetadata().getManComposition().get( 9));
817         Assertions.assertEquals(ManeuverFieldType.THR_EFFIC,     man.get(1).getMetadata().getManComposition().get(10));
818         Assertions.assertEquals(9, man.get(1).getMetadata().getManUnits().size());
819         Assertions.assertEquals("s",    man.get(1).getMetadata().getManUnits().get(0).getName());
820         Assertions.assertEquals("N",    man.get(1).getMetadata().getManUnits().get(1).getName());
821         Assertions.assertEquals("N",    man.get(1).getMetadata().getManUnits().get(2).getName());
822         Assertions.assertEquals("N",    man.get(1).getMetadata().getManUnits().get(3).getName());
823         Assertions.assertEquals("%",    man.get(1).getMetadata().getManUnits().get(4).getName());
824         Assertions.assertEquals("deg",  man.get(1).getMetadata().getManUnits().get(5).getName());
825         Assertions.assertEquals("n/a",  man.get(1).getMetadata().getManUnits().get(6).getName());
826         Assertions.assertEquals("s",    man.get(1).getMetadata().getManUnits().get(7).getName());
827         Assertions.assertEquals("n/a",  man.get(1).getMetadata().getManUnits().get(8).getName());
828         Assertions.assertEquals(1,      man.get(1).getManeuvers().size());
829         Assertions.assertEquals(500.0,        man.get(1).getManeuvers().get(0).getDate().durationFrom(t0), 1.0e-10);
830         Assertions.assertEquals(100,          man.get(1).getManeuvers().get(0).getDuration(),         1.0e-10);
831         Assertions.assertEquals(  0.0,        man.get(1).getManeuvers().get(0).getThrust().getX(),    1.0e-10);
832         Assertions.assertEquals(  0.5,        man.get(1).getManeuvers().get(0).getThrust().getY(),    1.0e-10);
833         Assertions.assertEquals( 0.05,        man.get(1).getManeuvers().get(0).getThrustMagnitudeSigma(), 1.0e-10);
834         Assertions.assertEquals( 1.0,         FastMath.toDegrees(man.get(1).getManeuvers().get(0).getThrustDirectionSigma()), 1.0e-10);
835         Assertions.assertEquals(OnOff.ON,     man.get(1).getManeuvers().get(0).getThrustInterpolation());
836         Assertions.assertTrue(man.get(1).getManeuvers().get(0).getThrustInterpolation().isOn());
837         Assertions.assertEquals(300.0,        man.get(1).getManeuvers().get(0).getThrustIsp(),        1.0e-10);
838         Assertions.assertEquals(0.95,         man.get(1).getManeuvers().get(0).getThrustEfficiency(), 1.0e-10);
839 
840         // check perturbation data
841         Perturbations perts = file.getData().getPerturbationsBlock();
842         Assertions.assertEquals(1, perts.getComments().size());
843         Assertions.assertEquals("Perturbations specification", perts.getComments().get(0));
844         Assertions.assertEquals(3.986004415e14, perts.getGm(),     1.0);
845 
846         // check orbit determination
847         OrbitDetermination od = file.getData().getOrbitDeterminationBlock();
848         Assertions.assertEquals(1, od.getComments().size());
849         Assertions.assertEquals("Orbit Determination information", od.getComments().get(0));
850         Assertions.assertEquals("OOD #10059",    od.getId());
851         Assertions.assertEquals("OOD #10058",    od.getPrevId());
852         Assertions.assertEquals(OdMethodType.SF, od.getMethod().getType());
853         Assertions.assertEquals("ODTK",          od.getMethod().getTool());
854         Assertions.assertEquals(new AbsoluteDate(2001, 11, 6, 11, 17, 33.0, utc), od.getEpoch());
855         Assertions.assertEquals(273, od.getObsUsed());
856         Assertions.assertEquals( 91, od.getTracksUsed());
857 
858         // check no user data
859         Assertions.assertNull(file.getData().getUserDefinedBlock());
860 
861     }
862 
863     @Test
864     public void testParseOCM4() {
865         final String   name  = "/ccsds/odm/ocm/OCMExample4.txt";
866         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
867         final Ocm file = new ParserBuilder().
868                              withMu(Constants.IERS2003_EARTH_MU).
869                              buildOcmParser().
870                              parseMessage(source);
871 
872         // Check Header Block;
873         Assertions.assertEquals(3.0, file.getHeader().getFormatVersion(), 1.0e-10);
874         Assertions.assertEquals(2, file.getHeader().getComments().size());
875         Assertions.assertEquals("This file is a dummy example with inconsistent data", file.getHeader().getComments().get(0));
876         Assertions.assertEquals("it is used to exercise all possible keys in Key-Value Notation", file.getHeader().getComments().get(1));
877         Assertions.assertEquals("dummy-classification",                file.getHeader().getClassification());
878         Assertions.assertEquals(new AbsoluteDate(2019, 7, 23, 10, 29, new TimeOffset(31L, 576000000000000000L), TimeScalesFactory.getUTC()),
879                                 file.getHeader().getCreationDate());
880         Assertions.assertEquals("JPL",                                 file.getHeader().getOriginator());
881         Assertions.assertEquals("ABC-12_34",                           file.getHeader().getMessageId());
882 
883         // Check metadata
884         Assertions.assertEquals(1,                                                    file.getMetadata().getComments().size());
885         Assertions.assertEquals("Metadata comment",                                   file.getMetadata().getComments().get(0));
886         Assertions.assertEquals("POLYSAT",                                            file.getMetadata().getObjectName());
887         Assertions.assertEquals(3,                                                    file.getMetadata().getAlternateNames().size());
888         Assertions.assertEquals("ALTERNATE",                                          file.getMetadata().getAlternateNames().get(0));
889         Assertions.assertEquals("OTHER",                                              file.getMetadata().getAlternateNames().get(1));
890         Assertions.assertEquals("RELATED",                                            file.getMetadata().getAlternateNames().get(2));
891         Assertions.assertEquals("18SPCS 18571",                                       file.getMetadata().getObjectDesignator());
892         Assertions.assertEquals("2000-053A",                                          file.getMetadata().getInternationalDesignator());
893         Assertions.assertEquals("Mr. Rodgers",                                        file.getMetadata().getOriginatorPOC());
894         Assertions.assertEquals("Flight Dynamics Mission Design Lead",                file.getMetadata().getOriginatorPosition());
895         Assertions.assertEquals("+12345678901",                                       file.getMetadata().getOriginatorPhone());
896         Assertions.assertEquals("JOHN.DOE@EXAMPLE.ORG",                               file.getMetadata().getOriginatorEmail());
897         Assertions.assertEquals("5040 Spaceflight Ave., Cocoa Beach, FL, USA, 12345", file.getMetadata().getOriginatorAddress());
898         Assertions.assertEquals("NASA",                                                file.getMetadata().getTechOrg());
899         Assertions.assertEquals("Maxwell Smart",                                       file.getMetadata().getTechPOC());
900         Assertions.assertEquals("+98765432109",                                        file.getMetadata().getTechPhone());
901         Assertions.assertEquals("MAX@EXAMPLE.ORG",                                     file.getMetadata().getTechEmail());
902         Assertions.assertEquals("34 Orekit avenue, Earth",                             file.getMetadata().getTechAddress());
903         Assertions.assertEquals("ABC-12_33",                                           file.getMetadata().getPreviousMessageID());
904         Assertions.assertEquals("ABC-12_35",                                           file.getMetadata().getNextMessageID());
905         Assertions.assertEquals("ADM_MSG_35132.TXT",                                   file.getMetadata().getAdmMessageLink());
906         Assertions.assertEquals("CDM_MSG_35132.TXT",                                   file.getMetadata().getCdmMessageLink());
907         Assertions.assertEquals("PRM_MSG_35132.TXT",                                   file.getMetadata().getPrmMessageLink());
908         Assertions.assertEquals("RDM_MSG_35132.TXT",                                   file.getMetadata().getRdmMessageLink());
909         Assertions.assertEquals("COMSPOC",                                             file.getMetadata().getCatalogName());
910         Assertions.assertEquals("INTELSAT",                                            file.getMetadata().getOperator());
911         Assertions.assertEquals("SIRIUS",                                              file.getMetadata().getOwner());
912         Assertions.assertEquals("FRANCE",                                              file.getMetadata().getCountry());
913         Assertions.assertEquals("SPIRE",                                               file.getMetadata().getConstellation());
914         Assertions.assertEquals("PAYLOAD",                                             file.getMetadata().getObjectType().toString());
915         Assertions.assertEquals("Operational",                                         file.getMetadata().getOpsStatus().toString());
916         Assertions.assertEquals("Extended Geostationary Orbit",                        file.getMetadata().getOrbitCategory().toString());
917         Assertions.assertEquals(7,                                                     file.getMetadata().getOcmDataElements().size());
918         Assertions.assertEquals(OcmElements.ORB,                                       file.getMetadata().getOcmDataElements().get(0));
919         Assertions.assertEquals(OcmElements.PHYS,                                      file.getMetadata().getOcmDataElements().get(1));
920         Assertions.assertEquals(OcmElements.COV,                                       file.getMetadata().getOcmDataElements().get(2));
921         Assertions.assertEquals(OcmElements.MAN,                                       file.getMetadata().getOcmDataElements().get(3));
922         Assertions.assertEquals(OcmElements.PERT,                                      file.getMetadata().getOcmDataElements().get(4));
923         Assertions.assertEquals(OcmElements.OD,                                        file.getMetadata().getOcmDataElements().get(5));
924         Assertions.assertEquals(OcmElements.USER,                                      file.getMetadata().getOcmDataElements().get(6));
925         Assertions.assertEquals("UTC",                                                 file.getMetadata().getTimeSystem().name());
926         final AbsoluteDate epoch = file.getMetadata().getEpochT0();
927         Assertions.assertEquals(new AbsoluteDate(2019, 7, 23,  0, 0, 0.0, TimeScalesFactory.getUTC()), epoch);
928         Assertions.assertEquals(28800.0, file.getMetadata().getSclkOffsetAtEpoch(), 1.0e-10);
929         Assertions.assertEquals(2.5,     file.getMetadata().getSclkSecPerSISec(), 1.0e-15);
930         Assertions.assertEquals(new AbsoluteDate(2019, 7, 23,  9, 29,
931                                                  new TimeOffset(31, TimeOffset.SECOND, 576, TimeOffset.MILLISECOND),
932                                                  TimeScalesFactory.getUTC()),
933                                 file.getMetadata().getPreviousMessageEpoch());
934         Assertions.assertEquals(new AbsoluteDate(2019, 7, 23, 11, 29,
935                                                  new TimeOffset(31, TimeOffset.SECOND, 576, TimeOffset.MILLISECOND),
936                                                  TimeScalesFactory.getUTC()),
937                                 file.getMetadata().getNextMessageEpoch());
938         Assertions.assertEquals(new AbsoluteDate(2019, 7, 23,  9, 30,  0.0, TimeScalesFactory.getUTC()),
939                                 file.getMetadata().getStartTime());
940         Assertions.assertEquals(new AbsoluteDate(2019, 7, 23, 10, 29, 50.0, TimeScalesFactory.getUTC()),
941                                 file.getMetadata().getStopTime());
942         Assertions.assertEquals(0.041550925925 * Constants.JULIAN_DAY, file.getMetadata().getTimeSpan(), 1.0e-15);
943         Assertions.assertEquals(37.0,                                  file.getMetadata().getTaimutcT0(), 1.0e-15);
944         Assertions.assertEquals(new AbsoluteDate(2050, 12, 31, 23, 59, 60.0, TimeScalesFactory.getUTC()),
945                                 file.getMetadata().getNextLeapEpoch());
946         Assertions.assertEquals(38.0,                                  file.getMetadata().getNextLeapTaimutc(), 1.0e-15);
947         Assertions.assertEquals(-0.1642060,                            file.getMetadata().getUt1mutcT0(), 1.0e-15);
948         Assertions.assertEquals("IERS",                                file.getMetadata().getEopSource());
949         Assertions.assertEquals("LAGRANGE ORDER 5",                    file.getMetadata().getInterpMethodEOP());
950         Assertions.assertEquals("JPL_DE_430",                          file.getMetadata().getCelestialSource());
951 
952         // check trajectory data
953         Assertions.assertEquals(3, file.getData().getTrajectoryBlocks().size());
954         TrajectoryStateHistory osh0 = file.getData().getTrajectoryBlocks().get(0);
955         Assertions.assertEquals("this is number 1 ORB comment", osh0.getMetadata().getComments().get(0));
956         Assertions.assertEquals("orbit 1",       osh0.getMetadata().getTrajID());
957         Assertions.assertEquals("orbit 0",       osh0.getMetadata().getTrajPrevID());
958         Assertions.assertEquals("orbit 2",       osh0.getMetadata().getTrajNextID());
959         Assertions.assertEquals("DETERMINED_OD", osh0.getMetadata().getTrajBasis());
960         Assertions.assertEquals("OD_17",         osh0.getMetadata().getTrajBasisID());
961         Assertions.assertEquals(InterpolationMethod.HERMITE, osh0.getMetadata().getInterpolationMethod());
962         Assertions.assertEquals(3, osh0.getMetadata().getInterpolationDegree());
963         Assertions.assertEquals("Orekit",        osh0.getMetadata().getPropagator());
964         Assertions.assertEquals(CenterName.EARTH.name(), osh0.getMetadata().getCenter().getName());
965         Assertions.assertEquals(CelestialBodyFrame.TOD, osh0.getMetadata().getTrajReferenceFrame().asCelestialBodyFrame());
966         Assertions.assertEquals(    0.0,   osh0.getMetadata().getTrajFrameEpoch().durationFrom(epoch),    1.0e-12);
967         Assertions.assertEquals(34200.0,   osh0.getMetadata().getUseableStartTime().durationFrom(epoch), 1.0e-12);
968         Assertions.assertEquals(35999.999, osh0.getMetadata().getUseableStopTime().durationFrom(epoch),  1.0e-12);
969         Assertions.assertEquals(17, osh0.getMetadata().getOrbRevNum());
970         Assertions.assertEquals( 1, osh0.getMetadata().getOrbRevNumBasis());
971         Assertions.assertEquals(OrbitElementsType.CARTPVA, osh0.getMetadata().getTrajType());
972         Assertions.assertEquals(9, osh0.getMetadata().getTrajUnits().size());
973         Assertions.assertEquals(Unit.KILOMETRE,  osh0.getMetadata().getTrajUnits().get(0));
974         Assertions.assertEquals(Unit.KILOMETRE,  osh0.getMetadata().getTrajUnits().get(1));
975         Assertions.assertEquals(Unit.KILOMETRE,  osh0.getMetadata().getTrajUnits().get(2));
976         Assertions.assertEquals(Units.KM_PER_S,  osh0.getMetadata().getTrajUnits().get(3));
977         Assertions.assertEquals(Units.KM_PER_S,  osh0.getMetadata().getTrajUnits().get(4));
978         Assertions.assertEquals(Units.KM_PER_S,  osh0.getMetadata().getTrajUnits().get(5));
979         Assertions.assertEquals(Units.KM_PER_S2, osh0.getMetadata().getTrajUnits().get(6));
980         Assertions.assertEquals(Units.KM_PER_S2, osh0.getMetadata().getTrajUnits().get(7));
981         Assertions.assertEquals(Units.KM_PER_S2, osh0.getMetadata().getTrajUnits().get(8));
982         Assertions.assertEquals(3, osh0.getCoordinates().size());
983         Assertions.assertEquals(   0.0, osh0.getCoordinates().get(0).getDate().durationFrom(epoch), 1.0e-10);
984         Assertions.assertEquals( 1.0e6, osh0.getCoordinates().get(0).getPosition().getX(), 1.0e-10);
985         Assertions.assertEquals( 300.0, osh0.getCoordinates().get(1).getDate().durationFrom(epoch), 1.0e-10);
986         Assertions.assertEquals( 3.0e3, osh0.getCoordinates().get(1).getVelocity().getY(), 1.0e-10);
987         Assertions.assertEquals( 600.0, osh0.getCoordinates().get(2).getDate().durationFrom(epoch), 1.0e-10);
988         Assertions.assertEquals(  -6.0, osh0.getCoordinates().get(2).getAcceleration().getZ(), 1.0e-10);
989         TrajectoryStateHistory osh1 = file.getData().getTrajectoryBlocks().get(1);
990         Assertions.assertEquals("this is number 2 ORB comment", osh1.getMetadata().getComments().get(0));
991         Assertions.assertEquals("orbit 2",    osh1.getMetadata().getTrajID());
992         Assertions.assertEquals("orbit 1",    osh1.getMetadata().getTrajPrevID());
993         Assertions.assertEquals("orbit 3",    osh1.getMetadata().getTrajNextID());
994         Assertions.assertEquals("PREDICTED",  osh1.getMetadata().getTrajBasis());
995         Assertions.assertEquals("SIMULATION", osh1.getMetadata().getTrajBasisID());
996         Assertions.assertEquals(-1,           osh1.getMetadata().getOrbRevNum());
997         Assertions.assertEquals(-1,           osh1.getMetadata().getOrbRevNumBasis());
998         Assertions.assertEquals(3, osh1.getCoordinates().size());
999         Assertions.assertEquals(1800.0, osh1.getCoordinates().get(0).getDate().durationFrom(epoch), 1.0e-10);
1000         Assertions.assertEquals(2100.0, osh1.getCoordinates().get(1).getDate().durationFrom(epoch), 1.0e-10);
1001         Assertions.assertEquals(2400.0, osh1.getCoordinates().get(2).getDate().durationFrom(epoch), 1.0e-10);
1002         TrajectoryStateHistory osh2 = file.getData().getTrajectoryBlocks().get(2);
1003         Assertions.assertEquals("this is number 3 ORB comment", osh2.getMetadata().getComments().get(0));
1004         Assertions.assertEquals("orbit 3",    osh2.getMetadata().getTrajID());
1005         Assertions.assertEquals("orbit 2",    osh2.getMetadata().getTrajPrevID());
1006         Assertions.assertEquals("orbit 4",    osh2.getMetadata().getTrajNextID());
1007         Assertions.assertEquals("SIMULATED",  osh2.getMetadata().getTrajBasis());
1008         Assertions.assertEquals("ce6898a2-db5f-11ec-8d7c-03ee8546e2d3", osh2.getMetadata().getTrajBasisID());
1009         Assertions.assertEquals(-1,           osh2.getMetadata().getOrbRevNum());
1010         Assertions.assertEquals(-1,           osh2.getMetadata().getOrbRevNumBasis());
1011         Assertions.assertEquals("OSCULATING", osh2.getMetadata().getOrbAveraging());
1012         Assertions.assertEquals(3, osh2.getCoordinates().size());
1013         Assertions.assertEquals(2800.0, osh2.getCoordinates().get(0).getDate().durationFrom(epoch), 1.0e-10);
1014         Assertions.assertEquals(3100.0, osh2.getCoordinates().get(1).getDate().durationFrom(epoch), 1.0e-10);
1015         Assertions.assertEquals(3400.0, osh2.getCoordinates().get(2).getDate().durationFrom(epoch), 1.0e-10);
1016 
1017         // check physical data
1018         OrbitPhysicalProperties phys = file.getData().getPhysicBlock();
1019         Assertions.assertEquals("this is PHYS comment", phys.getComments().get(0));
1020         Assertions.assertEquals("AIRBUS",   phys.getManufacturer());
1021         Assertions.assertEquals("EUROSTAR", phys.getBusModel());
1022         Assertions.assertEquals(3,          phys.getDockedWith().size());
1023         Assertions.assertEquals("A1",       phys.getDockedWith().get(0));
1024         Assertions.assertEquals("A2",       phys.getDockedWith().get(1));
1025         Assertions.assertEquals("A3",       phys.getDockedWith().get(2));
1026         Assertions.assertEquals(5.0,        phys.getDragConstantArea(),               1.0e-10);
1027         Assertions.assertEquals(2.1,        phys.getDragCoefficient(),                1.0e-10);
1028         Assertions.assertEquals(0.1,        phys.getDragUncertainty(),                1.0e-10);
1029         Assertions.assertEquals(700.0,      phys.getInitialWetMass(),                 1.0e-10);
1030         Assertions.assertEquals(600.0,      phys.getWetMass(),                        1.0e-10);
1031         Assertions.assertEquals(500.0,      phys.getDryMass(),                        1.0e-10);
1032         Assertions.assertNull(phys.getOebParentFrame().asOrbitRelativeFrame());
1033         Assertions.assertEquals("TOD",      phys.getOebParentFrame().getName());
1034         Assertions.assertEquals(32400.0,    phys.getOebParentFrameEpoch().durationFrom(epoch), 1.0e-10);
1035         Assertions.assertEquals(0.64,       phys.getOebQ().getQ1(),                   1.0e-10);
1036         Assertions.assertEquals(0.48,       phys.getOebQ().getQ2(),                   1.0e-10);
1037         Assertions.assertEquals(0.48,       phys.getOebQ().getQ3(),                   1.0e-10);
1038         Assertions.assertEquals(0.36,       phys.getOebQ().getQ0(),                   1.0e-10);
1039         Assertions.assertEquals(3.0,        phys.getOebMax(),                         1.0e-10);
1040         Assertions.assertEquals(2.0,        phys.getOebIntermediate(),                1.0e-10);
1041         Assertions.assertEquals(1.0,        phys.getOebMin(),                         1.0e-10);
1042         Assertions.assertEquals(2.2,        phys.getOebAreaAlongMax(),                1.0e-10);
1043         Assertions.assertEquals(3.2,        phys.getOebAreaAlongIntermediate(),       1.0e-10);
1044         Assertions.assertEquals(6.2,        phys.getOebAreaAlongMin(),                1.0e-10);
1045         Assertions.assertEquals(4.3,        phys.getMinAreaForCollisionProbability(), 1.0e-10);
1046         Assertions.assertEquals(6.3,        phys.getMaxAreaForCollisionProbability(), 1.0e-10);
1047         Assertions.assertEquals(5.3,        phys.getTypAreaForCollisionProbability(), 1.0e-10);
1048         Assertions.assertEquals(2.4,        phys.getRcs(),                            1.0e-10);
1049         Assertions.assertEquals(1.4,        phys.getMinRcs(),                         1.0e-10);
1050         Assertions.assertEquals(3.4,        phys.getMaxRcs(),                         1.0e-10);
1051         Assertions.assertEquals(3.5,        phys.getSrpConstantArea(),                1.0e-10);
1052         Assertions.assertEquals(1.7,        phys.getSrpCoefficient(),                 1.0e-10);
1053         Assertions.assertEquals(0.2,        phys.getSrpUncertainty(),                 1.0e-10);
1054         Assertions.assertEquals(15.0,       phys.getVmAbsolute(),                     1.0e-10);
1055         Assertions.assertEquals(19.0,       phys.getVmApparentMin(),                  1.0e-10);
1056         Assertions.assertEquals(15.4,       phys.getVmApparent(),                     1.0e-10);
1057         Assertions.assertEquals(14.0,       phys.getVmApparentMax(),                  1.0e-10);
1058         Assertions.assertEquals(0.7,        phys.getReflectance(),                    1.0e-10);
1059         Assertions.assertEquals("THREE_AXIS",      phys.getAttitudeControlMode());
1060         Assertions.assertEquals("REACTION_WHEELS", phys.getAttitudeActuatorType());
1061         Assertions.assertEquals(0.3, FastMath.toDegrees(phys.getAttitudeKnowledgeAccuracy()), 1.0e-10);
1062         Assertions.assertEquals(2.0, FastMath.toDegrees(phys.getAttitudeControlAccuracy()),   1.0e-10);
1063         Assertions.assertEquals(2.3, FastMath.toDegrees(phys.getAttitudePointingAccuracy()),  1.0e-10);
1064         Assertions.assertEquals(20.0,       phys.getManeuversPerYear(),             1.0e-10);
1065         Assertions.assertEquals(6.8,        phys.getMaxThrust(),                    1.0e-10);
1066         Assertions.assertEquals(1900.0,     phys.getBolDv(),                        1.0e-10);
1067         Assertions.assertEquals(200.0,      phys.getRemainingDv(),                  1.0e-10);
1068         Assertions.assertEquals(1000.0,     phys.getInertiaMatrix().getEntry(0, 0), 1.0e-10);
1069         Assertions.assertEquals( 800.0,     phys.getInertiaMatrix().getEntry(1, 1), 1.0e-10);
1070         Assertions.assertEquals( 400.0,     phys.getInertiaMatrix().getEntry(2, 2), 1.0e-10);
1071         Assertions.assertEquals(  20.0,     phys.getInertiaMatrix().getEntry(0, 1), 1.0e-10);
1072         Assertions.assertEquals(  20.0,     phys.getInertiaMatrix().getEntry(1, 0), 1.0e-10);
1073         Assertions.assertEquals(  40.0,     phys.getInertiaMatrix().getEntry(0, 2), 1.0e-10);
1074         Assertions.assertEquals(  40.0,     phys.getInertiaMatrix().getEntry(2, 0), 1.0e-10);
1075         Assertions.assertEquals(  60.0,     phys.getInertiaMatrix().getEntry(1, 2), 1.0e-10);
1076         Assertions.assertEquals(  60.0,     phys.getInertiaMatrix().getEntry(2, 1), 1.0e-10);
1077 
1078         // check covariance data
1079         Assertions.assertEquals(2, file.getData().getCovarianceBlocks().size());
1080         OrbitCovarianceHistory ch0 = file.getData().getCovarianceBlocks().get(0);
1081         Assertions.assertEquals("this is number 1 COV comment", ch0.getMetadata().getComments().get(0));
1082         Assertions.assertEquals("covariance 1", ch0.getMetadata().getCovID());
1083         Assertions.assertEquals("covariance 0", ch0.getMetadata().getCovPrevID());
1084         Assertions.assertEquals("covariance 2", ch0.getMetadata().getCovNextID());
1085         Assertions.assertEquals("EMPIRICAL",    ch0.getMetadata().getCovBasis());
1086         Assertions.assertEquals("basis 1",      ch0.getMetadata().getCovBasisID());
1087         Assertions.assertNull(ch0.getMetadata().getCovReferenceFrame().asOrbitRelativeFrame());
1088         Assertions.assertEquals("MOD",          ch0.getMetadata().getCovReferenceFrame().getName());
1089         Assertions.assertEquals(33000.0,        ch0.getMetadata().getCovFrameEpoch().durationFrom(epoch), 1.0e-10);
1090         Assertions.assertEquals(0.5,            ch0.getMetadata().getCovScaleMin(),   1.0e-10);
1091         Assertions.assertEquals(5.0,            ch0.getMetadata().getCovScaleMax(),   1.0e-10);
1092         Assertions.assertEquals(0.25,           ch0.getMetadata().getCovConfidence(), 1.0e-10);
1093         Assertions.assertEquals(OrbitElementsType.CARTPV, ch0.getMetadata().getCovType());
1094         Assertions.assertEquals(6, ch0.getMetadata().getCovUnits().size());
1095         Assertions.assertEquals(Unit.KILOMETRE,  ch0.getMetadata().getCovUnits().get(0));
1096         Assertions.assertEquals(Unit.KILOMETRE,  ch0.getMetadata().getCovUnits().get(1));
1097         Assertions.assertEquals(Unit.KILOMETRE,  ch0.getMetadata().getCovUnits().get(2));
1098         Assertions.assertEquals(Units.KM_PER_S,  ch0.getMetadata().getCovUnits().get(3));
1099         Assertions.assertEquals(Units.KM_PER_S,  ch0.getMetadata().getCovUnits().get(4));
1100         Assertions.assertEquals(Units.KM_PER_S,  ch0.getMetadata().getCovUnits().get(5));
1101         Assertions.assertEquals(3, ch0.getCovariances().size());
1102         Assertions.assertEquals(   0.0,  ch0.getCovariances().get(0).getDate().durationFrom(epoch), 1.0e-10);
1103         Assertions.assertEquals(1.1e6,   ch0.getCovariances().get(0).getMatrix().getEntry(0, 0),    1.0e-10);
1104         Assertions.assertEquals( 300.0,  ch0.getCovariances().get(1).getDate().durationFrom(epoch), 1.0e-10);
1105         Assertions.assertEquals(13.2e6,  ch0.getCovariances().get(1).getMatrix().getEntry(2, 1),    1.0e-10);
1106         Assertions.assertEquals( 600.0,  ch0.getCovariances().get(2).getDate().durationFrom(epoch), 1.0e-10);
1107         Assertions.assertEquals(26.5e6,  ch0.getCovariances().get(2).getMatrix().getEntry(4, 5),    1.0e-10);
1108         OrbitCovarianceHistory ch1 = file.getData().getCovarianceBlocks().get(1);
1109         Assertions.assertEquals("this is number 2 COV comment", ch1.getMetadata().getComments().get(0));
1110         Assertions.assertEquals("covariance 2", ch1.getMetadata().getCovID());
1111         Assertions.assertEquals("covariance 1", ch1.getMetadata().getCovPrevID());
1112         Assertions.assertEquals("covariance 3", ch1.getMetadata().getCovNextID());
1113         Assertions.assertEquals("SIMULATED",    ch1.getMetadata().getCovBasis());
1114         Assertions.assertEquals("basis 2",      ch1.getMetadata().getCovBasisID());
1115         Assertions.assertEquals(1, ch1.getCovariances().size());
1116         Assertions.assertEquals(1800.0, ch1.getCovariances().get(0).getDate().durationFrom(epoch), 1.0e-10);
1117         Assertions.assertEquals(43.0e6,   ch1.getCovariances().get(0).getMatrix().getEntry(0, 0),    1.0e-10);
1118         Assertions.assertEquals(20.0e6,   ch1.getCovariances().get(0).getMatrix().getEntry(0, 1),    1.0e-10);
1119         Assertions.assertEquals( 6.0e6,   ch1.getCovariances().get(0).getMatrix().getEntry(0, 5),    1.0e-10);
1120         Assertions.assertEquals( 2.0e6,   ch1.getCovariances().get(0).getMatrix().getEntry(4, 3),    1.0e-10);
1121 
1122         // check maneuver data
1123         Assertions.assertEquals(3, file.getData().getManeuverBlocks().size());
1124         OrbitManeuverHistory m0 = file.getData().getManeuverBlocks().get(0);
1125         Assertions.assertEquals("this is number 1 MAN comment",  m0.getMetadata().getComments().get(0));
1126         Assertions.assertEquals("maneuver 1",                    m0.getMetadata().getManID());
1127         Assertions.assertEquals("maneuver 0",                    m0.getMetadata().getManPrevID());
1128         Assertions.assertEquals("maneuver 2",                    m0.getMetadata().getManNextID());
1129         Assertions.assertEquals(ManBasis.DETERMINED_TLM,         m0.getMetadata().getManBasis());
1130         Assertions.assertEquals("TLM 203",                       m0.getMetadata().getManBasisID());
1131         Assertions.assertEquals("THR_02",                        m0.getMetadata().getManDeviceID());
1132         Assertions.assertEquals(-100.0,                          m0.getMetadata().getManPrevEpoch().durationFrom(epoch), 1.0e-10);
1133         Assertions.assertEquals(+100.0,                          m0.getMetadata().getManNextEpoch().durationFrom(epoch), 1.0e-10);
1134         Assertions.assertEquals("ORBIT",                         m0.getMetadata().getManPurpose().get(0));
1135         Assertions.assertEquals("OD_5",                          m0.getMetadata().getManPredSource());
1136         Assertions.assertNull(m0.getMetadata().getManReferenceFrame().asOrbitRelativeFrame());
1137         Assertions.assertEquals("TOD",                           m0.getMetadata().getManReferenceFrame().getName());
1138         Assertions.assertEquals(2.3,                             m0.getMetadata().getManFrameEpoch().durationFrom(epoch), 1.0e-10);
1139         Assertions.assertEquals("MOON",                          m0.getMetadata().getGravitationalAssist().getName());
1140         Assertions.assertEquals(DutyCycleType.TIME,              m0.getMetadata().getDcType());
1141         Assertions.assertEquals(2.0,                             m0.getMetadata().getDcWindowOpen().durationFrom(epoch),  1.0e-10);
1142         Assertions.assertEquals(100.0,                           m0.getMetadata().getDcWindowClose().durationFrom(epoch), 1.0e-10);
1143         Assertions.assertEquals( 5,                              m0.getMetadata().getDcMinCycles());
1144         Assertions.assertEquals(30,                              m0.getMetadata().getDcMaxCycles());
1145         Assertions.assertEquals( 5.0,                            m0.getMetadata().getDcExecStart().durationFrom(epoch),   1.0e-10);
1146         Assertions.assertEquals(95.0,                            m0.getMetadata().getDcExecStop().durationFrom(epoch),    1.0e-10);
1147         Assertions.assertEquals(8000.0,                          m0.getMetadata().getDcRefTime().durationFrom(epoch),     1.0e-10);
1148         Assertions.assertEquals( 10.0,                           m0.getMetadata().getDcTimePulseDuration(),               1.0e-10);
1149         Assertions.assertEquals(200.0,                           m0.getMetadata().getDcTimePulsePeriod(),                 1.0e-10);
1150         Assertions.assertEquals(23,                              m0.getMetadata().getManComposition().size());
1151         Assertions.assertEquals(ManeuverFieldType.TIME_ABSOLUTE, m0.getMetadata().getManComposition().get( 0));
1152         Assertions.assertEquals(ManeuverFieldType.TIME_RELATIVE, m0.getMetadata().getManComposition().get( 1));
1153         Assertions.assertEquals(ManeuverFieldType.MAN_DURA,      m0.getMetadata().getManComposition().get( 2));
1154         Assertions.assertEquals(ManeuverFieldType.DELTA_MASS,    m0.getMetadata().getManComposition().get( 3));
1155         Assertions.assertEquals(ManeuverFieldType.ACC_X,         m0.getMetadata().getManComposition().get( 4));
1156         Assertions.assertEquals(ManeuverFieldType.ACC_Y,         m0.getMetadata().getManComposition().get( 5));
1157         Assertions.assertEquals(ManeuverFieldType.ACC_Z,         m0.getMetadata().getManComposition().get( 6));
1158         Assertions.assertEquals(ManeuverFieldType.ACC_INTERP,    m0.getMetadata().getManComposition().get( 7));
1159         Assertions.assertEquals(ManeuverFieldType.ACC_MAG_SIGMA, m0.getMetadata().getManComposition().get( 8));
1160         Assertions.assertEquals(ManeuverFieldType.ACC_DIR_SIGMA, m0.getMetadata().getManComposition().get( 9));
1161         Assertions.assertEquals(ManeuverFieldType.DV_X,          m0.getMetadata().getManComposition().get(10));
1162         Assertions.assertEquals(ManeuverFieldType.DV_Y,          m0.getMetadata().getManComposition().get(11));
1163         Assertions.assertEquals(ManeuverFieldType.DV_Z,          m0.getMetadata().getManComposition().get(12));
1164         Assertions.assertEquals(ManeuverFieldType.DV_MAG_SIGMA,  m0.getMetadata().getManComposition().get(13));
1165         Assertions.assertEquals(ManeuverFieldType.DV_DIR_SIGMA,  m0.getMetadata().getManComposition().get(14));
1166         Assertions.assertEquals(ManeuverFieldType.THR_X,         m0.getMetadata().getManComposition().get(15));
1167         Assertions.assertEquals(ManeuverFieldType.THR_Y,         m0.getMetadata().getManComposition().get(16));
1168         Assertions.assertEquals(ManeuverFieldType.THR_Z,         m0.getMetadata().getManComposition().get(17));
1169         Assertions.assertEquals(ManeuverFieldType.THR_EFFIC,     m0.getMetadata().getManComposition().get(18));
1170         Assertions.assertEquals(ManeuverFieldType.THR_INTERP,    m0.getMetadata().getManComposition().get(19));
1171         Assertions.assertEquals(ManeuverFieldType.THR_ISP,       m0.getMetadata().getManComposition().get(20));
1172         Assertions.assertEquals(ManeuverFieldType.THR_MAG_SIGMA, m0.getMetadata().getManComposition().get(21));
1173         Assertions.assertEquals(ManeuverFieldType.THR_DIR_SIGMA, m0.getMetadata().getManComposition().get(22));
1174         Assertions.assertEquals(m0.getMetadata().getManComposition().size() - 2, m0.getMetadata().getManUnits().size());
1175         for (int i = 0; i < m0.getMetadata().getManUnits().size(); ++i) {
1176             ManeuverFieldType type = m0.getMetadata().getManComposition().get(i + 2);
1177             Unit              unit = m0.getMetadata().getManUnits().get(i);
1178             Assertions.assertEquals(type.getUnit(), unit);
1179         }
1180         Assertions.assertEquals(2, m0.getManeuvers().size());
1181         Assertions.assertEquals(   0.0,   m0.getManeuvers().get(0).getDate().durationFrom(epoch), 1.0e-10);
1182         Assertions.assertEquals( 200.0,   m0.getManeuvers().get(0).getDuration(),                 1.0e-10);
1183         Assertions.assertEquals(OnOff.ON, m0.getManeuvers().get(0).getAccelerationInterpolation());
1184         Assertions.assertEquals( 600.0,   m0.getManeuvers().get(1).getDate().durationFrom(epoch), 1.0e-10);
1185         Assertions.assertEquals(  -5.0,   m0.getManeuvers().get(1).getDeltaMass(),                1.0e-10);
1186 
1187         OrbitManeuverHistory m1 = file.getData().getManeuverBlocks().get(1);
1188         Assertions.assertEquals("this is number 2 MAN comment",  m1.getMetadata().getComments().get(0));
1189         Assertions.assertEquals("maneuver 2",                    m1.getMetadata().getManID());
1190         Assertions.assertEquals("maneuver 1",                    m1.getMetadata().getManPrevID());
1191         Assertions.assertEquals("maneuver 3",                    m1.getMetadata().getManNextID());
1192         Assertions.assertEquals(ManBasis.PLANNED,                m1.getMetadata().getManBasis());
1193         Assertions.assertEquals("analysis 17",                   m1.getMetadata().getManBasisID());
1194         Assertions.assertEquals("THR_07",                        m1.getMetadata().getManDeviceID());
1195         Assertions.assertEquals( 200.0,                          m1.getMetadata().getManPrevEpoch().durationFrom(epoch), 1.0e-10);
1196         Assertions.assertEquals( 300.0,                          m1.getMetadata().getManNextEpoch().durationFrom(epoch), 1.0e-10);
1197         Assertions.assertEquals("PERIOD",                        m1.getMetadata().getManPurpose().get(0));
1198         Assertions.assertEquals("OD_5",                          m1.getMetadata().getManPredSource());
1199         Assertions.assertEquals(OrbitRelativeFrame.TNW_INERTIAL, m1.getMetadata().getManReferenceFrame().asOrbitRelativeFrame());
1200         Assertions.assertEquals(0.0,                             m1.getMetadata().getManFrameEpoch().durationFrom(epoch), 1.0e-10);
1201         Assertions.assertEquals("EARTH",                         m1.getMetadata().getGravitationalAssist().getName());
1202         Assertions.assertEquals(DutyCycleType.TIME_AND_ANGLE,    m1.getMetadata().getDcType());
1203         Assertions.assertEquals(1002.0,                          m1.getMetadata().getDcWindowOpen().durationFrom(epoch),  1.0e-10);
1204         Assertions.assertEquals(1100.0,                          m1.getMetadata().getDcWindowClose().durationFrom(epoch), 1.0e-10);
1205         Assertions.assertEquals(14,                              m1.getMetadata().getDcMinCycles());
1206         Assertions.assertEquals(60,                              m1.getMetadata().getDcMaxCycles());
1207         Assertions.assertEquals(1005.0,                          m1.getMetadata().getDcExecStart().durationFrom(epoch),   1.0e-10);
1208         Assertions.assertEquals(1095.0,                          m1.getMetadata().getDcExecStop().durationFrom(epoch),    1.0e-10);
1209         Assertions.assertEquals(12000.0,                         m1.getMetadata().getDcRefTime().durationFrom(epoch),     1.0e-10);
1210         Assertions.assertEquals( 20.0,                           m1.getMetadata().getDcTimePulseDuration(),               1.0e-10);
1211         Assertions.assertEquals(400.0,                           m1.getMetadata().getDcTimePulsePeriod(),                 1.0e-10);
1212         Assertions.assertEquals(22,                              m1.getMetadata().getManComposition().size());
1213         Assertions.assertEquals(0.0,
1214                             Vector3D.distance(m1.getMetadata().getDcRefDir(),
1215                                               Vector3D.PLUS_I),
1216                             1.0e-10);
1217         Assertions.assertEquals(SpacecraftBodyFrame.BaseEquipment.SENSOR, m1.getMetadata().getDcBodyFrame().getBaseEquipment());
1218         Assertions.assertEquals("3",                             m1.getMetadata().getDcBodyFrame().getLabel());
1219         Assertions.assertEquals(0.0,
1220                             Vector3D.distance(m1.getMetadata().getDcBodyTrigger(),
1221                                               new Vector3D(0.707, 0.0, 0.707)),
1222                             1.0e-10);
1223         Assertions.assertEquals(25.0, FastMath.toDegrees(m1.getMetadata().getDcPhaseStartAngle()), 1.0e-10);
1224         Assertions.assertEquals(35.0, FastMath.toDegrees(m1.getMetadata().getDcPhaseStopAngle()),  1.0e-10);
1225         Assertions.assertEquals(22,                              m1.getMetadata().getManComposition().size());
1226         Assertions.assertEquals(ManeuverFieldType.TIME_RELATIVE, m1.getMetadata().getManComposition().get( 0));
1227         Assertions.assertEquals(ManeuverFieldType.MAN_DURA,      m1.getMetadata().getManComposition().get( 1));
1228         Assertions.assertEquals(ManeuverFieldType.DELTA_MASS,    m1.getMetadata().getManComposition().get( 2));
1229         Assertions.assertEquals(ManeuverFieldType.ACC_X,         m1.getMetadata().getManComposition().get( 3));
1230         Assertions.assertEquals(ManeuverFieldType.ACC_Y,         m1.getMetadata().getManComposition().get( 4));
1231         Assertions.assertEquals(ManeuverFieldType.ACC_Z,         m1.getMetadata().getManComposition().get( 5));
1232         Assertions.assertEquals(ManeuverFieldType.ACC_INTERP,    m1.getMetadata().getManComposition().get( 6));
1233         Assertions.assertEquals(ManeuverFieldType.ACC_MAG_SIGMA, m1.getMetadata().getManComposition().get( 7));
1234         Assertions.assertEquals(ManeuverFieldType.ACC_DIR_SIGMA, m1.getMetadata().getManComposition().get( 8));
1235         Assertions.assertEquals(ManeuverFieldType.DV_X,          m1.getMetadata().getManComposition().get( 9));
1236         Assertions.assertEquals(ManeuverFieldType.DV_Y,          m1.getMetadata().getManComposition().get(10));
1237         Assertions.assertEquals(ManeuverFieldType.DV_Z,          m1.getMetadata().getManComposition().get(11));
1238         Assertions.assertEquals(ManeuverFieldType.DV_MAG_SIGMA,  m1.getMetadata().getManComposition().get(12));
1239         Assertions.assertEquals(ManeuverFieldType.DV_DIR_SIGMA,  m1.getMetadata().getManComposition().get(13));
1240         Assertions.assertEquals(ManeuverFieldType.THR_X,         m1.getMetadata().getManComposition().get(14));
1241         Assertions.assertEquals(ManeuverFieldType.THR_Y,         m1.getMetadata().getManComposition().get(15));
1242         Assertions.assertEquals(ManeuverFieldType.THR_Z,         m1.getMetadata().getManComposition().get(16));
1243         Assertions.assertEquals(ManeuverFieldType.THR_EFFIC,     m1.getMetadata().getManComposition().get(17));
1244         Assertions.assertEquals(ManeuverFieldType.THR_INTERP,    m1.getMetadata().getManComposition().get(18));
1245         Assertions.assertEquals(ManeuverFieldType.THR_ISP,       m1.getMetadata().getManComposition().get(19));
1246         Assertions.assertEquals(ManeuverFieldType.THR_MAG_SIGMA, m1.getMetadata().getManComposition().get(20));
1247         Assertions.assertEquals(ManeuverFieldType.THR_DIR_SIGMA, m1.getMetadata().getManComposition().get(21));
1248         Assertions.assertEquals(m1.getMetadata().getManComposition().size() - 1, m1.getMetadata().getManUnits().size());
1249         for (int i = 0; i < m1.getMetadata().getManUnits().size(); ++i) {
1250             ManeuverFieldType type = m1.getMetadata().getManComposition().get(i + 1);
1251             Unit              unit = m1.getMetadata().getManUnits().get(i);
1252             Assertions.assertEquals(type.getUnit(), unit);
1253         }
1254         Assertions.assertEquals(2, m1.getManeuvers().size());
1255         Assertions.assertEquals(1000.0,    m1.getManeuvers().get(0).getDate().durationFrom(epoch), 1.0e-10);
1256         Assertions.assertEquals(0.02,      m1.getManeuvers().get(0).getThrustMagnitudeSigma(),     1.0e-10);
1257         Assertions.assertEquals(4.3,       FastMath.toDegrees(m1.getManeuvers().get(0).getThrustDirectionSigma()), 1.0e-10);
1258         Assertions.assertEquals(OnOff.OFF, m1.getManeuvers().get(0).getAccelerationInterpolation());
1259         Assertions.assertEquals(1600.0,    m1.getManeuvers().get(1).getDate().durationFrom(epoch), 1.0e-10);
1260         Assertions.assertEquals( 25.0,     m1.getManeuvers().get(1).getDv().getX(),                1.0e-10);
1261 
1262 
1263         OrbitManeuverHistory m2 = file.getData().getManeuverBlocks().get(2);
1264         Assertions.assertEquals("this is number 3 MAN comment",     m2.getMetadata().getComments().get(0));
1265         Assertions.assertEquals("maneuver 3",                       m2.getMetadata().getManID());
1266         Assertions.assertEquals("DEPLOYMENT",                       m2.getMetadata().getManDeviceID());
1267         Assertions.assertEquals(10,                                 m2.getMetadata().getManComposition().size());
1268         Assertions.assertEquals(ManeuverFieldType.TIME_ABSOLUTE,    m2.getMetadata().getManComposition().get( 0));
1269         Assertions.assertEquals(ManeuverFieldType.DEPLOY_ID,        m2.getMetadata().getManComposition().get( 1));
1270         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_X,      m2.getMetadata().getManComposition().get( 2));
1271         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_Y,      m2.getMetadata().getManComposition().get( 3));
1272         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_Z,      m2.getMetadata().getManComposition().get( 4));
1273         Assertions.assertEquals(ManeuverFieldType.DEPLOY_MASS,      m2.getMetadata().getManComposition().get( 5));
1274         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_SIGMA,  m2.getMetadata().getManComposition().get( 6));
1275         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DIR_SIGMA, m2.getMetadata().getManComposition().get( 7));
1276         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_RATIO,  m2.getMetadata().getManComposition().get( 8));
1277         Assertions.assertEquals(ManeuverFieldType.DEPLOY_DV_CDA,    m2.getMetadata().getManComposition().get( 9));
1278         Assertions.assertEquals(m2.getMetadata().getManComposition().size() - 1, m2.getMetadata().getManUnits().size());
1279         for (int i = 0; i < m2.getMetadata().getManUnits().size(); ++i) {
1280             ManeuverFieldType type = m2.getMetadata().getManComposition().get(i + 1);
1281             Unit              unit = m2.getMetadata().getManUnits().get(i);
1282             Assertions.assertEquals(type.getUnit(), unit);
1283         }
1284         Assertions.assertEquals(8, m2.getManeuvers().size());
1285         Assertions.assertEquals(35100.0,   m2.getManeuvers().get(0).getDate().durationFrom(epoch), 1.0e-10);
1286         Assertions.assertEquals("BEE_1",   m2.getManeuvers().get(0).getDeployId());
1287         Assertions.assertEquals(35160.0,   m2.getManeuvers().get(1).getDate().durationFrom(epoch), 1.0e-10);
1288         Assertions.assertEquals(    0.3,   m2.getManeuvers().get(1).getDeployDv().getY(),          1.0e-10);
1289 
1290         // check perturbation data
1291         final Perturbations pert = file.getData().getPerturbationsBlock();
1292         Assertions.assertEquals("this is PERT comment",         pert.getComments().get(0));
1293         Assertions.assertEquals("NRLMSIS00",                    pert.getAtmosphericModel());
1294         Assertions.assertEquals("TEG-4",                        pert.getGravityModel());
1295         Assertions.assertEquals(36,                             pert.getGravityDegree());
1296         Assertions.assertEquals(12,                             pert.getGravityOrder());
1297         Assertions.assertEquals(6378137.0,                      pert.getEquatorialRadius(), 1.0e-9);
1298         Assertions.assertEquals(3.986004415e14,                 pert.getGm(),               1.0);
1299         Assertions.assertEquals("MOON",                         pert.getNBodyPerturbations().get(0).getName());
1300         Assertions.assertEquals("SUN",                          pert.getNBodyPerturbations().get(1).getName());
1301         Assertions.assertEquals(4.17807421629e-3,               FastMath.toDegrees(pert.getCentralBodyRotation()), 1.0e-12);
1302         Assertions.assertEquals(0.00335281066475,               pert.getOblateFlattening(), 1.0e-12);
1303         Assertions.assertEquals("SEMI-DIURNAL",                 pert.getOceanTidesModel());
1304         Assertions.assertEquals("DIURNAL",                      pert.getSolidTidesModel());
1305         Assertions.assertEquals("IERS2010",                     pert.getReductionTheory());
1306         Assertions.assertEquals("KNOCKE",                       pert.getAlbedoModel());
1307         Assertions.assertEquals(100,                            pert.getAlbedoGridSize());
1308         Assertions.assertEquals(ShadowModel.DUAL_CONE,          pert.getShadowModel());
1309         Assertions.assertEquals("EARTH",                        pert.getShadowBodies().get(0).getName());
1310         Assertions.assertEquals("MOON",                         pert.getShadowBodies().get(1).getName());
1311         Assertions.assertEquals("BOX_WING",                     pert.getSrpModel());
1312         Assertions.assertEquals("CELESTRAK",                    pert.getSpaceWeatherSource());
1313         Assertions.assertEquals(0.0, pert.getSpaceWeatherEpoch().durationFrom(new AbsoluteDate(2019, 7, 22, TimeScalesFactory.getUTC())), 1.0e-10);
1314         Assertions.assertEquals("LAGRANGE_ORDER_5",             pert.getInterpMethodSW());
1315         Assertions.assertEquals(3.2e-9,                         pert.getFixedGeomagneticKp(),  1.0e-20);
1316         Assertions.assertEquals(2.1e-9,                         pert.getFixedGeomagneticAp(),  1.0e-20);
1317         Assertions.assertEquals(-20.0e-9,                       pert.getFixedGeomagneticDst(), 1.0e-20);
1318         Assertions.assertEquals(1.20e-20,                       pert.getFixedF10P7(),          1.0e-30);
1319         Assertions.assertEquals(1.32e-20,                       pert.getFixedF10P7Mean(),      1.0e-30);
1320         Assertions.assertEquals(1.30e-20,                       pert.getFixedM10P7(),          1.0e-30);
1321         Assertions.assertEquals(1.42e-20,                       pert.getFixedM10P7Mean(),      1.0e-30);
1322         Assertions.assertEquals(1.40e-20,                       pert.getFixedS10P7(),          1.0e-30);
1323         Assertions.assertEquals(1.52e-20,                       pert.getFixedS10P7Mean(),      1.0e-30);
1324         Assertions.assertEquals(1.50e-20,                       pert.getFixedY10P7(),          1.0e-30);
1325         Assertions.assertEquals(1.62e-20,                       pert.getFixedY10P7Mean(),      1.0e-30);
1326 
1327         // check orbit determination data
1328         OrbitDetermination od = file.getData().getOrbitDeterminationBlock();
1329         Assertions.assertEquals("this is OD comment", od.getComments().get(0));
1330         Assertions.assertEquals("OD_24",              od.getId());
1331         Assertions.assertEquals("OD_23",              od.getPrevId());
1332         Assertions.assertEquals("BWLS",               od.getMethod().getName());
1333         Assertions.assertEquals(OdMethodType.BWLS,    od.getMethod().getType());
1334         Assertions.assertEquals("OREKIT",             od.getMethod().getTool());
1335         Assertions.assertEquals(0.0,
1336                             od.getEpoch().durationFrom(new AbsoluteDate(2019, 7, 22, 17, 32, 27.0,
1337                                                                         TimeScalesFactory.getUTC())),
1338                             1.0e-10);
1339         Assertions.assertEquals(302400.0,             od.getTimeSinceFirstObservation(), 1.0e-10);
1340         Assertions.assertEquals(103680.0,             od.getTimeSinceLastObservation(),  1.0e-10);
1341         Assertions.assertEquals(449280.0,             od.getRecommendedOdSpan(),         1.0e-10);
1342         Assertions.assertEquals(198720.0,             od.getActualOdSpan(),              1.0e-10);
1343         Assertions.assertEquals(100,                  od.getObsAvailable());
1344         Assertions.assertEquals( 90,                  od.getObsUsed());
1345         Assertions.assertEquals( 33,                  od.getTracksAvailable());
1346         Assertions.assertEquals( 30,                  od.getTracksUsed());
1347         Assertions.assertEquals(86400.0,              od.getMaximumObsGap(),             1.0e-10);
1348         Assertions.assertEquals(58.73,                od.getEpochEigenMaj(),             1.0e-10);
1349         Assertions.assertEquals(35.7,                 od.getEpochEigenInt(),             1.0e-10);
1350         Assertions.assertEquals(21.5,                 od.getEpochEigenMin(),             1.0e-10);
1351         Assertions.assertEquals(32.5,                 od.getMaxPredictedEigenMaj(),      1.0e-10);
1352         Assertions.assertEquals(22.0,                 od.getMinPredictedEigenMin(),      1.0e-10);
1353         Assertions.assertEquals(0.953,                od.getConfidence(),                1.0e-10);
1354         Assertions.assertEquals(0.857,                od.getGdop(),                      1.0e-10);
1355         Assertions.assertEquals(6,                    od.getSolveN());
1356         Assertions.assertEquals("POS[3]",             od.getSolveStates().get(0));
1357         Assertions.assertEquals("VEL[3]",             od.getSolveStates().get(1));
1358         Assertions.assertEquals(2,                    od.getConsiderN());
1359         Assertions.assertEquals("DRAG",               od.getConsiderParameters().get(0));
1360         Assertions.assertEquals("SRP",                od.getConsiderParameters().get(1));
1361         Assertions.assertEquals(3,                    od.getSensorsN());
1362         Assertions.assertEquals("EGLIN",              od.getSensors().get(0));
1363         Assertions.assertEquals("FYLINGDALES",        od.getSensors().get(1));
1364         Assertions.assertEquals("PLAGNOLE",           od.getSensors().get(2));
1365         Assertions.assertEquals(1.3,                  od.getWeightedRms(), 1.0e-10);
1366         Assertions.assertEquals("RANGE",              od.getDataTypes().get(0));
1367         Assertions.assertEquals("DOPPLER",            od.getDataTypes().get(1));
1368         Assertions.assertEquals("AZEL",               od.getDataTypes().get(2));
1369 
1370         // check user data
1371         Assertions.assertEquals(1, file.getData().getUserDefinedBlock().getParameters().size());
1372         Assertions.assertEquals("OREKIT", file.getData().getUserDefinedBlock().getParameters().get("LIBRARY"));
1373 
1374         Assertions.assertEquals(1, file.getSatellites().size());
1375         OcmSatelliteEphemeris ephemeris = file.getSatellites().get("POLYSAT");
1376         Assertions.assertEquals("POLYSAT", ephemeris.getId());
1377         Assertions.assertEquals(3.986004415e14, ephemeris.getMu(), 1e5);
1378         Assertions.assertEquals(3.0e5, Constants.IERS2003_EARTH_MU - ephemeris.getMu(), 1e0);
1379         Assertions.assertEquals(3, ephemeris.getSegments().size());
1380         List<TimeStampedPVCoordinates> h0 = ephemeris.getSegments().get(0).getCoordinates();
1381         Assertions.assertEquals(3, h0.size());
1382         Assertions.assertEquals(   0.0, h0.get(0).getDate().durationFrom(epoch), 1.0e-10);
1383         Assertions.assertEquals( 300.0, h0.get(1).getDate().durationFrom(epoch), 1.0e-10);
1384         Assertions.assertEquals( 600.0, h0.get(2).getDate().durationFrom(epoch), 1.0e-10);
1385         List<TimeStampedPVCoordinates> h1 = ephemeris.getSegments().get(1).getCoordinates();
1386         Assertions.assertEquals(3, h1.size());
1387         Assertions.assertEquals(1800.0, h1.get(0).getDate().durationFrom(epoch), 1.0e-10);
1388         Assertions.assertEquals(2100.0, h1.get(1).getDate().durationFrom(epoch), 1.0e-10);
1389         Assertions.assertEquals(2400.0, h1.get(2).getDate().durationFrom(epoch), 1.0e-10);
1390 
1391         Assertions.assertEquals(   0.0, ephemeris.getStart().durationFrom(epoch), 10e-10);
1392         Assertions.assertEquals(3400.0, ephemeris.getStop().durationFrom(epoch), 10e-10);
1393 
1394     }
1395 
1396 }