1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.adm.aem;
18
19 import java.net.URISyntaxException;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.function.Function;
23
24 import org.hamcrest.MatcherAssert;
25 import org.hamcrest.Matchers;
26 import org.hipparchus.analysis.differentiation.UnivariateDerivative1;
27 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
28 import org.hipparchus.geometry.euclidean.threed.Rotation;
29 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
30 import org.hipparchus.geometry.euclidean.threed.RotationOrder;
31 import org.hipparchus.geometry.euclidean.threed.Vector3D;
32 import org.hipparchus.util.Binary64;
33 import org.hipparchus.util.Binary64Field;
34 import org.hipparchus.util.FastMath;
35 import org.hipparchus.util.MathUtils;
36 import org.junit.jupiter.api.Assertions;
37 import org.junit.jupiter.api.BeforeEach;
38 import org.junit.jupiter.api.Test;
39 import org.orekit.Utils;
40 import org.orekit.attitudes.Attitude;
41 import org.orekit.attitudes.BoundedAttitudeProvider;
42 import org.orekit.attitudes.FieldAttitude;
43 import org.orekit.bodies.CelestialBodyFactory;
44 import org.orekit.data.DataContext;
45 import org.orekit.data.DataSource;
46 import org.orekit.errors.OrekitException;
47 import org.orekit.errors.OrekitMessages;
48 import org.orekit.files.ccsds.definitions.BodyFacade;
49 import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
50 import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
51 import org.orekit.files.ccsds.definitions.FrameFacade;
52 import org.orekit.files.ccsds.definitions.OrbitRelativeFrame;
53 import org.orekit.files.ccsds.definitions.OrekitCcsdsFrameMapper;
54 import org.orekit.files.ccsds.definitions.SpacecraftBodyFrame;
55 import org.orekit.files.ccsds.definitions.TimeSystem;
56 import org.orekit.files.ccsds.ndm.ParserBuilder;
57 import org.orekit.files.ccsds.ndm.adm.AttitudeEndpoints;
58 import org.orekit.files.ccsds.ndm.adm.AttitudeType;
59 import org.orekit.files.ccsds.section.Segment;
60 import org.orekit.frames.Frame;
61 import org.orekit.frames.FramesFactory;
62 import org.orekit.frames.ITRFVersion;
63 import org.orekit.frames.Transform;
64 import org.orekit.orbits.CircularOrbit;
65 import org.orekit.orbits.FieldCircularOrbit;
66 import org.orekit.orbits.PositionAngleType;
67 import org.orekit.time.AbsoluteDate;
68 import org.orekit.time.FieldAbsoluteDate;
69 import org.orekit.time.TimeOffset;
70 import org.orekit.time.TimeScale;
71 import org.orekit.time.TimeScalesFactory;
72 import org.orekit.utils.AngularDerivativesFilter;
73 import org.orekit.utils.Constants;
74 import org.orekit.utils.IERSConventions;
75 import org.orekit.utils.TimeStampedAngularCoordinates;
76
77 public class AEMParserTest {
78
79 @BeforeEach
80 public void setUp()
81 throws Exception {
82 Utils.setDataRoot("regular-data");
83 }
84
85 @Test
86 public void testParseAEM01() {
87 final String ex = "/ccsds/adm/aem/AEMExample01.txt";
88 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
89 final Aem file = new ParserBuilder().buildAemParser().parseMessage(source);
90 final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
91 final Segment<AemMetadata, AemData> segment1 = file.getSegments().get(1);
92 final AbsoluteDate start = new AbsoluteDate("1996-11-28T22:08:02.5555", TimeScalesFactory.getUTC());
93 Assertions.assertEquals(0.0, start.durationFrom(file.getSatellites().get("1996-062A").getStart()), Double.MIN_VALUE);
94 final AbsoluteDate end = new AbsoluteDate("1996-12-28T21:23:00.5555", TimeScalesFactory.getUTC());
95 Assertions.assertEquals(0.0, end.durationFrom(file.getSatellites().get("1996-062A").getStop()), Double.MIN_VALUE);
96 Assertions.assertEquals("1996-062A", file.getSatellites().get("1996-062A").getId());
97 Assertions.assertEquals(1.0, file.getHeader().getFormatVersion(), Double.MIN_VALUE);
98 Assertions.assertEquals(new AbsoluteDate(2002, 11, 4, 17, 22, 31.0, TimeScalesFactory.getUTC()),
99 file.getHeader().getCreationDate());
100 Assertions.assertEquals("NASA/JPL", file.getHeader().getOriginator());
101 Assertions.assertEquals("UTC", segment0.getMetadata().getTimeSystem().name());
102 Assertions.assertEquals("MARS GLOBAL SURVEYOR", segment0.getMetadata().getObjectName());
103 Assertions.assertEquals("1996-062A", segment0.getMetadata().getObjectID());
104 Assertions.assertEquals("MARS BARYCENTER", segment0.getMetadata().getCenter().getName());
105 Assertions.assertEquals(1996, segment0.getMetadata().getLaunchYear());
106 Assertions.assertEquals(62, segment0.getMetadata().getLaunchNumber());
107 Assertions.assertEquals("A", segment0.getMetadata().getLaunchPiece());
108 Assertions.assertFalse(segment0.getMetadata().getHasCreatableBody());
109 Assertions.assertNull(segment0.getMetadata().getCenter().getBody());
110 Assertions.assertEquals(new AbsoluteDate(1996, 11, 28, 21, 29, new TimeOffset(7, TimeOffset.SECOND,
111 255500, TimeOffset.MICROSECOND),
112 TimeScalesFactory.getUTC()),
113 segment0.getMetadata().getStartTime());
114 Assertions.assertEquals(new AbsoluteDate(1996, 11, 30, 1, 28, new TimeOffset(2, TimeOffset.SECOND,
115 555500, TimeOffset.MICROSECOND),
116 TimeScalesFactory.getUTC()),
117 segment0.getMetadata().getStopTime());
118 Assertions.assertEquals(new AbsoluteDate(1996, 11, 28, 22, 8, new TimeOffset(2, TimeOffset.SECOND,
119 555500, TimeOffset.MICROSECOND),
120 TimeScalesFactory.getUTC()),
121 segment0.getMetadata().getUseableStartTime());
122 Assertions.assertEquals(new AbsoluteDate(1996, 11, 30, 1, 18, new TimeOffset(2, TimeOffset.SECOND,
123 555500, TimeOffset.MICROSECOND),
124 TimeScalesFactory.getUTC()),
125 segment0.getMetadata().getUseableStopTime());
126 Assertions.assertEquals("HERMITE", segment0.getMetadata().getInterpolationMethod());
127 Assertions.assertEquals(7, segment0.getMetadata().getInterpolationDegree());
128 Assertions.assertFalse(segment0.getMetadata().isFirst());
129 Assertions.assertEquals("EME2000", segment0.getMetadata().getEndpoints().getFrameA().getName());
130 Assertions.assertEquals(SpacecraftBodyFrame.BaseEquipment.SC_BODY,
131 segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
132 Assertions.assertEquals("1",
133 segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
134 Assertions.assertTrue(segment0.getMetadata().getEndpoints().isA2b());
135 Assertions.assertEquals(AttitudeType.QUATERNION, segment1.getMetadata().getAttitudeType());
136 Assertions.assertEquals(AngularDerivativesFilter.USE_R, segment0.getMetadata().getAttitudeType().getAngularDerivativesFilter());
137 verifyAngularCoordinates(new TimeStampedAngularCoordinates(new AbsoluteDate(1996, 11, 28, 21, 29,
138 new TimeOffset(7, TimeOffset.SECOND,
139 255500, TimeOffset.MICROSECOND),
140 TimeScalesFactory.getUTC()),
141 new Rotation(0.68427, 0.56748, 0.03146, 0.45689, false),
142 Vector3D.ZERO,
143 Vector3D.ZERO),
144 segment0.getData().getAngularCoordinates().get(0), 1.0e-5);
145 verifyAngularCoordinates(new TimeStampedAngularCoordinates(new AbsoluteDate(1996, 11, 28, 22, 8,
146 new TimeOffset(3, TimeOffset.SECOND,
147 555500, TimeOffset.MICROSECOND),
148 TimeScalesFactory.getUTC()),
149 new Rotation(0.74533, 0.42319, -0.45697, 0.23784, false),
150 Vector3D.ZERO,
151 Vector3D.ZERO),
152 segment0.getData().getAngularCoordinates().get(1), 1.0e-5);
153 verifyAngularCoordinates(new TimeStampedAngularCoordinates(new AbsoluteDate(1996, 11, 28, 22, 8,
154 new TimeOffset(4, TimeOffset.SECOND,
155 555500, TimeOffset.MICROSECOND),
156 TimeScalesFactory.getUTC()),
157 new Rotation(0.45652, -0.84532, 0.26974, -0.06532, false),
158 Vector3D.ZERO,
159 Vector3D.ZERO),
160 segment0.getData().getAngularCoordinates().get(2), 1.0e-5);
161 ArrayList<String> ephemeridesDataLinesComment = new ArrayList<>();
162 ephemeridesDataLinesComment.add("This file was produced by M.R. Somebody, MSOO NAV/JPL, 2002 OCT 04.");
163 ephemeridesDataLinesComment.add("It is to be used for attitude reconstruction only. The relative accuracy of these");
164 ephemeridesDataLinesComment.add("attitudes is 0.1 degrees per axis.");
165 Assertions.assertEquals(ephemeridesDataLinesComment, segment0.getMetadata().getComments());
166
167 Assertions.assertEquals("UTC", segment1.getMetadata().getTimeSystem().name());
168 Assertions.assertEquals("MARS GLOBAL SURVEYOR", segment1.getMetadata().getObjectName());
169 Assertions.assertEquals("1996-062A", segment1.getMetadata().getObjectID());
170 Assertions.assertEquals("MARS BARYCENTER", segment1.getMetadata().getCenter().getName());
171 Assertions.assertEquals(1996, segment1.getMetadata().getLaunchYear());
172 Assertions.assertEquals(62, segment1.getMetadata().getLaunchNumber());
173 Assertions.assertEquals("A", segment1.getMetadata().getLaunchPiece());
174 Assertions.assertFalse(segment1.getMetadata().getHasCreatableBody());
175 Assertions.assertNull(segment1.getMetadata().getCenter().getBody());
176 Assertions.assertEquals(new AbsoluteDate(1996, 12, 18, 12, 5, new TimeOffset(555500, TimeOffset.MICROSECOND), TimeScalesFactory.getUTC()),
177 segment1.getMetadata().getStartTime());
178 Assertions.assertEquals(new AbsoluteDate(1996, 12, 28, 21, 28, new TimeOffset(555500, TimeOffset.MICROSECOND), TimeScalesFactory.getUTC()),
179 segment1.getMetadata().getStopTime());
180 Assertions.assertEquals(new AbsoluteDate(1996, 12, 18, 12, 10, new TimeOffset(555500, TimeOffset.MICROSECOND), TimeScalesFactory.getUTC()),
181 segment1.getMetadata().getUseableStartTime());
182 Assertions.assertEquals(new AbsoluteDate(1996, 12, 28, 21, 23, new TimeOffset(555500, TimeOffset.MICROSECOND), TimeScalesFactory.getUTC()),
183 segment1.getMetadata().getUseableStopTime());
184 Assertions.assertFalse(segment1.getMetadata().isFirst());
185 Assertions.assertEquals("EME2000", segment0.getMetadata().getEndpoints().getFrameA().getName());
186 Assertions.assertEquals(SpacecraftBodyFrame.BaseEquipment.SC_BODY,
187 segment0.getMetadata().getEndpoints().getSpacecraftBodyFrame().asSpacecraftBodyFrame().getBaseEquipment());
188 Assertions.assertEquals("1",
189 segment0.getMetadata().getEndpoints().getSpacecraftBodyFrame().asSpacecraftBodyFrame().getLabel());
190 Assertions.assertTrue(segment0.getMetadata().getEndpoints().isA2b());
191 Assertions.assertEquals(AttitudeType.QUATERNION, segment1.getMetadata().getAttitudeType());
192 Assertions.assertEquals(AngularDerivativesFilter.USE_R, segment0.getMetadata().getAttitudeType().getAngularDerivativesFilter());
193 verifyAngularCoordinates(new TimeStampedAngularCoordinates(new AbsoluteDate(1996, 12, 18, 12, 5, new TimeOffset(555500, TimeOffset.MICROSECOND),
194 TimeScalesFactory.getUTC()),
195 new Rotation(0.72501, -0.64585, 0.018542, -0.23854, false),
196 Vector3D.ZERO,
197 Vector3D.ZERO),
198 segment1.getData().getAngularCoordinates().get(0), 1.0e-5);
199 verifyAngularCoordinates(new TimeStampedAngularCoordinates(new AbsoluteDate(1996, 12, 18, 12, 10, new TimeOffset(5, TimeOffset.SECOND,
200 555500,
201 TimeOffset.MICROSECOND),
202 TimeScalesFactory.getUTC()),
203 new Rotation(-0.16767, 0.87451, -0.43475, 0.13458, false),
204 Vector3D.ZERO,
205 Vector3D.ZERO),
206 segment1.getData().getAngularCoordinates().get(1), 1.0e-5);
207 verifyAngularCoordinates(new TimeStampedAngularCoordinates(new AbsoluteDate(1996, 12, 18, 12, 10, new TimeOffset(10, TimeOffset.SECOND,
208 555500, TimeOffset.MICROSECOND),
209 TimeScalesFactory.getUTC()),
210 new Rotation(-0.71418, 0.03125, -0.65874, 0.23458, false),
211 Vector3D.ZERO,
212 Vector3D.ZERO),
213 segment1.getData().getAngularCoordinates().get(2), 1.0e-5);
214 ArrayList<String> ephemeridesDataLinesComment2 = new ArrayList<>();
215 ephemeridesDataLinesComment2.add("This block begins after trajectory correction maneuver TCM-3.");
216 Assertions.assertEquals(ephemeridesDataLinesComment2, segment1.getMetadata().getComments());
217 }
218
219 @Test
220 public void testParseAEM02() {
221 final String name = "/ccsds/adm/aem/AEMExample02.txt";
222 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
223 AemParser parser = new ParserBuilder().
224 withMissionReferenceDate(new AbsoluteDate("1996-12-17T00:00:00.000",
225 TimeScalesFactory.getUTC())).
226 buildAemParser();
227
228 final Aem file = parser.parse(source);
229 final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
230 final List<String> headerComment = new ArrayList<>();
231 headerComment.add("comment");
232 Assertions.assertEquals(headerComment, file.getHeader().getComments());
233 final List<String> metadataComment = new ArrayList<>();
234 metadataComment.add("This file was produced by M.R. Somebody, MSOO NAV/JPL, 2002 OCT 04.");
235 metadataComment.add("It is to be used for attitude reconstruction only. The relative accuracy of these");
236 metadataComment.add("attitudes is 0.1 degrees per axis.");
237 Assertions.assertEquals(metadataComment, segment0.getMetadata().getComments());
238 Assertions.assertEquals("EME2000", segment0.getMetadata().getEndpoints().getFrameA().getName());
239 Assertions.assertEquals(SpacecraftBodyFrame.BaseEquipment.SC_BODY,
240 segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
241 Assertions.assertEquals("1",
242 segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
243 List<AemSegment> blocks = file.getSegments();
244 Assertions.assertEquals(1, blocks.size());
245 Assertions.assertEquals(IERSConventions.IERS_2010, parser.getConventions());
246 Assertions.assertTrue(parser.isSimpleEOP());
247 Assertions.assertEquals(0.0, parser.getMissionReferenceDate().durationFrom(new AbsoluteDate(1996, 12, 17, 0, 0, 0.0,
248 TimeScalesFactory.getUTC())), 1.0e-5);
249 Assertions.assertEquals(DataContext.getDefault(), parser.getDataContext());
250 Assertions.assertEquals((new AbsoluteDate("1996-12-17T00:00:00.000",
251 TimeScalesFactory.getUTC())),
252 parser.getMissionReferenceDate());
253 }
254
255 @Test
256 public void testParseKvnAEM03() {
257 final String ex = "/ccsds/adm/aem/AEMExample03.txt";
258 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
259 validateAEM03(new ParserBuilder().buildAemParser().parseMessage(source));
260 }
261
262 @Test
263 public void testParseXmlAEM03() {
264 final String ex = "/ccsds/adm/aem/AEMExample03.xml";
265 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
266 final AemParser parser = new ParserBuilder().buildAemParser();
267 validateAEM03(parser.parse(source));
268 }
269
270 private void validateAEM03(final Aem file) {
271
272 final TimeScale utc = TimeScalesFactory.getUTC();
273 Assertions.assertEquals(1.0, file.getHeader().getFormatVersion(), 1.0e-15);
274 Assertions.assertEquals(0,
275 file.getHeader().getCreationDate().durationFrom(new AbsoluteDate("2008-071T17:09:49", utc)),
276 1.0e-12);
277 Assertions.assertEquals("GSFC FDF", file.getHeader().getOriginator());
278 final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
279 Assertions.assertEquals("ST5-224", segment0.getMetadata().getObjectName());
280 Assertions.assertEquals("2006224", segment0.getMetadata().getObjectID());
281 Assertions.assertEquals("J2000", segment0.getMetadata().getEndpoints().getFrameA().getName());
282 Assertions.assertEquals("SC_BODY_1", segment0.getMetadata().getEndpoints().getFrameB().getName());
283 Assertions.assertTrue(segment0.getMetadata().getEndpoints().isA2b());
284 Assertions.assertEquals(TimeSystem.UTC, segment0.getMetadata().getTimeSystem());
285 Assertions.assertEquals(0,
286 segment0.getMetadata().getStartTime().durationFrom(new AbsoluteDate("2006-090T05:00:00.071", utc)),
287 1.0e-12);
288 Assertions.assertEquals(0,
289 segment0.getMetadata().getUseableStartTime().durationFrom(new AbsoluteDate("2006-090T05:00:00.071", utc)),
290 1.0e-12);
291 Assertions.assertEquals(0,
292 segment0.getMetadata().getUseableStopTime().durationFrom(new AbsoluteDate("2006-090T05:00:00.946", utc)),
293 1.0e-12);
294 Assertions.assertEquals(0,
295 segment0.getMetadata().getStopTime().durationFrom(new AbsoluteDate("2006-090T05:00:00.946", utc)),
296 1.0e-12);
297 Assertions.assertEquals(AttitudeType.SPIN, segment0.getMetadata().getAttitudeType());
298 Assertions.assertEquals(1, segment0.getData().getComments().size());
299 Assertions.assertEquals("Spin KF ground solution, SPINKF rates", segment0.getData().getComments().get(0));
300 Assertions.assertEquals(8, segment0.getData().getAngularCoordinates().size());
301 TimeStampedAngularCoordinates prev = null;
302 for (TimeStampedAngularCoordinates tac : segment0.getData().getAngularCoordinates()) {
303 if (prev != null) {
304 double dt = tac.getDate().durationFrom(prev.getDate());
305 double dR = Rotation.distance(tac.getRotation(), prev.getRotation());
306 double meanRate = 0.5 * (prev.getRotationRate().getNorm() + tac.getRotationRate().getNorm());
307 Assertions.assertEquals(dR, dt * meanRate, 1.3e-3);
308 }
309 prev = tac;
310 }
311
312 }
313
314 @Test
315 public void testParseAEM04() {
316 final TimeScale utc = TimeScalesFactory.getUTC();
317 final String ex = "/ccsds/adm/aem/AEMExample04.txt";
318 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
319 final AemParser parser = new ParserBuilder().buildAemParser();
320 final Aem file = parser.parseMessage(source);
321 Assertions.assertEquals(1.0, file.getHeader().getFormatVersion(), 1.0e-15);
322 Assertions.assertEquals(0,
323 file.getHeader().getCreationDate().durationFrom(new AbsoluteDate("2021-04-13T08:41:42", utc)),
324 1.0e-12);
325 Assertions.assertEquals("CS GROUP", file.getHeader().getOriginator());
326 final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
327 Assertions.assertEquals("COPIHUE", segment0.getMetadata().getObjectName());
328 Assertions.assertEquals("2100-017F", segment0.getMetadata().getObjectID());
329 Assertions.assertEquals(2100, segment0.getMetadata().getLaunchYear());
330 Assertions.assertEquals(17, segment0.getMetadata().getLaunchNumber());
331 Assertions.assertEquals("F", segment0.getMetadata().getLaunchPiece());
332 Assertions.assertEquals("EME2000", segment0.getMetadata().getEndpoints().getFrameA().getName());
333 Assertions.assertEquals("SC_BODY_1", segment0.getMetadata().getEndpoints().getFrameB().getName());
334 Assertions.assertTrue(segment0.getMetadata().getEndpoints().isA2b());
335 Assertions.assertEquals(TimeSystem.UTC, segment0.getMetadata().getTimeSystem());
336 Assertions.assertEquals(0,
337 segment0.getMetadata().getStartTime().durationFrom(new AbsoluteDate("2021-12-31T00:00:00.000", utc)),
338 1.0e-12);
339 Assertions.assertEquals(0,
340 segment0.getMetadata().getUseableStartTime().durationFrom(new AbsoluteDate("2021-12-31T00:00:00.500", utc)),
341 1.0e-12);
342 Assertions.assertEquals(0,
343 segment0.getMetadata().getUseableStopTime().durationFrom(new AbsoluteDate("2021-12-31T00:00:05.500", utc)),
344 1.0e-12);
345 Assertions.assertEquals(0,
346 segment0.getMetadata().getStopTime().durationFrom(new AbsoluteDate("2021-12-31T00:00:06.000", utc)),
347 1.0e-12);
348 Assertions.assertEquals(AttitudeType.QUATERNION_DERIVATIVE, segment0.getMetadata().getAttitudeType());
349 Assertions.assertEquals("HERMITE", segment0.getMetadata().getInterpolationMethod());
350 Assertions.assertEquals(3, segment0.getMetadata().getInterpolationDegree());
351 Assertions.assertEquals(1, segment0.getData().getComments().size());
352 Assertions.assertEquals(13, segment0.getData().getAngularCoordinates().size());
353 TimeStampedAngularCoordinates prev = null;
354 for (TimeStampedAngularCoordinates tac : segment0.getData().getAngularCoordinates()) {
355 if (prev != null) {
356 double dt = tac.getDate().durationFrom(prev.getDate());
357 double dR = Rotation.distance(tac.getRotation(), prev.getRotation());
358 double meanRate = 0.5 * (prev.getRotationRate().getNorm() + tac.getRotationRate().getNorm());
359 Assertions.assertEquals(dR, dt * meanRate, 1.5e-6);
360 }
361 prev = tac;
362 }
363
364 }
365
366 @Test
367 public void testParseAEM05() {
368 final String ex = "/ccsds/adm/aem/AEMExample05.txt";
369 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
370 final AemParser parser = new ParserBuilder().buildAemParser();
371 final Aem file = parser.parseMessage(source);
372 final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
373 final List<String> headerComment = new ArrayList<>();
374 headerComment.add("comment");
375 Assertions.assertEquals(headerComment, file.getHeader().getComments());
376 final List<String> metadataComment = new ArrayList<>();
377 metadataComment.add("This file was produced by M.R. Somebody, MSOO NAV/JPL, 2002 OCT 04.");
378 metadataComment.add("It is to be used for attitude reconstruction only. The relative accuracy of these");
379 metadataComment.add("attitudes is 0.1 degrees per axis.");
380 Assertions.assertEquals(metadataComment, segment0.getMetadata().getComments());
381 Assertions.assertEquals("UTC", segment0.getMetadata().getTimeSystem().name());
382 Assertions.assertEquals("MARS GLOBAL SURVEYOR", segment0.getMetadata().getObjectName());
383 Assertions.assertEquals("1996-062A", segment0.getMetadata().getObjectID());
384 Assertions.assertEquals("MARS BARYCENTER", segment0.getMetadata().getCenter().getName());
385 Assertions.assertEquals(1996, segment0.getMetadata().getLaunchYear());
386 Assertions.assertEquals(62, segment0.getMetadata().getLaunchNumber());
387 Assertions.assertEquals("A", segment0.getMetadata().getLaunchPiece());
388 Assertions.assertEquals(RotationOrder.ZXY, segment0.getMetadata().getEulerRotSeq());
389 Assertions.assertTrue(segment0.getMetadata().rateFrameIsA());
390 Assertions.assertFalse(segment0.getMetadata().getHasCreatableBody());
391 Assertions.assertNull(segment0.getMetadata().getCenter().getBody());
392
393
394 final AbsoluteDate refDate = new AbsoluteDate(1996, 11, 28, 21, 29, 7.2555, TimeScalesFactory.getUTC());
395
396
397 final TimeStampedAngularCoordinates ac = segment0.getData().getAngularCoordinates().get(0);
398 final FieldRotation<UnivariateDerivative1> r = ac.toUnivariateDerivative1Rotation();
399 final UnivariateDerivative1[] angles = r.getAngles(segment0.getMetadata().getEulerRotSeq(),
400 RotationConvention.FRAME_TRANSFORM);
401 Assertions.assertEquals(0.0, refDate.durationFrom(ac.getDate()), 1.0e-5);
402 Assertions.assertEquals(0.0, ac.getRotationAcceleration().getNorm(), 1.0e-5);
403 Assertions.assertEquals(-26.78, FastMath.toDegrees(angles[0].getValue()), 1.0e-2);
404 Assertions.assertEquals(46.26, FastMath.toDegrees(angles[1].getValue()), 1.0e-2);
405 Assertions.assertEquals(144.10, FastMath.toDegrees(angles[2].getValue()), 1.0e-2);
406 Assertions.assertEquals(0.10450, FastMath.toDegrees(angles[0].getFirstDerivative()), 1.0e-5);
407 Assertions.assertEquals(0.03214, FastMath.toDegrees(angles[1].getFirstDerivative()), 1.0e-5);
408 Assertions.assertEquals(0.02156, FastMath.toDegrees(angles[2].getFirstDerivative()), 1.0e-5);
409 }
410
411 @Test
412 public void testParseAEM06a() {
413 final String ex = "/ccsds/adm/aem/AEMExample06a.txt";
414 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
415 final AemParser parser = new ParserBuilder().buildAemParser();
416
417 final Aem file = parser.parseMessage(source);
418 final TimeStampedAngularCoordinates ac = file.getSegments().get(0).getAngularCoordinates().get(7);
419 final Vector3D lastSpin = ac.getRotation().applyInverseTo(Vector3D.PLUS_K);
420 Assertions.assertEquals(268.45119, FastMath.toDegrees(MathUtils.normalizeAngle(lastSpin.getAlpha(), FastMath.PI)), 1.0e-5);
421 Assertions.assertEquals(68.317275, FastMath.toDegrees(lastSpin.getDelta()), 1.0e-5);
422 }
423
424 @Test
425 public void testParseAEM06b() {
426 final String ex = "/ccsds/adm/aem/AEMExample06b.txt";
427 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
428 final AemParser parser = new ParserBuilder().buildAemParser();
429
430 final Aem file = parser.parseMessage(source);
431 final TimeStampedAngularCoordinates ac = file.getSegments().get(0).getAngularCoordinates().get(7);
432 final Vector3D lastSpin = ac.getRotation().applyInverseTo(Vector3D.PLUS_K);
433 Assertions.assertEquals(268.45119, FastMath.toDegrees(MathUtils.normalizeAngle(lastSpin.getAlpha(), FastMath.PI)), 1.0e-5);
434 Assertions.assertEquals(68.317275, FastMath.toDegrees(lastSpin.getDelta()), 1.0e-5);
435 }
436
437 @Test
438 public void testParseAEM07() {
439 final String ex = "/ccsds/adm/aem/AEMExample07.txt";
440 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
441 final AemParser parser = new ParserBuilder().buildAemParser();
442 final Aem file = parser.parseMessage(source);
443 final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
444 final List<String> headerComment = new ArrayList<>();
445 headerComment.add("comment");
446 Assertions.assertEquals(headerComment, file.getHeader().getComments());
447 final List<String> metadataComment = new ArrayList<>();
448 metadataComment.add("This file was produced by M.R. Somebody, MSOO NAV/JPL, 2002 OCT 04.");
449 metadataComment.add("It is to be used for attitude reconstruction only. The relative accuracy of these");
450 metadataComment.add("attitudes is 0.1 degrees per axis.");
451 Assertions.assertEquals(metadataComment, segment0.getMetadata().getComments());
452 Assertions.assertEquals(TimeSystem.UTC, segment0.getMetadata().getTimeSystem());
453 Assertions.assertEquals("MARS GLOBAL SURVEYOR", segment0.getMetadata().getObjectName());
454 Assertions.assertEquals("1996-062A", segment0.getMetadata().getObjectID());
455 Assertions.assertEquals("MARS BARYCENTER", segment0.getMetadata().getCenter().getName());
456 Assertions.assertEquals(1996, segment0.getMetadata().getLaunchYear());
457 Assertions.assertEquals(62, segment0.getMetadata().getLaunchNumber());
458 Assertions.assertEquals("A", segment0.getMetadata().getLaunchPiece());
459 Assertions.assertFalse(segment0.getMetadata().getHasCreatableBody());
460 Assertions.assertNull(segment0.getMetadata().getCenter().getBody());
461 Assertions.assertEquals(CelestialBodyFrame.EME2000, segment0.getMetadata().getEndpoints().getFrameA().asCelestialBodyFrame());
462 Assertions.assertEquals(SpacecraftBodyFrame.BaseEquipment.SC_BODY, segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
463 Assertions.assertEquals("1", segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
464 Assertions.assertTrue(segment0.getMetadata().getEndpoints().isA2b());
465 Assertions.assertEquals(new AbsoluteDate("2002-12-18T12:00:00.331", TimeScalesFactory.getUTC()),
466 segment0.getMetadata().getStartTime());
467 Assertions.assertEquals(new AbsoluteDate("2002-12-18T12:00:00.331", TimeScalesFactory.getUTC()),
468 segment0.getMetadata().getUseableStartTime());
469 Assertions.assertEquals(new AbsoluteDate("2002-12-18T12:02:00.331", TimeScalesFactory.getUTC()),
470 segment0.getMetadata().getUseableStopTime());
471 Assertions.assertEquals(new AbsoluteDate("2002-12-18T12:02:00.331", TimeScalesFactory.getUTC()),
472 segment0.getMetadata().getStopTime());
473 Assertions.assertEquals(AttitudeType.QUATERNION, segment0.getMetadata().getAttitudeType());
474 Assertions.assertFalse(segment0.getMetadata().isFirst());
475 Assertions.assertEquals("HERMITE", segment0.getMetadata().getInterpolationMethod());
476 Assertions.assertEquals(7, segment0.getMetadata().getInterpolationDegree());
477
478 final AbsoluteDate refDate = new AbsoluteDate("2002-12-18T12:00:00.331", TimeScalesFactory.getUTC());
479
480 Assertions.assertEquals(3, segment0.getData().getAngularCoordinates().size());
481 final TimeStampedAngularCoordinates ac0 = segment0.getData().getAngularCoordinates().get(0);
482 Assertions.assertEquals(0.0, ac0.getDate().durationFrom(refDate), 1.0e-5);
483 Assertions.assertEquals(0.0,
484 Rotation.distance(new Rotation(0.68427, 0.56748, 0.03146, 0.45689, true),
485 ac0.getRotation()),
486 1.0e-10);
487 final TimeStampedAngularCoordinates ac1 = segment0.getData().getAngularCoordinates().get(1);
488 Assertions.assertEquals(60.0, ac1.getDate().durationFrom(refDate), 1.0e-5);
489 Assertions.assertEquals(0.0,
490 Rotation.distance(new Rotation(0.74533, 0.42319, -0.45697, 0.23784, true),
491 ac1.getRotation()),
492 1.0e-10);
493 final TimeStampedAngularCoordinates ac2 = segment0.getData().getAngularCoordinates().get(2);
494 Assertions.assertEquals(120.0, ac2.getDate().durationFrom(refDate), 1.0e-5);
495 Assertions.assertEquals(0.0,
496 Rotation.distance(new Rotation(0.45652, -0.84532, 0.26974, -0.06532, true),
497 ac2.getRotation()),
498 1.0e-10);
499
500 }
501
502 @Test
503 public void testParseAEM11() {
504 final String ex = "/ccsds/adm/aem/AEMExample11.xml";
505 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
506 final AemParser parser = new ParserBuilder().buildAemParser();
507 final Aem file = parser.parseMessage(source);
508 final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
509 final List<String> headerComment = new ArrayList<>();
510 headerComment.add("This example shows an AEM with a rotation");
511 Assertions.assertEquals(headerComment, file.getHeader().getComments());
512 final List<String> metadataComment = new ArrayList<>();
513 metadataComment.add("The relative accuracy of these");
514 metadataComment.add("attitudes is 0.1 degrees per axis.");
515 Assertions.assertEquals(metadataComment, segment0.getMetadata().getComments());
516 Assertions.assertEquals(TimeSystem.UTC, segment0.getMetadata().getTimeSystem());
517 Assertions.assertEquals("FICTITIOUS", segment0.getMetadata().getObjectName());
518 Assertions.assertEquals("2020-224A", segment0.getMetadata().getObjectID());
519 Assertions.assertEquals("EARTH", segment0.getMetadata().getCenter().getName());
520 Assertions.assertEquals(CelestialBodyFrame.J2000, segment0.getMetadata().getEndpoints().getFrameA().asCelestialBodyFrame());
521 Assertions.assertEquals(SpacecraftBodyFrame.BaseEquipment.SC_BODY, segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
522 Assertions.assertEquals("1", segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
523 Assertions.assertTrue(segment0.getMetadata().getEndpoints().isA2b());
524 Assertions.assertEquals(new AbsoluteDate("2020-090T05:00:00.071", TimeScalesFactory.getUTC()),
525 segment0.getMetadata().getStartTime());
526 Assertions.assertEquals(new AbsoluteDate("2020-090T05:00:00.946", TimeScalesFactory.getUTC()),
527 segment0.getMetadata().getStopTime());
528 Assertions.assertEquals(AttitudeType.EULER_ANGLE_DERIVATIVE, segment0.getMetadata().getAttitudeType());
529
530 final AbsoluteDate refDate = new AbsoluteDate("2020-090T05:00:00.071", TimeScalesFactory.getUTC());
531
532 Assertions.assertEquals(2, segment0.getData().getAngularCoordinates().size());
533 final TimeStampedAngularCoordinates ac0 = segment0.getData().getAngularCoordinates().get(0);
534 Assertions.assertEquals(0.0, ac0.getDate().durationFrom(refDate), 1.0e-5);
535 Assertions.assertEquals(0.0,
536 Rotation.distance(new Rotation(RotationOrder.XYZ, RotationConvention.FRAME_TRANSFORM,
537 FastMath.toRadians(45),
538 FastMath.toRadians(0.9),
539 FastMath.toRadians(15)),
540 ac0.getRotation()),
541 1.0e-10);
542 final TimeStampedAngularCoordinates ac1 = segment0.getData().getAngularCoordinates().get(1);
543 Assertions.assertEquals(0.875, ac1.getDate().durationFrom(refDate), 1.0e-5);
544 Assertions.assertEquals(0.0,
545 Rotation.distance(new Rotation(RotationOrder.XYZ, RotationConvention.FRAME_TRANSFORM,
546 FastMath.toRadians(50),
547 FastMath.toRadians(1.9),
548 FastMath.toRadians(1.5)),
549 ac1.getRotation()),
550 1.0e-10);
551
552 }
553
554 @Test
555 public void testParseAEM13() {
556 final TimeScale tai = TimeScalesFactory.getTAI();
557 final String ex = "/ccsds/adm/aem/AEMExample13.xml";
558 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
559 final AemParser parser = new ParserBuilder().buildAemParser();
560 final Aem file = parser.parseMessage(source);
561 final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
562 Assertions.assertEquals(TimeSystem.TAI, segment0.getMetadata().getTimeSystem());
563 Assertions.assertEquals("OREKIT SAT", segment0.getMetadata().getObjectName());
564 Assertions.assertEquals("2020-012A", segment0.getMetadata().getObjectID());
565 Assertions.assertEquals(OrbitRelativeFrame.LVLH, segment0.getMetadata().getEndpoints().getFrameA().asOrbitRelativeFrame());
566 Assertions.assertEquals(SpacecraftBodyFrame.BaseEquipment.IMU_FRAME, segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
567 Assertions.assertEquals("1", segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
568 Assertions.assertFalse(segment0.getMetadata().getEndpoints().isA2b());
569 Assertions.assertEquals(new AbsoluteDate("2021-04-15T13:31:20.000", tai), segment0.getMetadata().getStartTime());
570 Assertions.assertEquals(new AbsoluteDate("2021-04-15T13:31:23.000", tai), segment0.getMetadata().getStopTime());
571 Assertions.assertEquals(AttitudeType.QUATERNION_DERIVATIVE, segment0.getMetadata().getAttitudeType());
572 Assertions.assertTrue(segment0.getMetadata().isFirst());
573
574 final AbsoluteDate refDate = new AbsoluteDate("2021-04-15T13:31:20.000", tai);
575
576 Assertions.assertEquals(7, segment0.getData().getAngularCoordinates().size());
577 final TimeStampedAngularCoordinates ac0 = segment0.getData().getAngularCoordinates().get(0);
578 Assertions.assertEquals(0.0, ac0.getDate().durationFrom(refDate), 1.0e-5);
579 Assertions.assertEquals(0.0,
580 Rotation.distance(new Rotation(-0.488615, -0.402157, 0.581628, 0.511111, true),
581 ac0.getRotation()),
582 1.0e-10);
583 final TimeStampedAngularCoordinates ac1 = segment0.getData().getAngularCoordinates().get(1);
584 Assertions.assertEquals(0.5, ac1.getDate().durationFrom(refDate), 1.0e-5);
585 Assertions.assertEquals(0.0,
586 Rotation.distance(new Rotation(-0.488765, -0.402027, 0.581486, 0.511231, true),
587 ac1.getRotation()),
588 1.0e-10);
589 final TimeStampedAngularCoordinates ac2 = segment0.getData().getAngularCoordinates().get(2);
590 Assertions.assertEquals(1.0, ac2.getDate().durationFrom(refDate), 1.0e-5);
591 Assertions.assertEquals(0.0,
592 Rotation.distance(new Rotation(-0.488916, -0.401898, 0.581344, 0.511350, true),
593 ac2.getRotation()),
594 1.0e-10);
595
596 final CircularOrbit o = new CircularOrbit(6992992, -5e-04, 1.2e-03,
597 FastMath.toRadians(97.83), FastMath.toRadians(80.95),
598 FastMath.toRadians(179.86), PositionAngleType.MEAN,
599 FramesFactory.getEME2000(),
600 new AbsoluteDate("2021-04-15T13:31:22.000", tai),
601 Constants.EIGEN5C_EARTH_MU);
602 final FieldCircularOrbit<Binary64> fo =
603 new FieldCircularOrbit<>(new Binary64(o.getA()),
604 new Binary64(o.getCircularEx()), new Binary64(o.getCircularEy()),
605 new Binary64(o.getI()), new Binary64(o.getRightAscensionOfAscendingNode()),
606 new Binary64(o.getAlphaM()), PositionAngleType.MEAN,
607 o.getFrame(), new FieldAbsoluteDate<>(Binary64Field.getInstance(), o.getDate()),
608 new Binary64(o.getMu()));
609 final AemSatelliteEphemeris ephemeris = file.getSatellites().get("2020-012A");
610 final BoundedAttitudeProvider provider = ephemeris.getAttitudeProvider();
611 Attitude a = provider.getAttitude(o, o.getDate(), o.getFrame());
612 FieldAttitude<Binary64> fa = provider.getAttitude(fo, fo.getDate(), fo.getFrame());
613 Assertions.assertEquals(a.getRotation().getQ0(), fa.getRotation().getQ0().getReal(), 0.00001);
614 Assertions.assertEquals(a.getRotation().getQ1(), fa.getRotation().getQ1().getReal(), 0.00001);
615 Assertions.assertEquals(a.getRotation().getQ2(), fa.getRotation().getQ2().getReal(), 0.00001);
616 Assertions.assertEquals(a.getRotation().getQ3(), fa.getRotation().getQ3().getReal(), 0.00001);
617
618 }
619
620 @Test
621 public void testParseAEM14() {
622 final TimeScale tai = TimeScalesFactory.getTAI();
623 final String ex = "/ccsds/adm/aem/AEMExample14.txt";
624 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
625 final AemParser parser = new ParserBuilder().buildAemParser();
626 final Aem file = parser.parseMessage(source);
627
628 final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
629 Assertions.assertEquals(TimeSystem.TAI, segment0.getMetadata().getTimeSystem());
630 Assertions.assertEquals("MMS", segment0.getMetadata().getObjectName());
631 Assertions.assertEquals("2015-011A", segment0.getMetadata().getObjectID());
632 Assertions.assertEquals("EME2000", segment0.getMetadata().getEndpoints().getFrameA().getName());
633 Assertions.assertEquals(SpacecraftBodyFrame.BaseEquipment.SC_BODY, segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
634 Assertions.assertEquals("1", segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
635 Assertions.assertEquals(new AbsoluteDate("2023-01-01T00:00:00.000", tai), segment0.getMetadata().getStartTime());
636 Assertions.assertEquals(new AbsoluteDate("2023-01-01T00:04:30.000", tai), segment0.getMetadata().getStopTime());
637 Assertions.assertEquals(AttitudeType.EULER_ANGLE_DERIVATIVE, segment0.getMetadata().getAttitudeType());
638 Assertions.assertEquals(RotationOrder.ZXZ, segment0.getMetadata().getEulerRotSeq());
639 Assertions.assertEquals(10, segment0.getData().getAngularCoordinates().size());
640
641 Assertions.assertEquals(AttitudeType.SPIN_NUTATION_MOMENTUM,
642 file.getSegments().get(1).getMetadata().getAttitudeType());
643 Assertions.assertEquals(AttitudeType.QUATERNION,
644 file.getSegments().get(2).getMetadata().getAttitudeType());
645 Assertions.assertEquals(AttitudeType.QUATERNION_ANGVEL,
646 file.getSegments().get(3).getMetadata().getAttitudeType());
647 Assertions.assertEquals(AttitudeType.EULER_ANGLE_ANGVEL,
648 file.getSegments().get(4).getMetadata().getAttitudeType());
649
650 }
651
652 @Test
653 public void testWrongNDMType() {
654 final String name = "/ccsds/odm/opm/OPMExample1.txt";
655 try {
656 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
657 new ParserBuilder().buildAemParser().parseMessage(source);
658 Assertions.fail("an exception should have been thrown");
659 } catch (OrekitException oe) {
660 Assertions.assertEquals(OrekitMessages.UNSUPPORTED_FILE_FORMAT, oe.getSpecifier());
661 Assertions.assertEquals(name, oe.getParts()[0]);
662 }
663 }
664
665 @Test
666 public void testNonExistentFile() throws URISyntaxException {
667 final String realName = getClass().getResource("/ccsds/adm/aem/AEMExample01.txt").toURI().getPath();
668 final String wrongName = realName + "xxxxx";
669 final DataSource source = new DataSource(wrongName, () -> getClass().getResourceAsStream(wrongName));
670 try {
671 new ParserBuilder().buildAemParser().parseMessage(source);
672 Assertions.fail("an exception should have been thrown");
673 } catch (OrekitException oe) {
674 Assertions.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
675 Assertions.assertEquals(wrongName, oe.getParts()[0]);
676 }
677 }
678
679 @Test
680 public void testMissingAttitudeType() {
681 try {
682 final String name = "/ccsds/adm/aem/AEM-missing-attitude-type.txt";
683 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
684 new ParserBuilder().buildAemParser().parseMessage(source);
685 Assertions.fail("an exception should have been thrown");
686 } catch (OrekitException oe) {
687 Assertions.assertEquals(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, oe.getSpecifier());
688 Assertions.assertEquals(AemMetadataKey.ATTITUDE_TYPE.name(), oe.getParts()[0]);
689 }
690 }
691
692 @Test
693 public void testInconsistentDirection() {
694 try {
695 final String name = "/ccsds/adm/aem/AEM-inconsistent-direction.txt";
696 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
697 new ParserBuilder().buildAemParser().parseMessage(source);
698 Assertions.fail("an exception should have been thrown");
699 } catch (OrekitException oe) {
700 Assertions.assertEquals(OrekitMessages.CCSDS_KEYWORD_NOT_ALLOWED_IN_VERSION, oe.getSpecifier());
701 Assertions.assertEquals(AemMetadataKey.ATTITUDE_DIR, oe.getParts()[0]);
702 Assertions.assertEquals(2.0, (Double) oe.getParts()[1], 1.0e-15);
703 }
704 }
705
706 @Test
707 public void testInconsistentQuaternionType() {
708 try {
709 final String name = "/ccsds/adm/aem/AEM-inconsistent-quaternion-type.txt";
710 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
711 new ParserBuilder().buildAemParser().parseMessage(source);
712 Assertions.fail("an exception should have been thrown");
713 } catch (OrekitException oe) {
714 Assertions.assertEquals(OrekitMessages.CCSDS_KEYWORD_NOT_ALLOWED_IN_VERSION, oe.getSpecifier());
715 Assertions.assertEquals(AemMetadataKey.QUATERNION_TYPE, oe.getParts()[0]);
716 Assertions.assertEquals(2.0, (Double) oe.getParts()[1], 1.0e-15);
717 }
718 }
719
720 @Test
721 public void testLowerCaseValue() {
722
723 String file = "/ccsds/adm/aem/aemLowerCaseValue.aem";
724 final DataSource source = new DataSource(file, () -> getClass().getResourceAsStream(file));
725
726
727 Aem actual = new ParserBuilder().buildAemParser().parseMessage(source);
728
729
730 Assertions.assertEquals(
731 CelestialBodyFactory.getEarth(),
732 actual.getSegments().get(0).getMetadata().getCenter().getBody());
733 }
734
735 @Test
736 public void testWrongFile() {
737 final String name = "/ccsds/odm/opm/OPMExample1.txt";
738 try {
739 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
740 new ParserBuilder().buildAemParser().parseMessage(source);
741 Assertions.fail("an exception should have been thrown");
742 } catch (OrekitException oe) {
743 Assertions.assertEquals(OrekitMessages.UNSUPPORTED_FILE_FORMAT, oe.getSpecifier());
744 Assertions.assertEquals(name, oe.getParts()[0]);
745 }
746 }
747
748 @Test
749 public void testWrongKeyword() {
750
751 final String name = "/ccsds/adm/aem/AEM-wrong-keyword.txt";
752 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
753 try {
754 new ParserBuilder().buildAemParser().parseMessage(source);
755 Assertions.fail("an exception should have been thrown");
756 } catch (OrekitException oe) {
757 Assertions.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
758 Assertions.assertEquals(24, ((Integer) oe.getParts()[0]).intValue());
759 Assertions.assertTrue(((String) oe.getParts()[2]).startsWith("WRONG_KEYWORD"));
760 }
761 }
762
763 @Test
764 public void testEphemerisNumberFormatErrorType() {
765 final String name = "/ccsds/adm/aem/AEM-ephemeris-number-format-error.txt";
766 try {
767 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
768 new ParserBuilder().buildAemParser().parseMessage(source);
769 Assertions.fail("an exception should have been thrown");
770 } catch (OrekitException oe) {
771 Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
772 Assertions.assertEquals(28, oe.getParts()[0]);
773 Assertions.assertEquals(name, oe.getParts()[1]);
774 Assertions.assertEquals("1996-11-28T22:08:03.5555 0.42319 this-is-not-a-number 0.23784 0.74533", oe.getParts()[2]);
775 }
776 }
777
778 @Test
779 public void testKeywordWithinEphemeris() {
780
781 final String name = "/ccsds/adm/aem/AEM-keyword-within-ephemeris.txt";
782 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
783 try {
784 new ParserBuilder().buildAemParser().parseMessage(source);
785 Assertions.fail("an exception should have been thrown");
786 } catch (OrekitException oe) {
787 Assertions.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
788 Assertions.assertEquals(29, ((Integer) oe.getParts()[0]).intValue());
789 Assertions.assertTrue(((String) oe.getParts()[2]).startsWith("USER_DEFINED_TEST_KEY"));
790 }
791 }
792
793 @Test
794 public void testWrongRotationSequence() {
795
796 final String name = "/ccsds/adm/aem/AEM-inconsistent-rotation-sequence.txt";
797 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
798 try {
799 new ParserBuilder().buildAemParser().parseMessage(source);
800 Assertions.fail("an exception should have been thrown");
801 } catch (OrekitException oe) {
802 Assertions.assertEquals(OrekitMessages.CCSDS_INVALID_ROTATION_SEQUENCE, oe.getSpecifier());
803 Assertions.assertEquals("7051995", oe.getParts()[0]);
804 Assertions.assertEquals(22, ((Integer) oe.getParts()[1]).intValue());
805 Assertions.assertEquals(name, oe.getParts()[2]);
806 }
807 }
808
809 @Test
810 public void testSpuriousMetaDataSection() {
811 final String name = "/ccsds/adm/aem/spurious-metadata.txt";
812 final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
813 try {
814 new ParserBuilder().buildAemParser().parseMessage(source);
815 Assertions.fail("an exception should have been thrown");
816 } catch (OrekitException oe) {
817 Assertions.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
818 Assertions.assertEquals(26, ((Integer) oe.getParts()[0]).intValue());
819 Assertions.assertEquals("META", oe.getParts()[2]);
820 }
821 }
822
823 @Test
824 public void testMissingConvention() {
825 final String ex = "/ccsds/adm/aem/AEMExample01.txt";
826 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
827 final Aem file = new ParserBuilder().buildAemParser().parseMessage(source);
828 try {
829 file.getConventions();
830 } catch (OrekitException oe) {
831 Assertions.assertEquals(OrekitMessages.CCSDS_UNKNOWN_CONVENTIONS, oe.getSpecifier());
832 }
833 }
834
835 private void verifyAngularCoordinates(final TimeStampedAngularCoordinates expected,
836 final TimeStampedAngularCoordinates actual,
837 final double threshold) {
838
839 Assertions.assertEquals(0.0, expected.getDate().durationFrom(actual.getDate()), threshold);
840
841
842 Assertions.assertEquals(expected.getRotation().getQ0(), actual.getRotation().getQ0(), threshold);
843 Assertions.assertEquals(expected.getRotation().getQ1(), actual.getRotation().getQ1(), threshold);
844 Assertions.assertEquals(expected.getRotation().getQ2(), actual.getRotation().getQ2(), threshold);
845 Assertions.assertEquals(expected.getRotation().getQ3(), actual.getRotation().getQ3(), threshold);
846
847 Assertions.assertEquals(0.0, expected.getRotationRate().distance(actual.getRotationRate()), threshold);
848 }
849
850
851
852
853
854 @Test
855 public void testDefaultInterpolationDegree() {
856
857 final String name = "/ccsds/adm/aem/AEMExample01.txt";
858 ParserBuilder builder = new ParserBuilder();
859
860 final DataSource source1 = new DataSource(name, () -> getClass().getResourceAsStream(name));
861 final Aem file = builder.buildAemParser().parseMessage(source1);
862 Assertions.assertEquals(7, file.getSegments().get(0).getMetadata().getInterpolationDegree());
863 Assertions.assertEquals(1, file.getSegments().get(1).getMetadata().getInterpolationDegree());
864
865 final DataSource source2 = new DataSource(name, () -> getClass().getResourceAsStream(name));
866 final Aem file2 = builder.withDefaultInterpolationDegree(5).buildAemParser().parseMessage(source2);
867 Assertions.assertEquals(7, file2.getSegments().get(0).getMetadata().getInterpolationDegree());
868 Assertions.assertEquals(5, file2.getSegments().get(1).getMetadata().getInterpolationDegree());
869 }
870
871 @Test
872 public void testIssue739() {
873 final String ex = "/ccsds/adm/aem/AEMExample08.txt";
874 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
875 final Aem file = new ParserBuilder().buildAemParser().parseMessage(source);
876 final AemSegment segment0 = file.getSegments().get(0);
877 Assertions.assertEquals(CelestialBodyFrame.GTOD, segment0.getMetadata().getEndpoints().getFrameB().asCelestialBodyFrame());
878
879 final BoundedAttitudeProvider provider = segment0.getAttitudeProvider();
880 Attitude attitude = provider.getAttitude(null, new AbsoluteDate("1996-11-28T22:08:03.555", TimeScalesFactory.getUTC()), null);
881 Rotation rotation = attitude.getRotation();
882 Assertions.assertEquals(0.42319, rotation.getQ1(), 0.0001);
883 Assertions.assertEquals(-0.45697, rotation.getQ2(), 0.0001);
884 Assertions.assertEquals(0.23784, rotation.getQ3(), 0.0001);
885 Assertions.assertEquals(0.74533, rotation.getQ0(), 0.0001);
886 Assertions.assertEquals(0.0, provider.getMinDate().durationFrom(segment0.getMetadata().getStart()), 0.0001);
887 Assertions.assertEquals(0.0, provider.getMaxDate().durationFrom(segment0.getMetadata().getStop()), 0.0001);
888
889 }
890
891 @Test
892 public void testIssue739_2() {
893 final String ex = "/ccsds/adm/aem/AEMExample09.txt";
894 final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
895 final Aem file = new ParserBuilder().buildAemParser().parseMessage(source);
896 final AemSegment segment0 = file.getSegments().get(0);
897 Assertions.assertEquals(FramesFactory.getITRF(ITRFVersion.ITRF_1993, IERSConventions.IERS_2010, true),
898 segment0.getMetadata().getEndpoints().getFrameA().asFrame());
899
900 final BoundedAttitudeProvider provider = segment0.getAttitudeProvider();
901 Attitude attitude = provider.getAttitude(null, new AbsoluteDate("1996-11-28T22:08:03.555", TimeScalesFactory.getUTC()), null);
902 Rotation rotation = attitude.getRotation();
903 Assertions.assertEquals(0.42319, rotation.getQ1(), 0.0001);
904 Assertions.assertEquals(-0.45697, rotation.getQ2(), 0.0001);
905 Assertions.assertEquals(0.23784, rotation.getQ3(), 0.0001);
906 Assertions.assertEquals(0.74533, rotation.getQ0(), 0.0001);
907 Assertions.assertEquals(0.0, provider.getMinDate().durationFrom(segment0.getMetadata().getStart()), 0.0001);
908 Assertions.assertEquals(0.0, provider.getMaxDate().durationFrom(segment0.getMetadata().getStop()), 0.0001);
909
910 }
911
912
913 @Test
914 public void testFrameMapper() {
915
916 TimeScale tai = TimeScalesFactory.getTAI();
917 AbsoluteDate expectedEpoch = new AbsoluteDate("2023-01-01T00:00:00.0000", tai);
918 Frame parent = FramesFactory.getEME2000();
919 Frame itrf93 = FramesFactory.getITRF(ITRFVersion.ITRF_1993, IERSConventions.IERS_2010, true);
920 Frame myJ2000 = new Frame(parent, Transform.IDENTITY, "MyJ2000");
921 Frame scBodyFrame = new Frame(parent, new Transform(expectedEpoch, new Rotation(RotationOrder.XYZ, RotationConvention.FRAME_TRANSFORM,
922 Math.PI / 4, Math.PI / 2, Math.PI /3)), "SC_BODY_1");
923 CcsdsFrameMapper mapper = new CcsdsFrameMapper() {
924 @Override
925 public Frame buildCcsdsFrame(FrameFacade orientation, AbsoluteDate epoch) {
926 if ("SC_BODY_1".equals(orientation.getName()) && null == epoch) {
927 return scBodyFrame;
928 } else if (("J2000".equals(orientation.getName()) || "EME2000".equals(orientation.getName()))
929 && null == epoch) {
930 return myJ2000;
931 } else if ("ITRF1993".equals(orientation.getName()) && null == epoch) {
932 return itrf93;
933 } else {
934 throw new IllegalArgumentException(orientation.getName() + " " + epoch);
935 }
936 }
937
938 @Override
939 public Frame buildCcsdsFrame(BodyFacade center,
940 FrameFacade orientation,
941 AbsoluteDate epoch) {
942 if ("EARTH".equals(center.getName()) &&
943 "SC_BODY_1".equals(orientation.getName()) &&
944 null == epoch) {
945 return scBodyFrame;
946 } else if ("EARTH".equals(center.getName()) && null == epoch &&
947 ("EME2000".equals(orientation.getName()) || "J2000".equals(orientation.getName()))) {
948 return myJ2000;
949 } else if ("EARTH".equals(center.getName()) && "ITRF1993".equals(orientation.getName()) &&
950 null == epoch) {
951 return itrf93;
952 } else {
953 throw new IllegalArgumentException(
954 center + " " + orientation + " " + epoch);
955 }
956 }
957
958 };
959
960
961 final String quaternionExample = "/ccsds/adm/aem/AEMExample04.txt";
962 final String eulerExample = "/ccsds/adm/aem/AEMExample12.txt";
963 final String spinExample = "/ccsds/adm/aem/AEMExample06b.txt";
964 final DataSource quaternionSource = new DataSource(quaternionExample, () -> getClass().getResourceAsStream(quaternionExample));
965 final DataSource eulerSource = new DataSource(eulerExample, () -> getClass().getResourceAsStream(eulerExample));
966 final DataSource spinSource = new DataSource(spinExample, () -> getClass().getResourceAsStream(spinExample));
967
968
969 final AemParser parser = new ParserBuilder().withFrameMapper(mapper).buildAemParser();
970 final Aem qAem = parser.parseMessage(quaternionSource);
971 final Aem eAem = parser.parseMessage(eulerSource);
972 final Aem sAem = parser.parseMessage(spinSource);
973
974
975
976 final AemSegment qAemSegment = qAem.getSegments().get(0);
977 final AemMetadata qAemMetadata = qAemSegment.getMetadata();
978 final AttitudeEndpoints qEndpoints = qAemMetadata.getEndpoints();
979 final BodyFacade qCenter = qAemMetadata.getCenter();
980 final AemSegment eAemSegment = eAem.getSegments().get(0);
981 final AemMetadata eAemMetadata = eAemSegment.getMetadata();
982 final AttitudeEndpoints eEndpoints = eAemMetadata.getEndpoints();
983 final BodyFacade eCenter = eAemMetadata.getCenter();
984 final AemSegment sAemSegment = sAem.getSegments().get(0);
985 final AemMetadata sAemMetadata = sAemSegment.getMetadata();
986 final AttitudeEndpoints sEndpoints = sAemMetadata.getEndpoints();
987 final BodyFacade sCenter = sAemMetadata.getCenter();
988
989
990 MatcherAssert.assertThat(qAemSegment.getReferenceFrame(), Matchers.sameInstance(myJ2000));
991 MatcherAssert.assertThat(
992 qAemSegment.getMetadata().getEndpoints().getExternal(),
993 Matchers.sameInstance(myJ2000));
994 MatcherAssert.assertThat(
995 qAemSegment.getMetadata().getFrameMapper(),
996 Matchers.sameInstance(mapper));
997
998 MatcherAssert.assertThat(
999 mapper.buildCcsdsFrame(qCenter, qEndpoints.getFrameA(), null),
1000 Matchers.sameInstance(myJ2000));
1001 MatcherAssert.assertThat(
1002 mapper.buildCcsdsFrame(qCenter, qEndpoints.getFrameB(), null),
1003 Matchers.sameInstance(scBodyFrame));
1004
1005 MatcherAssert.assertThat(eAemSegment.getReferenceFrame(), Matchers.sameInstance(itrf93));
1006 MatcherAssert.assertThat(
1007 eAemSegment.getMetadata().getEndpoints().getExternal(),
1008 Matchers.sameInstance(itrf93));
1009 MatcherAssert.assertThat(
1010 mapper.buildCcsdsFrame(eCenter, eEndpoints.getFrameA(), null),
1011 Matchers.sameInstance(itrf93));
1012 MatcherAssert.assertThat(
1013 mapper.buildCcsdsFrame(eCenter, eEndpoints.getFrameB(), null),
1014 Matchers.sameInstance(scBodyFrame));
1015
1016 MatcherAssert.assertThat(sAemSegment.getReferenceFrame(), Matchers.sameInstance(myJ2000));
1017 MatcherAssert.assertThat(
1018 sAemSegment.getMetadata().getEndpoints().getExternal(),
1019 Matchers.sameInstance(myJ2000));
1020 MatcherAssert.assertThat(
1021 mapper.buildCcsdsFrame(sCenter, sEndpoints.getFrameA(), null),
1022 Matchers.sameInstance(myJ2000));
1023 MatcherAssert.assertThat(
1024 mapper.buildCcsdsFrame(sCenter, sEndpoints.getFrameB(), null),
1025 Matchers.sameInstance(scBodyFrame));
1026 }
1027
1028
1029 @Test
1030 @Deprecated
1031 public void testDeprecatedConstructor() {
1032
1033 AemParser actual = new AemParser(
1034 null, true, null, null, 0, null, new Function[0]);
1035
1036
1037 MatcherAssert.assertThat(actual.getFrameMapper(),
1038 Matchers.is(new OrekitCcsdsFrameMapper()));
1039 }
1040
1041 }