1   /* Copyright 2002-2023 CS GROUP
2    * Licensed to CS GROUP (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.oem;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.SequenceInputStream;
23  import java.net.URISyntaxException;
24  import java.nio.charset.Charset;
25  import java.nio.charset.StandardCharsets;
26  import java.util.ArrayList;
27  import java.util.List;
28  
29  import org.hamcrest.MatcherAssert;
30  import org.hipparchus.geometry.euclidean.threed.Rotation;
31  import org.hipparchus.geometry.euclidean.threed.Vector3D;
32  import org.hipparchus.linear.Array2DRowRealMatrix;
33  import org.hipparchus.util.Pair;
34  import org.junit.jupiter.api.Assertions;
35  import org.junit.jupiter.api.BeforeEach;
36  import org.junit.jupiter.api.Test;
37  import org.orekit.OrekitMatchers;
38  import org.orekit.Utils;
39  import org.orekit.bodies.CelestialBody;
40  import org.orekit.bodies.CelestialBodyFactory;
41  import org.orekit.data.DataContext;
42  import org.orekit.data.DataSource;
43  import org.orekit.errors.OrekitException;
44  import org.orekit.errors.OrekitMessages;
45  import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
46  import org.orekit.files.ccsds.definitions.OrbitRelativeFrame;
47  import org.orekit.files.ccsds.ndm.ParserBuilder;
48  import org.orekit.files.ccsds.ndm.odm.CartesianCovariance;
49  import org.orekit.frames.FactoryManagedFrame;
50  import org.orekit.frames.Frame;
51  import org.orekit.frames.FramesFactory;
52  import org.orekit.frames.ITRFVersion;
53  import org.orekit.frames.LOFType;
54  import org.orekit.frames.Transform;
55  import org.orekit.orbits.CartesianOrbit;
56  import org.orekit.propagation.BoundedPropagator;
57  import org.orekit.time.AbsoluteDate;
58  import org.orekit.time.TimeScalesFactory;
59  import org.orekit.utils.CartesianDerivativesFilter;
60  import org.orekit.utils.IERSConventions;
61  import org.orekit.utils.PVCoordinates;
62  import org.orekit.utils.TimeStampedPVCoordinates;
63  
64  
65  public class OemParserTest {
66  
67      @BeforeEach
68      public void setUp()
69          throws Exception {
70          Utils.setDataRoot("regular-data");
71      }
72  
73      @Test
74      public void testIssue788() {
75  
76          // Read the file
77          final String ex = "/ccsds/odm/oem/test.oem";
78          final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
79          final OemParser parser  = new ParserBuilder().buildOemParser();
80          final Oem file = parser.parseMessage(source);
81  
82          // Verify
83          Assertions.assertEquals(file.getDataContext().getCelestialBodies().getEarth().getGM(), file.getSegments().get(0).getMu(), Double.MIN_VALUE);
84          Assertions.assertEquals(3.986004328969392E14, file.getSegments().get(0).getMu(), Double.MIN_VALUE);
85  
86      }
87  
88      @Test
89      public void testParseOEM1() throws IOException {
90          //
91          final String ex = "/ccsds/odm/oem/OEMExample1.txt";
92          final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
93          final OemParser parser  = new ParserBuilder().withMu(CelestialBodyFactory.getMars().getGM()).buildOemParser();
94          final Oem file = parser.parseMessage(source);
95          Assertions.assertEquals("public, test-data", file.getHeader().getClassification());
96          Assertions.assertEquals(3, file.getSegments().size());
97          Assertions.assertEquals("UTC", file.getSegments().get(0).getMetadata().getTimeSystem().name());
98          Assertions.assertEquals("MARS GLOBAL SURVEYOR", file.getSegments().get(0).getMetadata().getObjectName());
99          Assertions.assertEquals("1996-062A", file.getSegments().get(0).getMetadata().getObjectID());
100         Assertions.assertEquals("MARS BARYCENTER", file.getSegments().get(0).getMetadata().getCenter().getName());
101         Assertions.assertEquals(1996, file.getSegments().get(0).getMetadata().getLaunchYear());
102         Assertions.assertEquals(62, file.getSegments().get(0).getMetadata().getLaunchNumber());
103         Assertions.assertEquals("A", file.getSegments().get(0).getMetadata().getLaunchPiece());
104         Assertions.assertNull(file.getSegments().get(0).getMetadata().getCenter().getBody());
105         Assertions.assertNull(file.getSegments().get(0).getMetadata().getCenter().getBody());
106         Assertions.assertEquals(new AbsoluteDate(1996, 12, 18, 12, 00, 0.331, TimeScalesFactory.getUTC()),
107                             file.getSegments().get(0).getMetadata().getStartTime());
108         Assertions.assertEquals(new AbsoluteDate(1996, 12, 28, 21, 28, 0.331, TimeScalesFactory.getUTC()),
109                             file.getSegments().get(0).getMetadata().getStopTime());
110         Assertions.assertEquals(new AbsoluteDate(1996, 12, 18, 12, 10, 0.331, TimeScalesFactory.getUTC()),
111                             file.getSegments().get(0).getMetadata().getUseableStartTime());
112         Assertions.assertEquals(new AbsoluteDate(1996, 12, 28, 21, 23, 0.331, TimeScalesFactory.getUTC()),
113                             file.getSegments().get(0).getMetadata().getUseableStopTime());
114         Assertions.assertEquals(InterpolationMethod.HERMITE, file.getSegments().get(0).getMetadata().getInterpolationMethod());
115         Assertions.assertEquals(7, file.getSegments().get(0).getMetadata().getInterpolationDegree());
116         ArrayList<String> ephemeridesDataLinesComment = new ArrayList<String>();
117         ephemeridesDataLinesComment.add("This file was produced by M.R. Somebody, MSOO NAV/JPL, 1996NOV 04. It is");
118         ephemeridesDataLinesComment.add("to be used for DSN scheduling purposes only.");
119         Assertions.assertEquals(ephemeridesDataLinesComment, file.getSegments().get(0).getData().getComments());
120         CartesianOrbit orbit = new CartesianOrbit(new PVCoordinates
121                                                   (new Vector3D(2789.619 * 1000, -280.045 * 1000, -1746.755 * 1000),
122                                                    new Vector3D(4.73372 * 1000, -2.49586 * 1000, -1.04195 * 1000)),
123                                                    FramesFactory.getEME2000(),
124                                                    new AbsoluteDate("1996-12-18T12:00:00.331", TimeScalesFactory.getUTC()),
125                                                    CelestialBodyFactory.getEarth().getGM());
126         Assertions.assertArrayEquals(orbit.getPosition().toArray(),
127                                      file.getSegments().get(0).getData().getEphemeridesDataLines().get(0).getPosition().toArray(), 1e-10);
128         Assertions.assertArrayEquals(orbit.getPVCoordinates().getVelocity().toArray(), file.getSegments().get(0).getData().getEphemeridesDataLines().get(0).getVelocity().toArray(), 1e-10);
129         Assertions.assertEquals(Vector3D.ZERO, file.getSegments().get(1).getData().getEphemeridesDataLines().get(1).getAcceleration());
130         final Array2DRowRealMatrix covMatrix = new Array2DRowRealMatrix(6, 6);
131         final double[] column1 = {
132              3.3313494e-04,  4.6189273e-04, -3.0700078e-04, -3.3493650e-07, -2.2118325e-07, -3.0413460e-07
133         };
134         final double[] column2 = {
135              4.6189273e-04,  6.7824216e-04, -4.2212341e-04, -4.6860842e-07, -2.8641868e-07, -4.9894969e-07
136         };
137         final double[] column3 = {
138             -3.0700078e-04, -4.2212341e-04, 3.2319319e-04,  2.4849495e-07, 1.7980986e-07,  3.5403109e-07
139         };
140         final double[] column4 = {
141             -3.3493650e-07, -4.6860842e-07, 2.4849495e-07,  4.29602280e-10, 2.6088992e-10,  1.86926319e-10
142         };
143         final double[] column5 = {
144             -2.2118325e-07, -2.8641868e-07, 1.7980986e-07,  2.6088992e-10, 1.7675147e-10,  1.0088625e-10
145         };
146         final double[] column6 = {
147             -3.0413460e-07, -4.9894969e-07, 3.5403109e-07,  1.8692631e-10, 1.0088625e-10,  6.2244443e-10
148         };
149         covMatrix.setColumn(0, column1);
150         covMatrix.setColumn(1, column2);
151         covMatrix.setColumn(2, column3);
152         covMatrix.setColumn(3, column4);
153         covMatrix.setColumn(4, column5);
154         covMatrix.setColumn(5, column6);
155         for (int i = 0; i < 6; i++) {
156             for (int j = 0; j < 6; j++) {
157                 Assertions.assertEquals(covMatrix.getEntry(i, j) * 1.0e6,
158                                     file.getSegments().get(2).getData().getCovarianceMatrices().get(0).getCovarianceMatrix().getEntry(i, j),
159                                     1e-10);
160             }
161         }
162         Assertions.assertEquals(new AbsoluteDate("1996-12-28T21:29:07.267", TimeScalesFactory.getUTC()),
163                             file.getSegments().get(2).getCovarianceMatrices().get(0).getEpoch());
164         Assertions.assertEquals(LOFType.QSW,
165                             file.getSegments().get(2).getCovarianceMatrices().get(0).getReferenceFrame().asOrbitRelativeFrame().getLofType());
166         Assertions.assertNull(file.getSegments().get(2).getCovarianceMatrices().get(0).getReferenceFrame().asFrame());
167         Assertions.assertNull(file.getSegments().get(2).getCovarianceMatrices().get(0).getReferenceFrame().asCelestialBodyFrame());
168         Assertions.assertNull(file.getSegments().get(2).getCovarianceMatrices().get(0).getReferenceFrame().asSpacecraftBodyFrame());
169         Assertions.assertNull(file.getSegments().get(2).getCovarianceMatrices().get(1).getReferenceFrame().asOrbitRelativeFrame());
170         Assertions.assertEquals(FramesFactory.getEME2000(),
171                             file.getSegments().get(2).getCovarianceMatrices().get(1).getReferenceFrame().asFrame());
172     }
173 
174     @Test
175     public void testParseOEM2() throws URISyntaxException {
176 
177         final String ex = "/ccsds/odm/oem/OEMExample2.txt";
178         final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
179         final AbsoluteDate missionReferenceDate = new AbsoluteDate("1996-12-17T00:00:00.000", TimeScalesFactory.getUTC());
180         OemParser parser = new ParserBuilder().
181                            withConventions(IERSConventions.IERS_2010).
182                            withSimpleEOP(true).
183                            withDataContext(DataContext.getDefault()).
184                            withMissionReferenceDate(missionReferenceDate).
185                            withMu(CelestialBodyFactory.getMars().getGM()).
186                            withDefaultInterpolationDegree(1).
187                            buildOemParser();
188 
189         final Oem file = parser.parseMessage(source);
190         final List<String> headerComment = new ArrayList<String>();
191         headerComment.add("comment");
192         Assertions.assertEquals(headerComment, file.getHeader().getComments());
193         final List<String> metadataComment = new ArrayList<String>();
194         metadataComment.add("comment 1");
195         metadataComment.add("comment 2");
196         Assertions.assertEquals(metadataComment, file.getSegments().get(0).getMetadata().getComments());
197         Assertions.assertEquals("TOD/2010 simple EOP",
198                             file.getSegments().get(0).getMetadata().getReferenceFrame().asFrame().getName());
199         Assertions.assertEquals("TOD",
200                             file.getSegments().get(0).getMetadata().getReferenceFrame().getName());
201         Assertions.assertEquals("EME2000", file.getSegments().get(1).getMetadata().getReferenceFrame().getName());
202         List<OemSegment> blocks = file.getSegments();
203         Assertions.assertEquals(2, blocks.size());
204         Assertions.assertEquals(129600.331,
205                             blocks.get(0).getMetadata().getFrameEpoch().durationFrom(missionReferenceDate),
206                             1.0e-15);
207         Assertions.assertEquals(129600.331,
208                             blocks.get(0).getMetadata().getStartTime().durationFrom(missionReferenceDate),
209                             1.0e-15);
210         Assertions.assertEquals(941347.267,
211                             blocks.get(1).getMetadata().getStartTime().durationFrom(missionReferenceDate),
212                             1.0e-15);
213 
214     }
215 
216     @Test
217     public void testParseOEM3KVN() throws IOException {
218 
219         final String ex = "/ccsds/odm/oem/OEMExample3.txt";
220         final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
221         final OemParser parser  = new ParserBuilder().withMu(CelestialBodyFactory.getMars().getGM()).buildOemParser();
222         final Oem file = parser.parse(source); // using the generic API here
223         Assertions.assertEquals("Copy of OEMExample.txt with changes so that interpolation will work.",
224                             file.getHeader().getComments().get(0));
225         Assertions.assertEquals(new AbsoluteDate("1996-11-04T17:22:31", TimeScalesFactory.getUTC()),
226                             file.getHeader().getCreationDate());
227         Assertions.assertEquals("NASA/JPL", file.getHeader().getOriginator());
228         Assertions.assertEquals("OEM 201113719185", file.getHeader().getMessageId());
229         Assertions.assertEquals("UTC", file.getSegments().get(0).getMetadata().getTimeSystem().name());
230         Assertions.assertEquals("MARS GLOBAL SURVEYOR", file.getSegments().get(0).getMetadata().getObjectName());
231         Assertions.assertEquals("1996-062A", file.getSegments().get(0).getMetadata().getObjectID());
232 
233         Assertions.assertEquals(1, file.getSatellites().size());
234         Assertions.assertEquals(true, file.getSatellites().containsKey("1996-062A"));
235         Assertions.assertEquals(false, file.getSatellites().containsKey("MARS GLOBAL SURVEYOR"));
236         Assertions.assertEquals(1, file.getSatellites().size());
237         Assertions.assertEquals("1996-062A", file.getSatellites().values().iterator().next().getId());
238         Assertions.assertEquals(
239                 new AbsoluteDate("1996-12-18T12:00:00.331", TimeScalesFactory.getUTC()),
240                 file.getSegments().get(0).getMetadata().getStartTime());
241 
242         final OemSatelliteEphemeris satellite = file.getSatellites().get("1996-062A");
243         Assertions.assertEquals("1996-062A", satellite.getId());
244         final OemSegment segment = (OemSegment) satellite.getSegments().get(0);
245         Assertions.assertEquals(CelestialBodyFactory.getMars().getGM(), segment.getMu(), 1.0);
246         Assertions.assertEquals("EME2000", segment.getMetadata().getReferenceFrame().getName());
247         Assertions.assertEquals(segment.getMetadata().getCenter().getName(), "MARS BARYCENTER");
248         Assertions.assertNull(segment.getMetadata().getCenter().getBody());
249         // Frame not creatable since it's center can't be created.
250         try {
251             segment.getFrame();
252             Assertions.fail("Expected Exception");
253         } catch (OrekitException e){
254             Assertions.assertEquals(e.getSpecifier(), OrekitMessages.NO_DATA_LOADED_FOR_CELESTIAL_BODY);
255         }
256         Assertions.assertEquals("UTC", segment.getMetadata().getTimeSystem().name());
257         Assertions.assertEquals(InterpolationMethod.HERMITE, segment.getMetadata().getInterpolationMethod());
258         Assertions.assertEquals(2, segment.getMetadata().getInterpolationDegree());
259         Assertions.assertEquals(3, segment.getInterpolationSamples());
260         Assertions.assertEquals(segment.getAvailableDerivatives(), CartesianDerivativesFilter.USE_PV);
261 
262         List<OemSegment> segments = file.getSegments();
263         Assertions.assertEquals(3, segments.size());
264         Assertions.assertEquals(3, segments.get(2).getData().getCoordinates().size());
265         final TimeStampedPVCoordinates pv20 = segments.get(2).getData().getCoordinates().get(0);
266         Assertions.assertEquals(
267                             new AbsoluteDate("1996-12-28T21:29:07.267", TimeScalesFactory.getUTC()),
268                             pv20.getDate());
269         Assertions.assertEquals(-2432166.0,   pv20.getPosition().getX(), 1.0e-10);
270         Assertions.assertEquals(  -63042.0,   pv20.getPosition().getY(), 1.0e-10);
271         Assertions.assertEquals( 1742754.0,   pv20.getPosition().getZ(), 1.0e-10);
272         Assertions.assertEquals(    7337.02,  pv20.getVelocity().getX(), 1.0e-10);
273         Assertions.assertEquals(   -3495.867, pv20.getVelocity().getY(), 1.0e-10);
274         Assertions.assertEquals(   -1041.945, pv20.getVelocity().getZ(), 1.0e-10);
275         final TimeStampedPVCoordinates pv21 = segments.get(2).getData().getCoordinates().get(1);
276         Assertions.assertEquals(new AbsoluteDate("1996-12-28T21:59:02.267", TimeScalesFactory.getUTC()),
277                             pv21.getDate());
278         Assertions.assertEquals(-2445234.0,   pv21.getPosition().getX(), 1.0e-10);
279         Assertions.assertEquals( -878141.0,   pv21.getPosition().getY(), 1.0e-10);
280         Assertions.assertEquals( 1873073.0,   pv21.getPosition().getZ(), 1.0e-10);
281         Assertions.assertEquals(    1860.43,  pv21.getVelocity().getX(), 1.0e-10);
282         Assertions.assertEquals(   -3421.256, pv21.getVelocity().getY(), 1.0e-10);
283         Assertions.assertEquals(    -996.366, pv21.getVelocity().getZ(), 1.0e-10);
284         final TimeStampedPVCoordinates pv22 = segments.get(2).getData().getCoordinates().get(2);
285         Assertions.assertEquals(new AbsoluteDate("1996-12-28T22:00:02.267", TimeScalesFactory.getUTC()),
286                             pv22.getDate());
287         Assertions.assertEquals(-2458079.0,   pv22.getPosition().getX(), 1.0e-10);
288         Assertions.assertEquals( -683858.0,   pv22.getPosition().getY(), 1.0e-10);
289         Assertions.assertEquals( 2007684.0,   pv22.getPosition().getZ(), 1.0e-10);
290         Assertions.assertEquals(    6367.86,  pv22.getVelocity().getX(), 1.0e-10);
291         Assertions.assertEquals(   -3339.563, pv22.getVelocity().getY(), 1.0e-10);
292         Assertions.assertEquals(    -946.654, pv22.getVelocity().getZ(), 1.0e-10);
293 
294         Assertions.assertEquals(2, segments.get(2).getCovarianceMatrices().size());
295         final CartesianCovariance c20 = segments.get(2).getCovarianceMatrices().get(0);
296         Assertions.assertEquals(new AbsoluteDate("1996-12-28T21:29:07.267", TimeScalesFactory.getUTC()),
297                             c20.getEpoch());
298         Assertions.assertEquals(OrbitRelativeFrame.RTN, c20.getReferenceFrame().asOrbitRelativeFrame());
299         Assertions.assertEquals( 333.13494,       c20.getCovarianceMatrix().getEntry(0, 0), 1.0e-5);
300         Assertions.assertEquals( 461.89273,       c20.getCovarianceMatrix().getEntry(1, 0), 1.0e-5);
301         Assertions.assertEquals( 678.24216,       c20.getCovarianceMatrix().getEntry(1, 1), 1.0e-5);
302         Assertions.assertEquals(-307.00078,       c20.getCovarianceMatrix().getEntry(2, 0), 1.0e-5);
303         Assertions.assertEquals(-422.12341,       c20.getCovarianceMatrix().getEntry(2, 1), 1.0e-5);
304         Assertions.assertEquals( 323.19319,       c20.getCovarianceMatrix().getEntry(2, 2), 1.0e-5);
305         Assertions.assertEquals(  -0.33493650,    c20.getCovarianceMatrix().getEntry(3, 0), 1.0e-8);
306         Assertions.assertEquals(  -0.46860842,    c20.getCovarianceMatrix().getEntry(3, 1), 1.0e-8);
307         Assertions.assertEquals(   0.24849495,    c20.getCovarianceMatrix().getEntry(3, 2), 1.0e-8);
308         Assertions.assertEquals(   0.00042960228, c20.getCovarianceMatrix().getEntry(3, 3), 1.0e-11);
309         Assertions.assertEquals(  -0.22118325,    c20.getCovarianceMatrix().getEntry(4, 0), 1.0e-8);
310         Assertions.assertEquals(  -0.28641868,    c20.getCovarianceMatrix().getEntry(4, 1), 1.0e-8);
311         Assertions.assertEquals(   0.17980986,    c20.getCovarianceMatrix().getEntry(4, 2), 1.0e-8);
312         Assertions.assertEquals(   0.00026088992, c20.getCovarianceMatrix().getEntry(4, 3), 1.0e-11);
313         Assertions.assertEquals(   0.00017675147, c20.getCovarianceMatrix().getEntry(4, 4), 1.0e-11);
314         Assertions.assertEquals(  -0.30413460,    c20.getCovarianceMatrix().getEntry(5, 0), 1.0e-8);
315         Assertions.assertEquals(  -0.49894969,    c20.getCovarianceMatrix().getEntry(5, 1), 1.0e-8);
316         Assertions.assertEquals(   0.35403109,    c20.getCovarianceMatrix().getEntry(5, 2), 1.0e-8);
317         Assertions.assertEquals(   0.00018692631, c20.getCovarianceMatrix().getEntry(5, 3), 1.0e-11);
318         Assertions.assertEquals(   0.00010088625, c20.getCovarianceMatrix().getEntry(5, 4), 1.0e-11);
319         Assertions.assertEquals(   0.00062244443, c20.getCovarianceMatrix().getEntry(5, 5), 1.0e-11);
320         for (int i = 0; i < c20.getCovarianceMatrix().getRowDimension(); ++i) {
321             for (int j = i + 1; j < c20.getCovarianceMatrix().getColumnDimension(); ++j) {
322                 Assertions.assertEquals(c20.getCovarianceMatrix().getEntry(j, i),
323                                     c20.getCovarianceMatrix().getEntry(i, j),
324                                     1.0e-10);
325             }
326         }
327 
328         final CartesianCovariance c21 = segments.get(2).getCovarianceMatrices().get(1);
329         Assertions.assertEquals(new AbsoluteDate("1996-12-29T21:00:00", TimeScalesFactory.getUTC()),
330                             c21.getEpoch());
331         Assertions.assertEquals(CelestialBodyFrame.EME2000, c21.getReferenceFrame().asCelestialBodyFrame());
332         Assertions.assertEquals( 344.24505,       c21.getCovarianceMatrix().getEntry(0, 0), 1.0e-5);
333         Assertions.assertEquals( 450.78162,       c21.getCovarianceMatrix().getEntry(1, 0), 1.0e-5);
334         Assertions.assertEquals( 689.35327,       c21.getCovarianceMatrix().getEntry(1, 1), 1.0e-5);
335         for (int i = 0; i < c21.getCovarianceMatrix().getRowDimension(); ++i) {
336             for (int j = i + 1; j < c21.getCovarianceMatrix().getColumnDimension(); ++j) {
337                 Assertions.assertEquals(c21.getCovarianceMatrix().getEntry(j, i),
338                                     c21.getCovarianceMatrix().getEntry(i, j),
339                                     1.0e-10);
340             }
341         }
342 
343     }
344 
345     @Test
346     public void testParseOEM3XML() throws IOException {
347 
348         final String ex = "/ccsds/odm/oem/OEMExample3.xml";
349         final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
350         final OemParser parser  = new ParserBuilder().withMu(CelestialBodyFactory.getMars().getGM()).buildOemParser();
351         final Oem file = parser.parseMessage(source);
352         Assertions.assertEquals("OEM 201113719185", file.getHeader().getMessageId());
353         Assertions.assertEquals("UTC", file.getSegments().get(0).getMetadata().getTimeSystem().name());
354         Assertions.assertEquals("MARS GLOBAL SURVEYOR", file.getSegments().get(0).getMetadata().getObjectName());
355         Assertions.assertEquals("2000-028A", file.getSegments().get(0).getMetadata().getObjectID());
356 
357         Assertions.assertEquals(1, file.getSatellites().size());
358         Assertions.assertEquals(true, file.getSatellites().containsKey("2000-028A"));
359         Assertions.assertEquals(false, file.getSatellites().containsKey("MARS GLOBAL SURVEYOR"));
360         Assertions.assertEquals(1, file.getSatellites().size());
361         Assertions.assertEquals("2000-028A", file.getSatellites().values().iterator().next().getId());
362         Assertions.assertEquals(
363                 new AbsoluteDate("1996-12-18T12:00:00.331", TimeScalesFactory.getUTC()),
364                 file.getSegments().get(0).getMetadata().getStartTime());
365 
366         final OemSatelliteEphemeris satellite = file.getSatellites().get("2000-028A");
367         Assertions.assertEquals("2000-028A", satellite.getId());
368         final OemSegment segment = (OemSegment) satellite.getSegments().get(0);
369         Assertions.assertEquals(CelestialBodyFactory.getMars().getGM(), segment.getMu(), 1.0);
370         Assertions.assertEquals("J2000", segment.getMetadata().getReferenceFrame().getName());
371         Assertions.assertEquals(segment.getMetadata().getCenter().getName(), "MARS BARYCENTER");
372         Assertions.assertNull(segment.getMetadata().getCenter().getBody());
373         // Frame not creatable since it's center can't be created.
374         try {
375             segment.getFrame();
376             Assertions.fail("Expected Exception");
377         } catch (OrekitException e){
378             Assertions.assertEquals(e.getSpecifier(), OrekitMessages.NO_DATA_LOADED_FOR_CELESTIAL_BODY);
379         }
380         Assertions.assertEquals("UTC", segment.getMetadata().getTimeSystem().name());
381         Assertions.assertEquals(InterpolationMethod.HERMITE, segment.getMetadata().getInterpolationMethod());
382         Assertions.assertEquals(7, segment.getMetadata().getInterpolationDegree());
383         Assertions.assertEquals(segment.getAvailableDerivatives(), CartesianDerivativesFilter.USE_PVA);
384 
385         List<OemSegment> segments = file.getSegments();
386         Assertions.assertEquals(1, segments.size());
387         Assertions.assertEquals("Produced by M.R. Sombedody, MSOO NAV/JPL, 1996 OCT 11. It is", segments.get(0).getData().getComments().get(0));
388         Assertions.assertEquals("to be used for DSN scheduling purposes only.", segments.get(0).getData().getComments().get(1));
389         Assertions.assertEquals(4, segments.get(0).getData().getCoordinates().size());
390         final TimeStampedPVCoordinates pv00 = segments.get(0).getData().getCoordinates().get(0);
391         Assertions.assertEquals(new AbsoluteDate("1996-12-18T12:00:00.331", TimeScalesFactory.getUTC()),
392                             pv00.getDate());
393         Assertions.assertEquals( 2789600.0, pv00.getPosition().getX(),     1.0e-10);
394         Assertions.assertEquals( -280000.0, pv00.getPosition().getY(),     1.0e-10);
395         Assertions.assertEquals(-1746800.0, pv00.getPosition().getZ(),     1.0e-10);
396         Assertions.assertEquals(    4730.0, pv00.getVelocity().getX(),     1.0e-10);
397         Assertions.assertEquals(   -2500.0, pv00.getVelocity().getY(),     1.0e-10);
398         Assertions.assertEquals(   -1040.0, pv00.getVelocity().getZ(),     1.0e-10);
399         Assertions.assertEquals(       8.0, pv00.getAcceleration().getX(), 1.0e-10);
400         Assertions.assertEquals(       1.0, pv00.getAcceleration().getY(), 1.0e-10);
401         Assertions.assertEquals(    -159.0, pv00.getAcceleration().getZ(), 1.0e-10);
402         final TimeStampedPVCoordinates pv01 = segments.get(0).getData().getCoordinates().get(1);
403         Assertions.assertEquals(new AbsoluteDate("1996-12-18T12:01:00.331", TimeScalesFactory.getUTC()),
404                             pv01.getDate());
405         Assertions.assertEquals( 2783400.0, pv01.getPosition().getX(),     1.0e-10);
406         Assertions.assertEquals( -308100.0, pv01.getPosition().getY(),     1.0e-10);
407         Assertions.assertEquals(-1877100.0, pv01.getPosition().getZ(),     1.0e-10);
408         Assertions.assertEquals(    5190.0, pv01.getVelocity().getX(),     1.0e-10);
409         Assertions.assertEquals(   -2420.0, pv01.getVelocity().getY(),     1.0e-10);
410         Assertions.assertEquals(   -2000.0, pv01.getVelocity().getZ(),     1.0e-10);
411         Assertions.assertEquals(       8.0, pv01.getAcceleration().getX(), 1.0e-10);
412         Assertions.assertEquals(       1.0, pv01.getAcceleration().getY(), 1.0e-10);
413         Assertions.assertEquals(       1.0, pv01.getAcceleration().getZ(), 1.0e-10);
414         final TimeStampedPVCoordinates pv02 = segments.get(0).getData().getCoordinates().get(2);
415         Assertions.assertEquals(new AbsoluteDate("1996-12-18T12:02:00.331", TimeScalesFactory.getUTC()),
416                             pv02.getDate());
417         Assertions.assertEquals( 2776000.0, pv02.getPosition().getX(),     1.0e-10);
418         Assertions.assertEquals( -336900.0, pv02.getPosition().getY(),     1.0e-10);
419         Assertions.assertEquals(-2008700.0, pv02.getPosition().getZ(),     1.0e-10);
420         Assertions.assertEquals(    5640.0, pv02.getVelocity().getX(),     1.0e-10);
421         Assertions.assertEquals(   -2340.0, pv02.getVelocity().getY(),     1.0e-10);
422         Assertions.assertEquals(   -1950.0, pv02.getVelocity().getZ(),     1.0e-10);
423         Assertions.assertEquals(       8.0, pv02.getAcceleration().getX(), 1.0e-10);
424         Assertions.assertEquals(       1.0, pv02.getAcceleration().getY(), 1.0e-10);
425         Assertions.assertEquals(     159.0, pv02.getAcceleration().getZ(), 1.0e-10);
426         final TimeStampedPVCoordinates pv03 = segments.get(0).getData().getCoordinates().get(3);
427         Assertions.assertEquals(new AbsoluteDate("1996-12-28T21:28:00.331", TimeScalesFactory.getUTC()),
428                             pv03.getDate());
429         Assertions.assertEquals(-3881000.0, pv03.getPosition().getX(),     1.0e-10);
430         Assertions.assertEquals(  564000.0, pv03.getPosition().getY(),     1.0e-10);
431         Assertions.assertEquals( -682800.0, pv03.getPosition().getZ(),     1.0e-10);
432         Assertions.assertEquals(   -3290.0, pv03.getVelocity().getX(),     1.0e-10);
433         Assertions.assertEquals(   -3670.0, pv03.getVelocity().getY(),     1.0e-10);
434         Assertions.assertEquals(    1640.0, pv03.getVelocity().getZ(),     1.0e-10);
435         Assertions.assertEquals(      -3.0, pv03.getAcceleration().getX(), 1.0e-10);
436         Assertions.assertEquals(       0.0, pv03.getAcceleration().getY(), 1.0e-10);
437         Assertions.assertEquals(       0.0, pv03.getAcceleration().getZ(), 1.0e-10);
438 
439         Assertions.assertEquals(1, segments.get(0).getCovarianceMatrices().size());
440         final CartesianCovariance c20 = segments.get(0).getCovarianceMatrices().get(0);
441         Assertions.assertEquals(new AbsoluteDate("1996-12-28T22:28:00.331", TimeScalesFactory.getUTC()),
442                             c20.getEpoch());
443         Assertions.assertEquals(CelestialBodyFrame.ITRF1997, c20.getReferenceFrame().asCelestialBodyFrame());
444         Assertions.assertEquals( 316000.0, c20.getCovarianceMatrix().getEntry(0, 0), 1.0e-10);
445         Assertions.assertEquals( 722000.0, c20.getCovarianceMatrix().getEntry(1, 0), 1.0e-10);
446         Assertions.assertEquals( 518000.0, c20.getCovarianceMatrix().getEntry(1, 1), 1.0e-10);
447         Assertions.assertEquals( 202000.0, c20.getCovarianceMatrix().getEntry(2, 0), 1.0e-10);
448         Assertions.assertEquals( 715000.0, c20.getCovarianceMatrix().getEntry(2, 1), 1.0e-10);
449         Assertions.assertEquals(   2000.0, c20.getCovarianceMatrix().getEntry(2, 2), 1.0e-10);
450         Assertions.assertEquals( 912000.0, c20.getCovarianceMatrix().getEntry(3, 0), 1.0e-10);
451         Assertions.assertEquals( 306000.0, c20.getCovarianceMatrix().getEntry(3, 1), 1.0e-10);
452         Assertions.assertEquals( 276000.0, c20.getCovarianceMatrix().getEntry(3, 2), 1.0e-10);
453         Assertions.assertEquals( 797000.0, c20.getCovarianceMatrix().getEntry(3, 3), 1.0e-10);
454         Assertions.assertEquals( 562000.0, c20.getCovarianceMatrix().getEntry(4, 0), 1.0e-10);
455         Assertions.assertEquals( 899000.0, c20.getCovarianceMatrix().getEntry(4, 1), 1.0e-10);
456         Assertions.assertEquals(  22000.0, c20.getCovarianceMatrix().getEntry(4, 2), 1.0e-10);
457         Assertions.assertEquals(  79000.0, c20.getCovarianceMatrix().getEntry(4, 3), 1.0e-10);
458         Assertions.assertEquals( 415000.0, c20.getCovarianceMatrix().getEntry(4, 4), 1.0e-10);
459         Assertions.assertEquals( 245000.0, c20.getCovarianceMatrix().getEntry(5, 0), 1.0e-10);
460         Assertions.assertEquals( 965000.0, c20.getCovarianceMatrix().getEntry(5, 1), 1.0e-10);
461         Assertions.assertEquals( 950000.0, c20.getCovarianceMatrix().getEntry(5, 2), 1.0e-10);
462         Assertions.assertEquals( 435000.0, c20.getCovarianceMatrix().getEntry(5, 3), 1.0e-10);
463         Assertions.assertEquals( 621000.0, c20.getCovarianceMatrix().getEntry(5, 4), 1.0e-10);
464         Assertions.assertEquals( 991000.0, c20.getCovarianceMatrix().getEntry(5, 5), 1.0e-10);
465         for (int i = 0; i < c20.getCovarianceMatrix().getRowDimension(); ++i) {
466             for (int j = i + 1; j < c20.getCovarianceMatrix().getColumnDimension(); ++j) {
467                 Assertions.assertEquals(c20.getCovarianceMatrix().getEntry(j, i),
468                                     c20.getCovarianceMatrix().getEntry(i, j),
469                                     1.0e-10);
470             }
471         }
472 
473     }
474 
475     @Test
476     public void testParseOemMissingOptionalData() throws IOException {
477 
478         final String ex = "/ccsds/odm/oem/OEMExample6.txt";
479         final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
480         final OemParser parser  = new ParserBuilder().withMu(CelestialBodyFactory.getMars().getGM()).buildOemParser();
481         final Oem file = parser.parseMessage(source);
482         Assertions.assertEquals("UTC", file.getSegments().get(0).getMetadata().getTimeSystem().name());
483         Assertions.assertEquals("MARS GLOBAL SURVEYOR", file.getSegments().get(0).getMetadata().getObjectName());
484         Assertions.assertEquals("1996-062A", file.getSegments().get(0).getMetadata().getObjectID());
485 
486         Assertions.assertEquals(1, file.getSatellites().size());
487         Assertions.assertEquals(true, file.getSatellites().containsKey("1996-062A"));
488         Assertions.assertEquals(false, file.getSatellites().containsKey("MARS GLOBAL SURVEYOR"));
489         Assertions.assertEquals(1, file.getSatellites().size());
490         Assertions.assertEquals("1996-062A", file.getSatellites().values().iterator().next().getId());
491         Assertions.assertEquals(
492                 new AbsoluteDate("2002-12-18T12:00:00.331", TimeScalesFactory.getUTC()),
493                 file.getSegments().get(0).getMetadata().getStartTime());
494 
495         OemSatelliteEphemeris satellite = file.getSatellites().get("1996-062A");
496         Assertions.assertEquals("1996-062A", satellite.getId());
497         OemSegment segment = satellite.getSegments().get(0);
498         Assertions.assertEquals(CelestialBodyFactory.getMars().getGM(), segment.getMu(), 1.0);
499         FactoryManagedFrame eme2000 = FramesFactory.getEME2000();
500         Frame actualFrame = segment.getFrame();
501         AbsoluteDate actualStart = satellite.getStart();
502         Transform actualTransform = eme2000.getTransformTo(actualFrame, actualStart);
503         CelestialBody mars = CelestialBodyFactory.getMars();
504         TimeStampedPVCoordinates marsPV = mars.getPVCoordinates(actualStart, eme2000);
505         TimeStampedPVCoordinates marsPV_in_marscentered_frame = mars.getPVCoordinates(actualStart, actualFrame);
506         MatcherAssert.assertThat(marsPV_in_marscentered_frame,
507                                  OrekitMatchers.pvCloseTo(PVCoordinates.ZERO, 1e-3));
508         Assertions.assertEquals(actualTransform.getTranslation(), marsPV.getPosition().negate());
509         Assertions.assertEquals(actualTransform.getVelocity(), marsPV.getVelocity().negate());
510         Assertions.assertEquals(actualTransform.getAcceleration(), marsPV.getAcceleration().negate());
511         Assertions.assertEquals(
512                 Rotation.distance(actualTransform.getRotation(), Rotation.IDENTITY),
513                 0.0, 0.0);
514         Assertions.assertEquals(actualTransform.getRotationRate(), Vector3D.ZERO);
515         Assertions.assertEquals(actualTransform.getRotationAcceleration(), Vector3D.ZERO);
516         Assertions.assertEquals("Mars/EME2000", actualFrame.getName());
517         Assertions.assertEquals(CelestialBodyFrame.EME2000, segment.getMetadata().getReferenceFrame().asCelestialBodyFrame());
518         Assertions.assertEquals("UTC", segment.getMetadata().getTimeSystem().name());
519         Assertions.assertEquals(segment.getAvailableDerivatives(),
520                 CartesianDerivativesFilter.USE_PV);
521         Assertions.assertEquals(satellite.getSegments().get(0).getMetadata().getStartTime(), actualStart);
522         Assertions.assertEquals(satellite.getSegments().get(2).getMetadata().getStopTime(), satellite.getStop());
523 
524         final BoundedPropagator propagator = satellite.getPropagator();
525         Assertions.assertEquals(propagator.getMinDate(), satellite.getStart());
526         Assertions.assertEquals(propagator.getMinDate(), satellite.getSegments().get(0).getStart());
527         Assertions.assertEquals(propagator.getMaxDate(), satellite.getStop());
528         Assertions.assertEquals(propagator.getMaxDate(), satellite.getSegments().get(2).getStop());
529 
530         final List<TimeStampedPVCoordinates> dataLines = new ArrayList<>();
531         for (OemSegment block : file.getSegments()) {
532             for (TimeStampedPVCoordinates dataLine : block.getData().getEphemeridesDataLines()) {
533                 if (dataLine.getDate().compareTo(satellite.getStart()) >= 0) {
534                     dataLines.add(dataLine);
535                 }
536             }
537         }
538 
539         final int ulps = 12;
540         for (TimeStampedPVCoordinates coord : dataLines) {
541             MatcherAssert.assertThat(propagator.getPVCoordinates(coord.getDate(), actualFrame),
542                                      OrekitMatchers.pvCloseTo(coord, ulps));
543             MatcherAssert.assertThat(propagator.propagate(coord.getDate()).getPVCoordinates(),
544                                      OrekitMatchers.pvCloseTo(coord, ulps));
545         }
546 
547     }
548 
549     @Test
550     public void testWrongODMType() {
551         try {
552             final String ex = "/ccsds/odm/oem/OEMExample1.txt";
553             final DataSource source =  new DataSource(ex, () -> getClass().getResourceAsStream(ex));
554             new ParserBuilder().
555             withMu(CelestialBodyFactory.getMars().getGM()).
556             buildOemParser().
557             parseMessage(source);
558         } catch (OrekitException oe) {
559             Assertions.assertEquals(OrekitMessages.UNSUPPORTED_FILE_FORMAT, oe.getSpecifier());
560             Assertions.assertEquals("OPMExample1.txt", oe.getParts()[0]);
561         }
562     }
563 
564     @Test
565     public void testEphemerisNumberFormatErrorType() {
566         final String ex = "/ccsds/odm/oem/OEM-ephemeris-number-format-error.txt";
567         try {
568             final DataSource source =  new DataSource(ex, () -> getClass().getResourceAsStream(ex));
569             new ParserBuilder().
570             withMu(CelestialBodyFactory.getMars().getGM()).
571             buildOemParser().
572             parseMessage(source);
573         } catch (OrekitException oe) {
574             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
575             Assertions.assertEquals(44, oe.getParts()[0]);
576             Assertions.assertEquals(ex, oe.getParts()[1]);
577             Assertions.assertEquals("1996-12-28T21:59:02.267 -2445.234 -878.141 this-is-not-a-number 1.86043 -3.421256 -0.996366", oe.getParts()[2]);
578         }
579     }
580 
581     @Test
582     public void testCovarianceNumberFormatErrorType() {
583         final String ex = "/ccsds/odm/oem/OEM-covariance-number-format-error.txt";
584         try {
585             final DataSource source =  new DataSource(ex, () -> getClass().getResourceAsStream(ex));
586             new ParserBuilder().
587             withMu(CelestialBodyFactory.getMars().getGM()).
588             buildOemParser().
589             parseMessage(source);
590         } catch (OrekitException oe) {
591             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
592             Assertions.assertEquals(52, oe.getParts()[0]);
593             Assertions.assertEquals(ex, oe.getParts()[1]);
594             Assertions.assertEquals("4.6189273e-04 this-is-not-a-number", oe.getParts()[2]);
595         }
596     }
597 
598     @Test
599     public void testNonExistentFile() throws URISyntaxException {
600         final String realName = getClass().getResource("/ccsds/odm/oem/OEMExample1.txt").toURI().getPath();
601         final String wrongName = realName + "xxxxx";
602         final DataSource source =  new DataSource(wrongName, () -> getClass().getResourceAsStream(wrongName));
603         try {
604             new ParserBuilder().
605             withMu(CelestialBodyFactory.getMars().getGM()).
606             buildOemParser().
607             parseMessage(source);
608             Assertions.fail("an exception should have been thrown");
609         } catch (OrekitException oe) {
610             Assertions.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
611             Assertions.assertEquals(wrongName, oe.getParts()[0]);
612         }
613     }
614 
615     @Test
616     public void testInconsistentTimeSystems() {
617         try {
618             final String ex = "/ccsds/odm/oem/OEM-inconsistent-time-systems.txt";
619             final DataSource source =  new DataSource(ex, () -> getClass().getResourceAsStream(ex));
620             new ParserBuilder().
621             withMu(CelestialBodyFactory.getMars().getGM()).
622             buildOemParser().
623             parseMessage(source);
624         } catch (OrekitException oe) {
625             Assertions.assertEquals(OrekitMessages.CCSDS_INCONSISTENT_TIME_SYSTEMS, oe.getSpecifier());
626             Assertions.assertEquals("UTC", oe.getParts()[0]);
627             Assertions.assertEquals("TCG", oe.getParts()[1]);
628         }
629     }
630 
631     @Test
632     public void testLowerCaseValue() {
633         //setup
634         String file = "/ccsds/odm/oem/oemLowerCaseValue.oem";
635         final DataSource source =  new DataSource(file, () -> getClass().getResourceAsStream(file));
636 
637         //action
638         final Oem actual = new ParserBuilder().
639                                withMu(CelestialBodyFactory.getMars().getGM()).
640                                buildOemParser().
641                                parseMessage(source);
642 
643         //verify
644         Assertions.assertEquals(
645                 CelestialBodyFactory.getEarth(),
646                 actual.getSegments().get(0).getMetadata().getCenter().getBody());
647     }
648 
649     @Test
650     public void testWrongKeyword()
651         throws URISyntaxException {
652         // simple test for OMM file, contains p/v entries and other mandatory
653         // data.
654         final String name = "/ccsds/odm/oem/OEM-wrong-keyword.txt";
655         final DataSource source =  new DataSource(name, () -> getClass().getResourceAsStream(name));
656         try {
657             new ParserBuilder().
658             withMu(CelestialBodyFactory.getMars().getGM()).
659             buildOemParser().
660             parseMessage(source);
661             Assertions.fail("an exception should have been thrown");
662         } catch (OrekitException oe) {
663             Assertions.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
664             Assertions.assertEquals(19, ((Integer) oe.getParts()[0]).intValue());
665             Assertions.assertTrue(((String) oe.getParts()[2]).startsWith("WRONG_KEYWORD"));
666         }
667     }
668 
669     @Test
670     public void testKeywordWithinEphemeris()
671         throws URISyntaxException {
672         // simple test for OMM file, contains p/v entries and other mandatory
673         // data.
674         final String name = "/ccsds/odm/oem/OEM-keyword-within-ephemeris.txt";
675         final DataSource source =  new DataSource(name, () -> getClass().getResourceAsStream(name));
676         try {
677             new ParserBuilder().
678             withMu(CelestialBodyFactory.getMars().getGM()).
679             buildOemParser().
680             parseMessage(source);
681             Assertions.fail("an exception should have been thrown");
682         } catch (OrekitException oe) {
683             Assertions.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
684             Assertions.assertEquals(24, ((Integer) oe.getParts()[0]).intValue());
685             Assertions.assertTrue(((String) oe.getParts()[2]).startsWith("USER_DEFINED_TEST_KEY"));
686         }
687     }
688 
689     @Test
690     public void testKeywordWithinCovariance()
691         throws URISyntaxException {
692         // simple test for OMM file, contains p/v entries and other mandatory
693         // data.
694         final String name = "/ccsds/odm/oem/OEM-keyword-within-covariance.txt";
695         final DataSource source =  new DataSource(name, () -> getClass().getResourceAsStream(name));
696         try {
697             new ParserBuilder().
698             withMu(CelestialBodyFactory.getMars().getGM()).
699             buildOemParser().
700             parseMessage(source);
701             Assertions.fail("an exception should have been thrown");
702         } catch (OrekitException oe) {
703             Assertions.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
704             Assertions.assertEquals(91, ((Integer) oe.getParts()[0]).intValue());
705             Assertions.assertTrue(((String) oe.getParts()[2]).startsWith("USER_DEFINED_TEST_KEY"));
706         }
707     }
708 
709     @Test
710     public void testTooLargeCovarianceDimension()
711         throws URISyntaxException {
712         final String name = "/ccsds/odm/oem/OEM-too-large-covariance-dimension.txt";
713         final DataSource source =  new DataSource(name, () -> getClass().getResourceAsStream(name));
714         try {
715             new ParserBuilder().
716             withMu(CelestialBodyFactory.getMars().getGM()).
717             buildOemParser().
718             parseMessage(source);
719             Assertions.fail("an exception should have been thrown");
720         } catch (OrekitException oe) {
721             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
722             Assertions.assertEquals(91, ((Integer) oe.getParts()[0]).intValue());
723             Assertions.assertTrue(((String) oe.getParts()[2]).startsWith("1.0e-12"));
724         }
725     }
726 
727     @Test
728     public void testTooSmallCovarianceDimension()
729         throws URISyntaxException {
730         final String name = "/ccsds/odm/oem/OEM-too-small-covariance-dimension.txt";
731         final DataSource source =  new DataSource(name, () -> getClass().getResourceAsStream(name));
732         try {
733             new ParserBuilder().
734             withMu(CelestialBodyFactory.getMars().getGM()).
735             buildOemParser().
736             parseMessage(source);
737             Assertions.fail("an exception should have been thrown");
738         } catch (OrekitException oe) {
739             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_ELEMENT_IN_FILE, oe.getSpecifier());
740             Assertions.assertEquals("EPOCH", oe.getParts()[0]);
741             Assertions.assertEquals(89, ((Integer) oe.getParts()[1]).intValue());
742             Assertions.assertTrue(((String) oe.getParts()[2]).endsWith("OEM-too-small-covariance-dimension.txt"));
743         }
744     }
745 
746     @Test
747     public void testTooManyCovarianceColumns()
748         throws URISyntaxException {
749         final String name = "/ccsds/odm/oem/OEM-too-many-covariance-columns.txt";
750         final DataSource source =  new DataSource(name, () -> getClass().getResourceAsStream(name));
751         try {
752             new ParserBuilder().
753             withMu(CelestialBodyFactory.getMars().getGM()).
754             buildOemParser().
755             parseMessage(source);
756             Assertions.fail("an exception should have been thrown");
757         } catch (OrekitException oe) {
758             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
759             Assertions.assertEquals(51, ((Integer) oe.getParts()[0]).intValue());
760             Assertions.assertTrue(((String) oe.getParts()[2]).startsWith("3.3313494e-04"));
761         }
762     }
763 
764     @Test
765     public void testTooFewCovarianceColumns()
766         throws URISyntaxException {
767         final String name = "/ccsds/odm/oem/OEM-too-few-covariance-columns.txt";
768         final DataSource source =  new DataSource(name, () -> getClass().getResourceAsStream(name));
769         try {
770             new ParserBuilder().
771             withMu(CelestialBodyFactory.getMars().getGM()).
772             buildOemParser().
773             parseMessage(source);
774             Assertions.fail("an exception should have been thrown");
775         } catch (OrekitException oe) {
776             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
777             Assertions.assertEquals(55, ((Integer) oe.getParts()[0]).intValue());
778             Assertions.assertTrue(((String) oe.getParts()[2]).startsWith("-2.2118325e-07"));
779         }
780     }
781 
782     /**
783      * Check if the parser enters the correct interpolation degree
784      * (the parsed one or the default if there is none)
785      */
786     @Test
787     public void testDefaultInterpolationDegree()
788         throws URISyntaxException {
789 
790         final String name = "/ccsds/odm/oem/OEMExample8.txt";
791 
792         final ParserBuilder builder = new ParserBuilder().withMu(CelestialBodyFactory.getMars().getGM());
793 
794         final DataSource source1 =  new DataSource(name, () -> getClass().getResourceAsStream(name));
795         final Oem file1 = builder.buildOemParser().parseMessage(source1);
796         Assertions.assertEquals(1, file1.getSegments().get(0).getMetadata().getInterpolationDegree());
797         Assertions.assertEquals(7, file1.getSegments().get(1).getMetadata().getInterpolationDegree());
798 
799         final DataSource source2 =  new DataSource(name, () -> getClass().getResourceAsStream(name));
800         final Oem file2 = builder.withDefaultInterpolationDegree(5).buildOemParser().parseMessage(source2);
801         Assertions.assertEquals(5, file2.getSegments().get(0).getMetadata().getInterpolationDegree());
802         Assertions.assertEquals(7, file2.getSegments().get(1).getMetadata().getInterpolationDegree());
803     }
804 
805     /**
806      * Check the parser can parse several ITRF frames. Test case for #361.
807      */
808     @Test
809     public void testITRFFrames() {
810         // setup
811         Charset utf8 = StandardCharsets.UTF_8;
812         IERSConventions conventions = IERSConventions.IERS_2010;
813         boolean simpleEop = true;
814         OemParser parser  = new ParserBuilder().
815                             withMu(CelestialBodyFactory.getMars().getGM()).
816                             buildOemParser();
817 
818         // frames to check
819         List<Pair<String, Frame>> frames = new ArrayList<>();
820         frames.add(new Pair<>("ITRF-93",  FramesFactory.getITRF(ITRFVersion.ITRF_1993, conventions, simpleEop)));
821         frames.add(new Pair<>("ITRF-97",  FramesFactory.getITRF(ITRFVersion.ITRF_1997, conventions, simpleEop)));
822         frames.add(new Pair<>("ITRF2000", FramesFactory.getITRF(ITRFVersion.ITRF_2000, conventions, simpleEop)));
823         frames.add(new Pair<>("ITRF2005", FramesFactory.getITRF(ITRFVersion.ITRF_2005, conventions, simpleEop)));
824         frames.add(new Pair<>("ITRF2008", FramesFactory.getITRF(ITRFVersion.ITRF_2008, conventions, simpleEop)));
825         frames.add(new Pair<>("ITRF2014", FramesFactory.getITRF(ITRFVersion.ITRF_2014, conventions, simpleEop)));
826 
827         for (Pair<String, Frame> frame : frames) {
828             final String frameName = frame.getFirst();
829 
830             InputStream pre    = OemParserTest.class.getResourceAsStream("/ccsds/odm/oem/OEMExample7.txt.pre");
831             InputStream middle = new ByteArrayInputStream(("REF_FRAME = " + frameName).getBytes(utf8));
832             InputStream post   = OemParserTest.class.getResourceAsStream("/ccsds/odm/oem/OEMExample7.txt.post");
833             DataSource   source = new DataSource("<patched>", () -> new SequenceInputStream(pre, new SequenceInputStream(middle, post)));
834 
835             // action
836             Oem actual = parser.parseMessage(source);
837 
838             // verify
839             OemSegment segment = actual.getSegments().get(0);
840             switch (frameName) {
841                 case "ITRF-93" :
842                     Assertions.assertEquals("ITRF1993", segment.getMetadata().getReferenceFrame().getName());
843                     break;
844                 case "ITRF-97" :
845                     Assertions.assertEquals("ITRF1997", segment.getMetadata().getReferenceFrame().getName());
846                     break;
847                 default :
848                     Assertions.assertEquals(frameName, segment.getMetadata().getReferenceFrame().getName());
849                     break;
850             }
851             // check expected frame
852             Frame actualFrame = segment.getFrame();
853             Frame expectedFrame = frame.getSecond();
854             Assertions.assertEquals(expectedFrame, actualFrame);
855             Assertions.assertEquals(expectedFrame.getTransformProvider(),
856                                 actualFrame.getTransformProvider());
857         }
858     }
859 
860     @Test
861     public void testEmptyComments() {
862         final String name = "/ccsds/odm/oem/ISS.resampled.truncated.txt";
863         final ParserBuilder builder = new ParserBuilder();
864         final DataSource source =  new DataSource(name, () -> getClass().getResourceAsStream(name));
865         final Oem iss = builder.buildOemParser().parseMessage(source);
866         Assertions.assertEquals("1998-067-A", iss.getSegments().get(0).getMetadata().getObjectID());
867         Assertions.assertEquals(23, iss.getSegments().get(0).getData().getComments().size());
868         Assertions.assertEquals("", iss.getSegments().get(0).getData().getComments().get(13));
869         Assertions.assertEquals("", iss.getSegments().get(0).getData().getComments().get(20));
870         Assertions.assertEquals(25, iss.getSegments().get(0).getData().getCoordinates().size());
871     }
872 
873 }