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
21 import java.io.ByteArrayInputStream;
22 import java.io.StringReader;
23 import java.nio.charset.StandardCharsets;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.List;
27
28 import org.hamcrest.CoreMatchers;
29 import org.hamcrest.MatcherAssert;
30 import org.hipparchus.geometry.euclidean.threed.Vector3D;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.orekit.Utils;
34 import org.orekit.bodies.CelestialBody;
35 import org.orekit.bodies.CelestialBodyFactory;
36 import org.orekit.bodies.GeodeticPoint;
37 import org.orekit.bodies.OneAxisEllipsoid;
38 import org.orekit.data.DataContext;
39 import org.orekit.data.DataSource;
40 import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
41 import org.orekit.files.ccsds.definitions.CenterName;
42 import org.orekit.files.ccsds.definitions.FrameFacade;
43 import org.orekit.files.ccsds.definitions.ModifiedFrame;
44 import org.orekit.files.ccsds.definitions.TimeSystem;
45 import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
46 import org.orekit.files.ccsds.ndm.ParserBuilder;
47 import org.orekit.files.ccsds.ndm.WriterBuilder;
48 import org.orekit.files.ccsds.section.Header;
49 import org.orekit.files.ccsds.utils.generation.Generator;
50 import org.orekit.files.ccsds.utils.generation.KvnGenerator;
51 import org.orekit.frames.Frame;
52 import org.orekit.frames.FramesFactory;
53 import org.orekit.frames.TopocentricFrame;
54 import org.orekit.propagation.BoundedPropagator;
55 import org.orekit.time.AbsoluteDate;
56 import org.orekit.utils.Constants;
57 import org.orekit.utils.IERSConventions;
58 import org.orekit.utils.TimeStampedPVCoordinates;
59
60
61
62
63
64
65 public class StreamingOemWriterTest {
66
67 private static final double POSITION_PRECISION = 1;
68
69 private static final double VELOCITY_PRECISION = 1e-2;
70
71
72 @Before
73 public void setUp() {
74 Utils.setDataRoot("regular-data");
75 }
76
77
78
79
80 @Test
81 public void testGuessCenter() {
82
83
84 List<CenterName> centerNames = new ArrayList<>(Arrays.asList(CenterName.values()));
85 centerNames.remove(CenterName.EARTH_MOON);
86 for (CenterName centerName : centerNames) {
87 CelestialBody body = centerName.getCelestialBody();
88 String name = centerName.name().replace('_', ' ');
89 MatcherAssert.assertThat(CenterName.guessCenter(body.getInertiallyOrientedFrame()),
90 CoreMatchers.is(name));
91 MatcherAssert.assertThat(CenterName.guessCenter(body.getBodyOrientedFrame()),
92 CoreMatchers.is(name));
93 }
94
95 CelestialBody emb = CenterName.EARTH_MOON.getCelestialBody();
96 MatcherAssert.assertThat(CenterName.guessCenter(emb.getInertiallyOrientedFrame()),
97 CoreMatchers.is("EARTH-MOON BARYCENTER"));
98 MatcherAssert.assertThat(CenterName.guessCenter(emb.getBodyOrientedFrame()),
99 CoreMatchers.is("EARTH-MOON BARYCENTER"));
100
101 ModifiedFrame frame = new ModifiedFrame(FramesFactory.getEME2000(),
102 CelestialBodyFrame.EME2000,
103 CelestialBodyFactory.getMars(), "MARS");
104 MatcherAssert.assertThat(CenterName.guessCenter(frame), CoreMatchers.is("MARS"));
105
106
107 Frame topo = new TopocentricFrame(new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
108 Constants.WGS84_EARTH_FLATTENING,
109 FramesFactory.getITRF(IERSConventions.IERS_2010, true)),
110 new GeodeticPoint(1.2, 2.3, 45.6),
111 "dummy");
112 MatcherAssert.assertThat(CenterName.guessCenter(topo), CoreMatchers.is("UNKNOWN"));
113 }
114
115
116
117
118
119
120
121
122 @Test
123 public void testWriteOemStepHandler() throws Exception {
124
125 List<String> files =
126 Arrays.asList("/ccsds/odm/oem/OEMExample5.txt", "/ccsds/odm/oem/OEMExample4.txt");
127 for (final String ex : files) {
128 final DataSource source0 = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
129 final OemParser parser = new ParserBuilder().withMu(CelestialBodyFactory.getEarth().getGM()).buildOemParser();
130 Oem oem = parser.parseMessage(source0);
131
132 OemSatelliteEphemeris satellite = oem.getSatellites().values().iterator().next();
133 OemSegment ephemerisBlock = satellite.getSegments().get(0);
134 double step = ephemerisBlock.
135 getMetadata().
136 getStopTime().
137 durationFrom(ephemerisBlock.getMetadata().getStartTime()) /
138 (ephemerisBlock.getCoordinates().size() - 1);
139 String originator = oem.getHeader().getOriginator();
140 OemSegment block = oem.getSegments().get(0);
141 String objectName = block.getMetadata().getObjectName();
142 String objectID = block.getMetadata().getObjectID();
143
144 Header header = new Header(3.0);
145 header.setOriginator(originator);
146 OemMetadata metadata = new OemMetadata(1);
147 metadata.setObjectName(objectName);
148 metadata.setObjectID(objectID);
149 metadata.setTimeSystem(TimeSystem.UTC);
150 metadata.setCenter(ephemerisBlock.getMetadata().getCenter());
151 metadata.setReferenceFrame(FrameFacade.map(FramesFactory.getEME2000()));
152 metadata.setStartTime(AbsoluteDate.J2000_EPOCH.shiftedBy(80 * Constants.JULIAN_CENTURY));
153 metadata.setStopTime(metadata.getStartTime().shiftedBy(Constants.JULIAN_YEAR));
154
155
156
157 final StringBuilder buffer1 = new StringBuilder();
158 StreamingOemWriter writer = new StreamingOemWriter(new KvnGenerator(buffer1, OemWriter.KVN_PADDING_WIDTH, "some-name", 60),
159 new WriterBuilder().buildOemWriter(),
160 header, metadata);
161 BoundedPropagator propagator = satellite.getPropagator();
162 propagator.setStepHandler(step, writer.newSegment());
163 propagator.propagate(propagator.getMinDate(), propagator.getMaxDate());
164 writer.close();
165
166
167 final DataSource source1 = new DataSource("buffer",
168 () -> new ByteArrayInputStream(buffer1.toString().getBytes(StandardCharsets.UTF_8)));
169 Oem generatedOem = new ParserBuilder().
170 withConventions(IERSConventions.IERS_2010).
171 withSimpleEOP(true).
172 withDataContext(DataContext.getDefault()).
173 withMu(CelestialBodyFactory.getEarth().getGM()).
174 withDefaultInterpolationDegree(1).
175 buildOemParser().
176 parseMessage(source1);
177 compareOems(oem, generatedOem, POSITION_PRECISION, VELOCITY_PRECISION);
178
179
180 final StringBuilder buffer2 = new StringBuilder();
181 OemWriter oemWriter = new WriterBuilder().buildOemWriter();
182 try (Generator generator = new KvnGenerator(buffer2, OemWriter.KVN_PADDING_WIDTH, "another-name", 60)) {
183 oemWriter.writeHeader(generator, header);
184 metadata.setObjectName(objectName);
185 metadata.setStartTime(block.getStart());
186 metadata.setStopTime(block.getStop());
187 final Frame stateFrame = satellite.getPropagator().getFrame();
188 metadata.setReferenceFrame(FrameFacade.map(stateFrame));
189 oemWriter.writeMetadata(generator, metadata);
190 for (TimeStampedPVCoordinates coordinate : block.getCoordinates()) {
191 oemWriter.writeOrbitEphemerisLine(generator, metadata, coordinate, true);
192 }
193 }
194
195
196 final DataSource source2 = new DataSource("buffer",
197 () -> new ByteArrayInputStream(buffer2.toString().getBytes(StandardCharsets.UTF_8)));
198 generatedOem = new ParserBuilder().
199 withConventions(IERSConventions.IERS_2010).
200 withSimpleEOP(true).
201 withDataContext(DataContext.getDefault()).
202 withMu(CelestialBodyFactory.getEarth().getGM()).
203 withDefaultInterpolationDegree(1).
204 withParsedUnitsBehavior(ParsedUnitsBehavior.STRICT_COMPLIANCE).
205 buildOemParser().
206 parseMessage(source2);
207 compareOems(oem, generatedOem, POSITION_PRECISION, VELOCITY_PRECISION);
208
209 }
210
211 }
212
213 @Test
214 public void testWriteOemEcfNoInterpolation() {
215
216 String path = "/ccsds/odm/oem/OEMExample5.txt";
217 DataSource source = new DataSource(path, () -> getClass().getResourceAsStream(path));
218 final OemParser oemParser = new ParserBuilder().buildOemParser();
219 final Oem original = oemParser.parse(source);
220 final OemSatelliteEphemeris originalEphem =
221 original.getSatellites().values().iterator().next();
222 final BoundedPropagator propagator = originalEphem.getPropagator();
223 StringBuilder buffer = new StringBuilder();
224 Header header = original.getHeader();
225 OemMetadata metadata = original.getSegments().get(0).getMetadata();
226 metadata.setTimeSystem(TimeSystem.UTC);
227 metadata.setReferenceFrame(FrameFacade.map(FramesFactory.getITRF(IERSConventions.IERS_2010, true)));
228 metadata.setInterpolationMethod(null);
229 metadata.setInterpolationDegree(-1);
230
231
232 StreamingOemWriter writer = new StreamingOemWriter(
233 new KvnGenerator(buffer, OemWriter.KVN_PADDING_WIDTH, "out", 0),
234 new WriterBuilder().buildOemWriter(),
235 header,
236 metadata,
237 false,
238 false);
239 propagator.setStepHandler(30 * 60, writer.newSegment());
240 propagator.propagate(propagator.getMinDate(), propagator.getMaxDate());
241
242
243 String actualText = buffer.toString();
244 String expectedPath = "/ccsds/odm/oem/OEMExample5ITRF.txt";
245 Oem expected = oemParser.parse(
246 new DataSource(expectedPath, () -> getClass().getResourceAsStream(expectedPath)));
247 Oem actual = oemParser.parse(
248 new DataSource("mem", () -> new StringReader(actualText)));
249
250 compareOems(expected, actual, 1e-6, 1e-9);
251 MatcherAssert.assertThat(
252 actualText,
253 CoreMatchers.not(CoreMatchers.containsString("INTERPOLATION_DEGREE")));
254
255 MatcherAssert.assertThat(
256 actualText,
257 CoreMatchers.containsString(
258 "\n2017-04-11T22:31:43.121856 -2757.3016318893897 -4173.479601381253 4566.01849801963 6.625901653953951 -1.011817208875361 3.0698336591568833\n"));
259 }
260
261 private static void compareOemEphemerisBlocks(OemSegment block1,
262 OemSegment block2,
263 double p_tol,
264 double v_tol) {
265 compareOemEphemerisBlocksMetadata(block1.getMetadata(), block2.getMetadata());
266 assertEquals(block1.getStart(), block2.getStart());
267 assertEquals(block1.getStop(), block2.getStop());
268 assertEquals(block1.getData().getEphemeridesDataLines().size(), block2.getData().getEphemeridesDataLines().size());
269 for (int i = 0; i < block1.getData().getEphemeridesDataLines().size(); i++) {
270 TimeStampedPVCoordinates c1 = block1.getData().getEphemeridesDataLines().get(i);
271 TimeStampedPVCoordinates c2 = block2.getData().getEphemeridesDataLines().get(i);
272 assertEquals("" + i, c1.getDate(), c2.getDate());
273 assertEquals(c1.getPosition() + " -> " + c2.getPosition(), 0.0,
274 Vector3D.distance(c1.getPosition(), c2.getPosition()), p_tol);
275 assertEquals(c1.getVelocity() + " -> " + c2.getVelocity(), 0.0,
276 Vector3D.distance(c1.getVelocity(), c2.getVelocity()), v_tol);
277 }
278
279 }
280
281 private static void compareOemEphemerisBlocksMetadata(OemMetadata meta1, OemMetadata meta2) {
282 assertEquals(meta1.getObjectID(), meta2.getObjectID());
283 assertEquals(meta1.getObjectName(), meta2.getObjectName());
284 assertEquals(meta1.getCenter().getName(), meta2.getCenter().getName());
285 assertEquals(meta1.getReferenceFrame().asFrame(), meta2.getReferenceFrame().asFrame());
286 assertEquals(meta1.getReferenceFrame().asCelestialBodyFrame(), meta2.getReferenceFrame().asCelestialBodyFrame());
287 assertEquals(meta1.getReferenceFrame().asOrbitRelativeFrame(), meta2.getReferenceFrame().asOrbitRelativeFrame());
288 assertEquals(meta1.getReferenceFrame().asSpacecraftBodyFrame(), meta2.getReferenceFrame().asSpacecraftBodyFrame());
289 assertEquals(meta1.getTimeSystem().name(), meta2.getTimeSystem().name());
290 }
291
292 static void compareOems(Oem file1, Oem file2, double p_tol, double v_tol) {
293 assertEquals(file1.getHeader().getOriginator(), file2.getHeader().getOriginator());
294 assertEquals(file1.getSegments().size(), file2.getSegments().size());
295 for (int i = 0; i < file1.getSegments().size(); i++) {
296 compareOemEphemerisBlocks(file1.getSegments().get(i), file2.getSegments().get(i), p_tol, v_tol);
297 }
298 }
299
300 }