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 java.io.ByteArrayInputStream;
20 import java.io.StringReader;
21 import java.nio.charset.StandardCharsets;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.List;
25
26 import org.hamcrest.CoreMatchers;
27 import org.hamcrest.MatcherAssert;
28 import org.hipparchus.geometry.euclidean.threed.Vector3D;
29 import org.junit.jupiter.api.Assertions;
30 import org.junit.jupiter.api.BeforeEach;
31 import org.junit.jupiter.api.Test;
32 import org.orekit.Utils;
33 import org.orekit.attitudes.FrameAlignedProvider;
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.ndm.odm.OdmHeader;
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 @BeforeEach
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 Frame frame = satellite.getSegments().get(0).getInertialFrame();
144
145 OdmHeader header = new OdmHeader();
146 header.setOriginator(originator);
147 OemMetadata metadata = new OemMetadata(1);
148 metadata.setObjectName(objectName);
149 metadata.setObjectID(objectID);
150 metadata.setTimeSystem(TimeSystem.UTC);
151 metadata.setCenter(ephemerisBlock.getMetadata().getCenter());
152 metadata.setReferenceFrame(FrameFacade.map(FramesFactory.getEME2000()));
153 metadata.setStartTime(AbsoluteDate.J2000_EPOCH.shiftedBy(80 * Constants.JULIAN_CENTURY));
154 metadata.setStopTime(metadata.getStartTime().shiftedBy(Constants.JULIAN_YEAR));
155
156
157
158 final StringBuilder buffer1 = new StringBuilder();
159 StreamingOemWriter writer = new StreamingOemWriter(new KvnGenerator(buffer1, OemWriter.KVN_PADDING_WIDTH, "some-name",
160 Constants.JULIAN_DAY, 60),
161 new WriterBuilder().buildOemWriter(),
162 header, metadata);
163 BoundedPropagator propagator = satellite.getPropagator(new FrameAlignedProvider(frame));
164 propagator.setStepHandler(step, writer.newSegment());
165 propagator.propagate(propagator.getMinDate(), propagator.getMaxDate());
166 writer.close();
167
168
169 final DataSource source1 = new DataSource("buffer",
170 () -> new ByteArrayInputStream(buffer1.toString().getBytes(StandardCharsets.UTF_8)));
171 Oem generatedOem = new ParserBuilder().
172 withConventions(IERSConventions.IERS_2010).
173 withSimpleEOP(true).
174 withDataContext(DataContext.getDefault()).
175 withMu(CelestialBodyFactory.getEarth().getGM()).
176 withDefaultInterpolationDegree(1).
177 buildOemParser().
178 parseMessage(source1);
179 compareOems(oem, generatedOem, POSITION_PRECISION, VELOCITY_PRECISION);
180
181
182 final StringBuilder buffer2 = new StringBuilder();
183 OemWriter oemWriter = new WriterBuilder().buildOemWriter();
184 try (Generator generator = new KvnGenerator(buffer2, OemWriter.KVN_PADDING_WIDTH, "another-name",
185 Constants.JULIAN_DAY, 60)) {
186 oemWriter.writeHeader(generator, header);
187 metadata.setObjectName(objectName);
188 metadata.setStartTime(block.getStart());
189 metadata.setStopTime(block.getStop());
190 metadata.setReferenceFrame(FrameFacade.map(frame));
191 oemWriter.writeMetadata(generator, metadata);
192 for (TimeStampedPVCoordinates coordinate : block.getCoordinates()) {
193 oemWriter.writeOrbitEphemerisLine(generator, metadata, coordinate, true);
194 }
195 }
196
197
198 final DataSource source2 = new DataSource("buffer",
199 () -> new ByteArrayInputStream(buffer2.toString().getBytes(StandardCharsets.UTF_8)));
200 generatedOem = new ParserBuilder().
201 withConventions(IERSConventions.IERS_2010).
202 withSimpleEOP(true).
203 withDataContext(DataContext.getDefault()).
204 withMu(CelestialBodyFactory.getEarth().getGM()).
205 withDefaultInterpolationDegree(1).
206 withParsedUnitsBehavior(ParsedUnitsBehavior.STRICT_COMPLIANCE).
207 buildOemParser().
208 parseMessage(source2);
209 compareOems(oem, generatedOem, POSITION_PRECISION, VELOCITY_PRECISION);
210
211 }
212
213 }
214
215 @Test
216 public void testWriteOemEcfNoInterpolation() {
217
218 String path = "/ccsds/odm/oem/OEMExample5.txt";
219 DataSource source = new DataSource(path, () -> getClass().getResourceAsStream(path));
220 final OemParser oemParser = new ParserBuilder().buildOemParser();
221 final Oem original = oemParser.parse(source);
222 final OemSatelliteEphemeris originalEphem =
223 original.getSatellites().values().iterator().next();
224 final Frame frame = originalEphem.getSegments().get(0).getInertialFrame();
225 final BoundedPropagator propagator = originalEphem.getPropagator(new FrameAlignedProvider(frame));
226 StringBuilder buffer = new StringBuilder();
227 OdmHeader header = original.getHeader();
228 OemMetadata metadata = original.getSegments().get(0).getMetadata();
229 metadata.setTimeSystem(TimeSystem.UTC);
230 metadata.setReferenceFrame(FrameFacade.map(FramesFactory.getITRF(IERSConventions.IERS_2010, true)));
231 metadata.setInterpolationMethod(null);
232 metadata.setInterpolationDegree(-1);
233
234
235 StreamingOemWriter writer = new StreamingOemWriter(
236 new KvnGenerator(buffer, OemWriter.KVN_PADDING_WIDTH, "out",
237 Constants.JULIAN_DAY, 0),
238 new WriterBuilder().buildOemWriter(),
239 header,
240 metadata,
241 false,
242 false);
243 propagator.setStepHandler(30 * 60, writer.newSegment());
244 propagator.propagate(propagator.getMinDate(), propagator.getMaxDate());
245
246
247 String actualText = buffer.toString();
248 String expectedPath = "/ccsds/odm/oem/OEMExample5ITRF.txt";
249 Oem expected = oemParser.parse(
250 new DataSource(expectedPath, () -> getClass().getResourceAsStream(expectedPath)));
251 Oem actual = oemParser.parse(
252 new DataSource("mem", () -> new StringReader(actualText)));
253
254 compareOems(expected, actual, 1.9e-5, 2.2e-8);
255 MatcherAssert.assertThat(
256 actualText,
257 CoreMatchers.not(CoreMatchers.containsString("INTERPOLATION_DEGREE")));
258
259 MatcherAssert.assertThat(
260 actualText,
261 CoreMatchers.containsString(
262 "\n2017-04-11T22:31:43.121856 -2757.3016318855234 -4173.47960139054 4566.018498013474 6.625901653955907 -1.0118172088819106 3.0698336591485442\n"));
263 }
264
265 private static void compareOemEphemerisBlocks(OemSegment block1,
266 OemSegment block2,
267 double p_tol,
268 double v_tol) {
269 compareOemEphemerisBlocksMetadata(block1.getMetadata(), block2.getMetadata());
270 Assertions.assertEquals(block1.getStart(), block2.getStart());
271 Assertions.assertEquals(block1.getStop(), block2.getStop());
272 Assertions.assertEquals(block1.getData().getEphemeridesDataLines().size(), block2.getData().getEphemeridesDataLines().size());
273 for (int i = 0; i < block1.getData().getEphemeridesDataLines().size(); i++) {
274 TimeStampedPVCoordinates c1 = block1.getData().getEphemeridesDataLines().get(i);
275 TimeStampedPVCoordinates c2 = block2.getData().getEphemeridesDataLines().get(i);
276 Assertions.assertEquals(c1.getDate(), c2.getDate(),"" + i);
277 Assertions.assertEquals(0.0,
278 Vector3D.distance(c1.getPosition(), c2.getPosition()), p_tol,c1.getPosition() + " -> " + c2.getPosition());
279 Assertions.assertEquals(0.0,
280 Vector3D.distance(c1.getVelocity(), c2.getVelocity()), v_tol,c1.getVelocity() + " -> " + c2.getVelocity());
281 }
282
283 }
284
285 private static void compareOemEphemerisBlocksMetadata(OemMetadata meta1, OemMetadata meta2) {
286 Assertions.assertEquals(meta1.getObjectID(), meta2.getObjectID());
287 Assertions.assertEquals(meta1.getObjectName(), meta2.getObjectName());
288 Assertions.assertEquals(meta1.getCenter().getName(), meta2.getCenter().getName());
289 Assertions.assertEquals(meta1.getReferenceFrame().asFrame(), meta2.getReferenceFrame().asFrame());
290 Assertions.assertEquals(meta1.getReferenceFrame().asCelestialBodyFrame(), meta2.getReferenceFrame().asCelestialBodyFrame());
291 Assertions.assertEquals(meta1.getReferenceFrame().asOrbitRelativeFrame(), meta2.getReferenceFrame().asOrbitRelativeFrame());
292 Assertions.assertEquals(meta1.getReferenceFrame().asSpacecraftBodyFrame(), meta2.getReferenceFrame().asSpacecraftBodyFrame());
293 Assertions.assertEquals(meta1.getTimeSystem().name(), meta2.getTimeSystem().name());
294 }
295
296 static void compareOems(Oem file1, Oem file2, double p_tol, double v_tol) {
297 Assertions.assertEquals(file1.getHeader().getOriginator(), file2.getHeader().getOriginator());
298 Assertions.assertEquals(file1.getSegments().size(), file2.getSegments().size());
299 for (int i = 0; i < file1.getSegments().size(); i++) {
300 compareOemEphemerisBlocks(file1.getSegments().get(i), file2.getSegments().get(i), p_tol, v_tol);
301 }
302 }
303
304 }