1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.odm.omm;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.CharArrayWriter;
21 import java.io.IOException;
22 import java.net.URISyntaxException;
23 import java.nio.charset.StandardCharsets;
24 import java.util.Arrays;
25 import java.util.Collections;
26 import java.util.HashMap;
27
28 import org.hipparchus.linear.Array2DRowRealMatrix;
29 import org.hipparchus.util.FastMath;
30 import org.hipparchus.util.MathUtils;
31 import org.junit.Assert;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.orekit.Utils;
35 import org.orekit.bodies.CelestialBodyFactory;
36 import org.orekit.data.DataContext;
37 import org.orekit.data.DataSource;
38 import org.orekit.errors.OrekitException;
39 import org.orekit.errors.OrekitMessages;
40 import org.orekit.files.ccsds.ndm.ParserBuilder;
41 import org.orekit.files.ccsds.ndm.WriterBuilder;
42 import org.orekit.files.ccsds.ndm.odm.CartesianCovariance;
43 import org.orekit.files.ccsds.ndm.odm.KeplerianElements;
44 import org.orekit.files.ccsds.ndm.odm.SpacecraftParameters;
45 import org.orekit.files.ccsds.ndm.odm.UserDefined;
46 import org.orekit.files.ccsds.utils.generation.Generator;
47 import org.orekit.files.ccsds.utils.generation.KvnGenerator;
48 import org.orekit.frames.FramesFactory;
49 import org.orekit.frames.LOFType;
50 import org.orekit.propagation.analytical.tle.TLE;
51 import org.orekit.time.AbsoluteDate;
52 import org.orekit.time.TimeScalesFactory;
53 import org.orekit.utils.Constants;
54 import org.orekit.utils.IERSConventions;
55
56 public class OmmParserTest {
57
58 @Before
59 public void setUp()
60 throws Exception {
61 Utils.setDataRoot("regular-data");
62 }
63
64 @Test
65 public void testParseOMM1() {
66
67
68 final String ex = "/ccsds/odm/omm/OMMExample1.txt";
69 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
70
71
72 final OmmParser parser = new ParserBuilder().withMu(398600e9).withDefaultMass(1000.0).buildOmmParser();
73 final Omm file = parser.parseMessage(source);
74
75
76 Assert.assertEquals(3.0, file.getHeader().getFormatVersion(), 1.0e-10);
77 Assert.assertEquals(new AbsoluteDate(2007, 03, 06, 16, 00, 00,
78 TimeScalesFactory.getUTC()),
79 file.getHeader().getCreationDate());
80 Assert.assertEquals("NOAA/USA", file.getHeader().getOriginator());
81 Assert.assertNull(file.getHeader().getMessageId());
82
83
84
85 Assert.assertEquals("GOES 9", file.getMetadata().getObjectName());
86 Assert.assertEquals("1995-025A", file.getMetadata().getObjectID());
87 Assert.assertEquals("EARTH", file.getMetadata().getCenter().getName());
88 Assert.assertNotNull(file.getMetadata().getCenter().getBody());
89 Assert.assertEquals(CelestialBodyFactory.getEarth(), file.getMetadata().getCenter().getBody());
90 Assert.assertEquals(FramesFactory.getTEME(), file.getMetadata().getFrame());
91 Assert.assertEquals("UTC", file.getMetadata().getTimeSystem().name());
92 Assert.assertEquals("SGP/SGP4", file.getMetadata().getMeanElementTheory());
93 Assert.assertEquals("TEME", file.getMetadata().getFrame().toString());
94 Assert.assertTrue(file.getData().getTLEBlock().getComments().isEmpty());
95
96
97 KeplerianElements kep = file.getData().getKeplerianElementsBlock();
98 Assert.assertEquals(new AbsoluteDate(2007, 03, 05, 10, 34, 41.4264,
99 TimeScalesFactory.getUTC()),
100 file.getDate());
101 Assert.assertEquals(1.00273272 * FastMath.PI / 43200.0, kep.getMeanMotion(), 1e-10);
102 Assert.assertEquals(0.0005013, kep.getE(), 1e-10);
103 Assert.assertEquals(FastMath.toRadians(3.0539), kep.getI(), 1e-10);
104 Assert.assertEquals(FastMath.toRadians(81.7939), kep.getRaan(), 1e-10);
105 Assert.assertEquals(FastMath.toRadians(249.2363), kep.getPa(), 1e-10);
106 Assert.assertEquals(FastMath.toRadians(150.1602), kep.getAnomaly(), 1e-10);
107 Assert.assertEquals(398600.8 * 1e9, kep.getMu(), 1e-10);
108
109
110
111 OmmTle tle = file.getData().getTLEBlock();
112 Assert.assertEquals(0, tle.getEphemerisType());
113 Assert.assertEquals('U', tle.getClassificationType());
114 int[] noradIDExpected = new int[23581];
115 int[] noradIDActual = new int[tle.getNoradID()];
116 Assert.assertEquals(noradIDExpected[0], noradIDActual[0]);
117 Assert.assertEquals(925, tle.getElementSetNumber());
118 int[] revAtEpochExpected = new int[4316];
119 int[] revAtEpochActual = new int[tle.getRevAtEpoch()];
120 Assert.assertEquals(revAtEpochExpected[0], revAtEpochActual[0]);
121 Assert.assertEquals(0.0001, tle.getBStar(), 1e-10);
122 Assert.assertEquals(-0.00000113 * FastMath.PI / 1.86624e9, tle.getMeanMotionDot(), 1e-12);
123 Assert.assertEquals(0.0 * FastMath.PI / 5.3747712e13, tle.getMeanMotionDotDot(), 1e-10);
124 Assert.assertEquals(1995, file.getMetadata().getLaunchYear());
125 Assert.assertEquals(25, file.getMetadata().getLaunchNumber());
126 Assert.assertEquals("A", file.getMetadata().getLaunchPiece());
127 file.generateKeplerianOrbit();
128 try {
129 file.generateSpacecraftState();
130 } catch (OrekitException orekitException) {
131 Assert.assertEquals(OrekitMessages.CCSDS_UNKNOWN_SPACECRAFT_MASS, orekitException.getSpecifier());
132 }
133 TLE generated = file.generateTLE();
134 Assert.assertEquals("1 23581U 95025A 07064.44075725 -.00000113 00000-0 10000-3 0 9250", generated.getLine1());
135 Assert.assertEquals("2 23581 3.0539 81.7939 0005013 249.2363 150.1602 1.00273272 43169", generated.getLine2());
136 }
137
138 @Test
139 public void testParseOMM2KVN() throws URISyntaxException {
140 String name = "/ccsds/odm/omm/OMMExample2.txt";
141 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
142 final OmmParser parser = new ParserBuilder().withMu(Constants.EIGEN5C_EARTH_MU).buildOmmParser();
143
144 validateOMM2(parser.parseMessage(source));
145 }
146
147 @Test
148 public void testParseOMM2XML() throws URISyntaxException {
149 String name = "/ccsds/odm/omm/OMMExample2.xml";
150 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
151 final OmmParser parser = new ParserBuilder().withMu(Constants.EIGEN5C_EARTH_MU).buildOmmParser();
152
153 validateOMM2(parser.parseMessage(source));
154 }
155
156 @Test
157 public void testIssue906() throws URISyntaxException {
158 String name = "/ccsds/odm/omm/OMM-with-units.xml";
159 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
160 final OmmParser parser = new ParserBuilder().withMu(Constants.EIGEN5C_EARTH_MU).buildOmmParser();
161
162 validateOMM2(parser.parseMessage(source));
163 }
164
165 @Test
166 public void testWriteOMM3() throws URISyntaxException, IOException {
167 final String name = "/ccsds/odm/omm/OMMExample2.xml";
168 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
169 OmmParser parser = new ParserBuilder().withMu(Constants.EIGEN5C_EARTH_MU).buildOmmParser();
170 final Omm original = parser.parseMessage(source);
171
172
173 final CharArrayWriter caw = new CharArrayWriter();
174 final Generator generator = new KvnGenerator(caw, OmmWriter.KVN_PADDING_WIDTH, "dummy", 60);
175 new WriterBuilder().buildOmmWriter().writeMessage(generator, original);
176
177
178 final byte[] bytes = caw.toString().getBytes(StandardCharsets.UTF_8);
179 final DataSource source2 = new DataSource(name, () -> new ByteArrayInputStream(bytes));
180 final Omm rebuilt = new ParserBuilder().buildOmmParser().parseMessage(source2);
181 validateOMM2(rebuilt);
182
183 }
184
185 private void validateOMM2(final Omm file) throws URISyntaxException {
186 Assert.assertEquals(3.0, file.getHeader().getFormatVersion(), 1.0e-10);
187 Assert.assertEquals("SGP/SGP4", file.getMetadata().getMeanElementTheory());
188 final KeplerianElements kep = file.getData().getKeplerianElementsBlock();
189 Assert.assertEquals(1.00273272, Constants.JULIAN_DAY * kep.getMeanMotion() / MathUtils.TWO_PI, 1e-10);
190 Assert.assertTrue(Double.isNaN(file.getData().getMass()));
191 CartesianCovariance covariance = file.getData().getCovarianceBlock();
192 Assert.assertEquals(FramesFactory.getTEME(), covariance.getReferenceFrame().asFrame());
193 Assert.assertEquals(6, covariance.getCovarianceMatrix().getRowDimension());
194 Assert.assertEquals(6, covariance.getCovarianceMatrix().getColumnDimension());
195 Assert.assertEquals(1995, file.getMetadata().getLaunchYear());
196 Assert.assertEquals(25, file.getMetadata().getLaunchNumber());
197 Assert.assertEquals("A", file.getMetadata().getLaunchPiece());
198 file.generateKeplerianOrbit();
199
200 Array2DRowRealMatrix covMatrix = new Array2DRowRealMatrix(6, 6);
201 double[] column1 = {
202 333.1349476038534, 461.8927349220216,
203 -307.0007847730449, -0.3349365033922630,
204 -0.2211832501084875, -0.3041346050686871
205 };
206 double[] column2 = {
207 461.8927349220216, 678.2421679971363,
208 -422.1234189514228, -0.4686084221046758,
209 -0.2864186892102733, -0.4989496988610662
210 };
211 double[] column3 = {
212 -307.0007847730449, -422.1234189514228,
213 323.1931992380369, 0.2484949578400095,
214 0.1798098699846038, 0.3540310904497689
215 };
216 double[] column4 = {
217 -0.3349365033922630, -0.4686084221046758,
218 0.2484949578400095, 0.0004296022805587290,
219 0.0002608899201686016, 0.0001869263192954590
220 };
221 double[] column5 = {
222 -0.2211832501084875, -0.2864186892102733,
223 0.1798098699846038, 0.0002608899201686016,
224 0.0001767514756338532, 0.0001008862586240695
225 };
226 double[] column6 = {
227 -0.3041346050686871, -0.4989496988610662,
228 0.3540310904497689, 0.0001869263192954590,
229 0.0001008862586240695, 0.0006224444338635500
230 };
231 covMatrix.setColumn(0, column1);
232 covMatrix.setColumn(1, column2);
233 covMatrix.setColumn(2, column3);
234 covMatrix.setColumn(3, column4);
235 covMatrix.setColumn(4, column5);
236 covMatrix.setColumn(5, column6);
237 for (int i = 0; i < 6; i++) {
238 for (int j = 0; j < 6; j++) {
239 Assert.assertEquals(covMatrix.getEntry(i, j),
240 covariance.getCovarianceMatrix().getEntry(i, j),
241 1e-15);
242 }
243 }
244
245 }
246
247 @Test
248 public void testParseOMM3() throws URISyntaxException {
249
250
251 final String name = "/ccsds/odm/omm/OMMExample3.txt";
252 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
253 final AbsoluteDate missionReferenceDate = new AbsoluteDate(2000, 1, 1, DataContext.getDefault().getTimeScales().getUTC());
254 final OmmParser parser = new ParserBuilder().
255 withMu(Constants.EIGEN5C_EARTH_MU).
256 withMissionReferenceDate(missionReferenceDate).
257 withDefaultMass(1000.0).
258 buildOmmParser();
259
260 final Omm file = parser.parseMessage(source);
261 final KeplerianElements kep = file.getData().getKeplerianElementsBlock();
262 Assert.assertEquals(2.0, file.getHeader().getFormatVersion(), 1.0e-10);
263 Assert.assertEquals(missionReferenceDate.shiftedBy(210840), file.getMetadata().getFrameEpoch());
264 Assert.assertEquals(6800e3, kep.getA(), 1e-10);
265
266 final SpacecraftParameters sp = file.getData().getSpacecraftParametersBlock();
267 Assert.assertEquals(300, sp.getMass(), 1e-10);
268 Assert.assertEquals(5, sp.getSolarRadArea(), 1e-10);
269 Assert.assertEquals(0.001, sp.getSolarRadCoeff(), 1e-10);
270
271 CartesianCovariance covariance = file.getData().getCovarianceBlock();
272 Assert.assertEquals(null, covariance.getReferenceFrame().asFrame());
273 Assert.assertEquals(null, covariance.getReferenceFrame().asCelestialBodyFrame());
274 Assert.assertEquals(LOFType.TNW, covariance.getReferenceFrame().asOrbitRelativeFrame().getLofType());
275
276 UserDefined ud = file.getData().getUserDefinedBlock();
277 HashMap<String, String> userDefinedParameters = new HashMap<String, String>();
278 userDefinedParameters.put("EARTH_MODEL", "WGS-84");
279 Assert.assertEquals(userDefinedParameters, ud.getParameters());
280 Assert.assertEquals(Arrays.asList("this is a comment", "here is another one"),
281 file.getHeader().getComments());
282 Assert.assertEquals(Collections.singletonList("this comment doesn't say much"),
283 file.getMetadata().getComments());
284 Assert.assertEquals(Collections.singletonList("the following data is what we're looking for"),
285 file.getData().getKeplerianElementsBlock().getComments());
286 Assert.assertEquals(Collections.singletonList("spacecraft data"),
287 file.getData().getSpacecraftParametersBlock().getComments());
288 Assert.assertEquals(Collections.singletonList("Covariance matrix"),
289 file.getData().getCovarianceBlock().getComments());
290 Assert.assertEquals(1995, file.getMetadata().getLaunchYear());
291 Assert.assertEquals(25, file.getMetadata().getLaunchNumber());
292 Assert.assertEquals("A", file.getMetadata().getLaunchPiece());
293 file.generateSpacecraftState();
294 file.generateKeplerianOrbit();
295
296 }
297
298 @Test
299 public void testWrongKeyword() throws URISyntaxException {
300
301
302 final String name = "/ccsds/odm/omm/OMM-wrong-keyword.txt";
303 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
304 final OmmParser parser = new ParserBuilder().
305 withMu(Constants.EIGEN5C_EARTH_MU).
306 withMissionReferenceDate(new AbsoluteDate()).
307 withDefaultMass(1000.0).
308 buildOmmParser();
309 try {
310 parser.parseMessage(source);
311 Assert.fail("an exception should have been thrown");
312 } catch (OrekitException oe) {
313 Assert.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
314 Assert.assertEquals(9, ((Integer) oe.getParts()[0]).intValue());
315 Assert.assertTrue(((String) oe.getParts()[2]).startsWith("WRONG_KEYWORD"));
316 }
317 }
318
319 @Test
320 public void testOrbitFileInterface() {
321
322 final String name = "/ccsds/odm/omm/OMMExample1.txt";
323 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
324
325
326 final OmmParser parser = new ParserBuilder().
327 withMu(398600e9).
328 withMissionReferenceDate(new AbsoluteDate()).
329 withDefaultMass(1000.0).
330 buildOmmParser();
331
332 final Omm file = parser.parseMessage(source);
333
334 final String satId = "1995-025A";
335 Assert.assertEquals(satId, file.getMetadata().getObjectID());
336
337 }
338
339 @Test
340 public void testWrongODMType() {
341 final String name = "/ccsds/odm/oem/OEMExample1.txt";
342 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
343 try {
344 new ParserBuilder().
345 withConventions(IERSConventions.IERS_1996).
346 withMu(Constants.EIGEN5C_EARTH_MU).
347 withMissionReferenceDate(new AbsoluteDate()).
348 withDefaultMass(1000.0).
349 buildOmmParser().
350 parseMessage(source);
351 } catch (OrekitException oe) {
352 Assert.assertEquals(OrekitMessages.UNSUPPORTED_FILE_FORMAT, oe.getSpecifier());
353 Assert.assertEquals(name, oe.getParts()[0]);
354 }
355 }
356
357 @Test
358 public void testNumberFormatErrorType() {
359 final String name = "/ccsds/odm/omm/OMM-number-format-error.txt";
360 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
361 try {
362 new ParserBuilder().
363 withConventions(IERSConventions.IERS_1996).
364 withMu(Constants.EIGEN5C_EARTH_MU).
365 withMissionReferenceDate(new AbsoluteDate()).
366 withDefaultMass(1000.0).
367 buildOmmParser().
368 parseMessage(source);
369 } catch (OrekitException oe) {
370 Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_ELEMENT_IN_FILE, oe.getSpecifier());
371 Assert.assertEquals("ARG_OF_PERICENTER", oe.getParts()[0]);
372 Assert.assertEquals(15, oe.getParts()[1]);
373 Assert.assertEquals(name, oe.getParts()[2]);
374 }
375 }
376
377 @Test
378 public void testNonExistentFile() throws URISyntaxException {
379 final String realName = "/ccsds/odm/omm/OMMExample1.txt";
380 final String wrongName = realName + "xxxxx";
381 final DataSource source = new DataSource(wrongName, () -> getClass().getResourceAsStream(wrongName));
382 try {
383 new ParserBuilder().
384 withConventions(IERSConventions.IERS_1996).
385 withMu(Constants.EIGEN5C_EARTH_MU).
386 withMissionReferenceDate(new AbsoluteDate()).
387 withDefaultMass(1000.0).
388 buildOmmParser().
389 parseMessage(source);
390 Assert.fail("an exception should have been thrown");
391 } catch (OrekitException oe) {
392 Assert.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
393 Assert.assertEquals(wrongName, oe.getParts()[0]);
394 }
395 }
396
397 }