1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.odm.oem;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.fail;
22
23 import java.io.BufferedReader;
24 import java.io.BufferedWriter;
25 import java.io.ByteArrayInputStream;
26 import java.io.CharArrayWriter;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.nio.charset.StandardCharsets;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35
36 import org.hipparchus.geometry.euclidean.threed.Vector3D;
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.orekit.Utils;
40 import org.orekit.bodies.CelestialBodyFactory;
41 import org.orekit.data.DataContext;
42 import org.orekit.data.DataSource;
43 import org.orekit.errors.OrekitIllegalArgumentException;
44 import org.orekit.errors.OrekitMessages;
45 import org.orekit.files.ccsds.definitions.BodyFacade;
46 import org.orekit.files.ccsds.definitions.FrameFacade;
47 import org.orekit.files.ccsds.definitions.TimeSystem;
48 import org.orekit.files.ccsds.ndm.ParserBuilder;
49 import org.orekit.files.ccsds.ndm.WriterBuilder;
50 import org.orekit.files.ccsds.ndm.odm.CartesianCovariance;
51 import org.orekit.files.ccsds.utils.FileFormat;
52 import org.orekit.files.ccsds.utils.generation.Generator;
53 import org.orekit.files.ccsds.utils.generation.KvnGenerator;
54 import org.orekit.files.ccsds.utils.generation.XmlGenerator;
55 import org.orekit.files.general.EphemerisFile;
56 import org.orekit.frames.Frame;
57 import org.orekit.frames.FramesFactory;
58 import org.orekit.time.AbsoluteDate;
59 import org.orekit.utils.Constants;
60 import org.orekit.utils.IERSConventions;
61 import org.orekit.utils.TimeStampedPVCoordinates;
62
63 public class EphemerisWriterTest {
64
65
66 private static final double POSITION_PRECISION = 1;
67
68 private static final double VELOCITY_PRECISION = 1e-2;
69
70 @Before
71 public void setUp() throws Exception {
72 Utils.setDataRoot("regular-data");
73 }
74
75 @Test
76 public void testOEMWriter() {
77 assertNotNull(new WriterBuilder().buildOemWriter());
78 }
79
80 @Test
81 public void testWriteOEM1Kvn() throws IOException {
82 final CharArrayWriter caw = new CharArrayWriter();
83 final Generator generator = new KvnGenerator(caw, 0, "", 60);
84 doTestWriteOEM1(caw, generator);
85 }
86
87 @Test
88 public void testWriteOEM1Xml() throws IOException {
89 final CharArrayWriter caw = new CharArrayWriter();
90 final Generator generator = new XmlGenerator(caw, 2, "", true);
91 doTestWriteOEM1(caw, generator);
92 }
93
94 private void doTestWriteOEM1(final CharArrayWriter caw, Generator generator) throws IOException {
95 final String ex = "/ccsds/odm/oem/OEMExample1.txt";
96 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
97 final OemParser parser = new ParserBuilder().withMu(CelestialBodyFactory.getMars().getGM()).buildOemParser();
98 final Oem oem = parser.parseMessage(source);
99
100 OemWriter writer = new WriterBuilder().
101 withConventions(IERSConventions.IERS_2010).
102 withDataContext(DataContext.getDefault()).
103 buildOemWriter();
104 writer.writeMessage(generator, oem);
105 final byte[] bytes = caw.toString().getBytes(StandardCharsets.UTF_8);
106
107 final Oem generatedOem = new ParserBuilder().
108 withConventions(IERSConventions.IERS_2010).
109 withSimpleEOP(true).
110 withDataContext(DataContext.getDefault()).
111 withMu(CelestialBodyFactory.getMars().getGM()).
112 withDefaultInterpolationDegree(1).
113 buildOemParser().
114 parseMessage(new DataSource("", () -> new ByteArrayInputStream(bytes)));
115 compareOems(oem, generatedOem);
116 }
117
118 @Test
119 public void testUnfoundSpaceId() throws IOException {
120 final String ex = "/ccsds/odm/oem/OEMExample1.txt";
121 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
122 final OemParser parser = new ParserBuilder().withMu(CelestialBodyFactory.getEarth().getGM()).buildOemParser();
123 final Oem oem = parser.parseMessage(source);
124
125 EphemerisWriter writer = new EphemerisWriter(new WriterBuilder().buildOemWriter(),
126 oem.getHeader(), dummyMetadata(), FileFormat.KVN, "", 0);
127 try {
128 writer.write(new CharArrayWriter(), oem);
129 fail("an exception should have been thrown");
130 } catch (OrekitIllegalArgumentException oiae) {
131 assertEquals(OrekitMessages.VALUE_NOT_FOUND, oiae.getSpecifier());
132 assertEquals(dummyMetadata().getObjectID(), oiae.getParts()[0]);
133 }
134
135 }
136
137 @Test
138 public void testNullFile() throws IOException {
139 final String ex = "/ccsds/odm/oem/OEMExample1.txt";
140 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
141 final OemParser parser = new ParserBuilder().withMu(CelestialBodyFactory.getEarth().getGM()).buildOemParser();
142 final Oem oem = parser.parseMessage(source);
143 EphemerisWriter writer = new EphemerisWriter(new WriterBuilder().buildOemWriter(),
144 oem.getHeader(),
145 oem.getSegments().get(0).getMetadata(),
146 FileFormat.KVN, "dummy", 0);
147 try {
148 writer.write((BufferedWriter) null, oem);
149 fail("an exception should have been thrown");
150 } catch (OrekitIllegalArgumentException oiae) {
151 assertEquals(OrekitMessages.NULL_ARGUMENT, oiae.getSpecifier());
152 assertEquals("writer", oiae.getParts()[0]);
153 }
154 }
155
156 @Test
157 public void testNullEphemeris() throws IOException {
158 EphemerisWriter writer = new EphemerisWriter(new WriterBuilder().buildOemWriter(),
159 null, dummyMetadata(), FileFormat.KVN, "nullEphemeris", 60);
160 CharArrayWriter caw = new CharArrayWriter();
161 writer.write(caw, null);
162 assertEquals(0, caw.size());
163 }
164
165 @Test
166 public void testUnisatelliteFileWithDefault() throws IOException {
167 final String ex = "/ccsds/odm/oem/OEMExample1.txt";
168 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
169 final OemParser parser = new ParserBuilder().withMu(CelestialBodyFactory.getEarth().getGM()).buildOemParser();
170 final Oem oem = parser.parseMessage(source);
171
172 OemWriter writer = new WriterBuilder().buildOemWriter();
173 final CharArrayWriter caw = new CharArrayWriter();
174 writer.writeMessage(new KvnGenerator(caw, 0, "", 60), oem);
175 final byte[] bytes = caw.toString().getBytes(StandardCharsets.UTF_8);
176
177 final Oem generatedOem = new ParserBuilder().
178 withMu(CelestialBodyFactory.getEarth().getGM()).
179 buildOemParser().
180 parseMessage(new DataSource("", () -> new ByteArrayInputStream(bytes)));
181 assertEquals(oem.getSegments().get(0).getMetadata().getObjectID(),
182 generatedOem.getSegments().get(0).getMetadata().getObjectID());
183 }
184
185 @Test
186 public void testIssue723() throws IOException {
187 final String ex = "/ccsds/odm/oem/OEMExampleWithHeaderComment.txt";
188 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
189 final OemParser parser = new ParserBuilder().withMu(CelestialBodyFactory.getEarth().getGM()).buildOemParser();
190 final Oem oem = parser.parseMessage(source);
191
192 EphemerisWriter writer = new EphemerisWriter(new WriterBuilder().buildOemWriter(),
193 oem.getHeader(),
194 oem.getSegments().get(0).getMetadata(),
195 FileFormat.KVN, "TestOEMIssue723.aem", 0);
196 final CharArrayWriter caw = new CharArrayWriter();
197 writer.write(caw, oem);
198 final byte[] bytes = caw.toString().getBytes(StandardCharsets.UTF_8);
199
200 final Oem generatedOem = new ParserBuilder().
201 withMu(CelestialBodyFactory.getEarth().getGM()).
202 buildOemParser().
203 parseMessage(new DataSource("", () -> new ByteArrayInputStream(bytes)));
204 assertEquals(oem.getHeader().getComments().get(0), generatedOem.getHeader().getComments().get(0));
205 }
206
207
208
209
210
211
212 @Test
213 public void testWriteOemFormat() throws IOException {
214
215 String exampleFile = "/ccsds/odm/oem/OEMExample4.txt";
216 final DataSource source = new DataSource(exampleFile, () -> getClass().getResourceAsStream(exampleFile));
217 final OemParser parser = new ParserBuilder().withMu(CelestialBodyFactory.getEarth().getGM()).buildOemParser();
218 Oem oem = parser.parseMessage(source);
219
220 OemWriter writer = new WriterBuilder().buildOemWriter();
221 final CharArrayWriter caw = new CharArrayWriter();
222 writer.writeMessage(new KvnGenerator(caw, 0, "", 60), oem);
223
224 String[] lines2 = caw.toString().split("\n");
225 assertEquals("2002-12-18T12:00:00.331 2789.619 -280.045 -1746.755 4.73372 -2.49586 -1.0419499999999997", lines2[21]);
226 assertEquals("2002-12-18T12:01:00.331 2783.419 -308.143 -1877.071 5.18604 -2.42124 -1.99608", lines2[22]);
227 assertEquals("2002-12-18T12:02:00.331 2776.033 -336.859 -2008.682 5.63678 -2.33951 -1.94687", lines2[23]);
228
229 }
230
231 @Test
232 public void testMultisatelliteFile() throws IOException {
233
234 final DataContext context = DataContext.getDefault();
235 final String id1 = "1999-012A";
236 final String id2 = "1999-012B";
237 StandAloneEphemerisFile file = new StandAloneEphemerisFile();
238 file.generate(id1, id1 + "-name", context.getFrames().getEME2000(),
239 new TimeStampedPVCoordinates(AbsoluteDate.GALILEO_EPOCH,
240 new Vector3D(1.0e6, 2.0e6, 3.0e6),
241 new Vector3D(-300, -200, -100)),
242 900.0, 60.0);
243 file.generate(id2, id2 + "-name", context.getFrames().getEME2000(),
244 new TimeStampedPVCoordinates(AbsoluteDate.GALILEO_EPOCH,
245 new Vector3D(3.0e6, 2.0e6, -1.0e6),
246 new Vector3D(-17, -20, 150)),
247 600.0, 10.0);
248
249
250 OemMetadata metadata = dummyMetadata();
251 metadata.setObjectID(id2);
252 EphemerisWriter writer = new EphemerisWriter(new WriterBuilder().withDataContext(context).buildOemWriter(),
253 null, metadata, FileFormat.KVN, "", -1);
254 final CharArrayWriter caw = new CharArrayWriter();
255 writer.write(caw, file);
256 final byte[] bytes = caw.toString().getBytes(StandardCharsets.UTF_8);
257
258 int count = 0;
259 try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
260 InputStreamReader isr = new InputStreamReader(bais, StandardCharsets.UTF_8);
261 BufferedReader br = new BufferedReader(isr)) {
262 for (String line = br.readLine(); line != null; line = br.readLine()) {
263 ++count;
264 }
265 }
266 assertEquals(80, count);
267
268 }
269
270 private static void compareOemEphemerisBlocks(OemSegment block1, OemSegment block2) {
271 compareOemEphemerisBlocksMetadata(block1.getMetadata(), block2.getMetadata());
272 assertEquals(block1.getStart(), block2.getStart());
273 assertEquals(block1.getStop(), block2.getStop());
274 assertEquals(block1.getMetadata().getInterpolationDegree(), block2.getMetadata().getInterpolationDegree());
275 assertEquals(block1.getMetadata().getInterpolationMethod(), block2.getMetadata().getInterpolationMethod());
276 assertEquals(block1.getData().getEphemeridesDataLines().size(), block2.getData().getEphemeridesDataLines().size());
277 for (int i = 0; i < block1.getData().getEphemeridesDataLines().size(); i++) {
278 TimeStampedPVCoordinates c1 = block1.getData().getEphemeridesDataLines().get(i);
279 TimeStampedPVCoordinates c2 = block2.getData().getEphemeridesDataLines().get(i);
280 assertEquals(c1.getDate(), c2.getDate());
281 assertEquals(c1.getPosition() + " -> " + c2.getPosition(), 0.0,
282 Vector3D.distance(c1.getPosition(), c2.getPosition()), POSITION_PRECISION);
283 assertEquals(c1.getVelocity() + " -> " + c2.getVelocity(), 0.0,
284 Vector3D.distance(c1.getVelocity(), c2.getVelocity()), VELOCITY_PRECISION);
285 }
286 assertEquals(block1.getCovarianceMatrices().size(), block2.getCovarianceMatrices().size());
287 for (int j = 0; j < block1.getCovarianceMatrices().size(); j++) {
288 CartesianCovariance covMat1 = block1.getCovarianceMatrices().get(j);
289 CartesianCovariance covMat2 = block2.getCovarianceMatrices().get(j);
290 assertEquals(covMat1.getEpoch(), covMat2.getEpoch());
291 assertEquals(covMat1.getReferenceFrame().asFrame(), covMat2.getReferenceFrame().asFrame());
292 assertEquals(covMat1.getReferenceFrame().asCelestialBodyFrame(), covMat2.getReferenceFrame().asCelestialBodyFrame());
293 assertEquals(covMat1.getReferenceFrame().asOrbitRelativeFrame(), covMat2.getReferenceFrame().asOrbitRelativeFrame());
294 assertEquals(covMat1.getReferenceFrame().asSpacecraftBodyFrame(), covMat2.getReferenceFrame().asSpacecraftBodyFrame());
295 assertEquals(covMat1.getCovarianceMatrix(),covMat2.getCovarianceMatrix());
296 }
297 }
298
299 private static void compareOemEphemerisBlocksMetadata(OemMetadata meta1, OemMetadata meta2) {
300 assertEquals(meta1.getObjectID(), meta2.getObjectID());
301 assertEquals(meta1.getObjectName(), meta2.getObjectName());
302 assertEquals(meta1.getCenter().getName(), meta2.getCenter().getName());
303 assertEquals(meta1.getReferenceFrame().asFrame(), meta2.getReferenceFrame().asFrame());
304 assertEquals(meta1.getReferenceFrame().asCelestialBodyFrame(), meta2.getReferenceFrame().asCelestialBodyFrame());
305 assertEquals(meta1.getReferenceFrame().asOrbitRelativeFrame(), meta2.getReferenceFrame().asOrbitRelativeFrame());
306 assertEquals(meta1.getReferenceFrame().asSpacecraftBodyFrame(), meta2.getReferenceFrame().asSpacecraftBodyFrame());
307 assertEquals(meta1.getTimeSystem().name(), meta2.getTimeSystem().name());
308 }
309
310 static void compareOems(Oem file1, Oem file2) {
311 assertEquals(file1.getHeader().getOriginator(), file2.getHeader().getOriginator());
312 assertEquals(file1.getSegments().size(), file2.getSegments().size());
313 for (int i = 0; i < file1.getSegments().size(); i++) {
314 compareOemEphemerisBlocks(file1.getSegments().get(i), file2.getSegments().get(i));
315 }
316 }
317
318 private class StandAloneEphemerisFile
319 implements EphemerisFile<TimeStampedPVCoordinates, OemSegment> {
320 private final Map<String, OemSatelliteEphemeris> satEphem;
321
322
323
324 public StandAloneEphemerisFile() {
325 this.satEphem = new HashMap<String, OemSatelliteEphemeris>();
326 }
327
328 private void generate(final String objectID, final String objectName,
329 final Frame referenceFrame, final TimeStampedPVCoordinates pv0,
330 final double duration, final double step) {
331
332 OemMetadata metadata = dummyMetadata();
333 metadata.addComment("metadata for " + objectName);
334 metadata.setObjectID(objectID);
335 metadata.setObjectName(objectName);
336 metadata.setStartTime(pv0.getDate());
337 metadata.setStopTime(pv0.getDate().shiftedBy(duration));
338 metadata.setUseableStartTime(metadata.getStartTime().shiftedBy(step));
339 metadata.setUseableStartTime(metadata.getStopTime().shiftedBy(-step));
340
341 OemData data = new OemData();
342 data.addComment("generated data for " + objectName);
343 data.addComment("duration was set to " + duration + " s");
344 data.addComment("step was set to " + step + " s");
345 for (double dt = 0; dt < duration; dt += step) {
346 data.addData(pv0.shiftedBy(dt), false);
347 }
348
349 if (!satEphem.containsKey(objectID)) {
350 satEphem.put(objectID,
351 new OemSatelliteEphemeris(objectID, Constants.EIGEN5C_EARTH_MU, Collections.emptyList()));
352 }
353
354 List<OemSegment> segments =
355 new ArrayList<>(satEphem.get(objectID).getSegments());
356 segments.add(new OemSegment(metadata, data, Constants.EIGEN5C_EARTH_MU));
357 satEphem.put(objectID, new OemSatelliteEphemeris(objectID, Constants.EIGEN5C_EARTH_MU, segments));
358
359 }
360
361 @Override
362 public Map<String, OemSatelliteEphemeris> getSatellites() {
363 return satEphem;
364 }
365
366 }
367
368 private OemMetadata dummyMetadata() {
369 OemMetadata metadata = new OemMetadata(4);
370 metadata.addComment("dummy comment");
371 metadata.setTimeSystem(TimeSystem.TT);
372 metadata.setObjectID("9999-999ZZZ");
373 metadata.setObjectName("transgalactic");
374 metadata.setCenter(new BodyFacade("EARTH", CelestialBodyFactory.getCelestialBodies().getEarth()));
375 metadata.setReferenceFrame(FrameFacade.map(FramesFactory.getEME2000()));
376 metadata.setStartTime(AbsoluteDate.J2000_EPOCH.shiftedBy(80 * Constants.JULIAN_CENTURY));
377 metadata.setStopTime(metadata.getStartTime().shiftedBy(Constants.JULIAN_YEAR));
378 return metadata;
379 }
380
381 }