1   /* Copyright 2022-2025 Luc Maisonobe
2    * Licensed to CS Systèmes d'Information (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.files.ccsds.ndm.adm.acm;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.CharArrayWriter;
21  import java.io.IOException;
22  import java.nio.charset.StandardCharsets;
23  import java.util.List;
24  
25  import org.hipparchus.geometry.euclidean.threed.RotationOrder;
26  import org.hipparchus.linear.DiagonalMatrix;
27  import org.hipparchus.util.FastMath;
28  import org.junit.jupiter.api.Assertions;
29  import org.junit.jupiter.api.BeforeEach;
30  import org.junit.jupiter.api.Test;
31  import org.orekit.Utils;
32  import org.orekit.data.DataSource;
33  import org.orekit.errors.OrekitException;
34  import org.orekit.errors.OrekitMessages;
35  import org.orekit.files.ccsds.definitions.AdMethodType;
36  import org.orekit.files.ccsds.definitions.CenterName;
37  import org.orekit.files.ccsds.definitions.SpacecraftBodyFrame.BaseEquipment;
38  import org.orekit.files.ccsds.ndm.ParserBuilder;
39  import org.orekit.files.ccsds.ndm.WriterBuilder;
40  import org.orekit.files.ccsds.utils.generation.Generator;
41  import org.orekit.files.ccsds.utils.generation.XmlGenerator;
42  import org.orekit.files.ccsds.utils.lexical.KvnLexicalAnalyzer;
43  import org.orekit.files.ccsds.utils.lexical.XmlLexicalAnalyzer;
44  import org.orekit.time.AbsoluteDate;
45  import org.orekit.time.TimeOffset;
46  import org.orekit.time.TimeScalesFactory;
47  import org.orekit.utils.Constants;
48  
49  public class AcmParserTest {
50  
51      @BeforeEach
52      public void setUp() {
53          Utils.setDataRoot("regular-data");
54      }
55  
56      @Test
57      public void testNonExistentKvnFile() {
58          final String realName = "/ccsds/adm/acm/ACMExample01.txt";
59          final String wrongName = realName + "xxxxx";
60          final DataSource source = new DataSource(wrongName, () -> getClass().getResourceAsStream(wrongName));
61          try {
62              new KvnLexicalAnalyzer(source).accept(new ParserBuilder().buildAcmParser());
63              Assertions.fail("an exception should have been thrown");
64          } catch (OrekitException oe) {
65              Assertions.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
66              Assertions.assertEquals(wrongName, oe.getParts()[0]);
67          }
68      }
69  
70      @Test
71      public void testNonExistentXmlFile() {
72          final String realName = "/ccsds/adm/acm/ACMExample01.txt";
73          final String wrongName = realName + "xxxxx";
74          final DataSource source = new DataSource(wrongName, () -> getClass().getResourceAsStream(wrongName));
75          try {
76              new XmlLexicalAnalyzer(source).accept(new ParserBuilder().buildAcmParser());
77              Assertions.fail("an exception should have been thrown");
78          } catch (OrekitException oe) {
79              Assertions.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
80              Assertions.assertEquals(wrongName, oe.getParts()[0]);
81          }
82      }
83  
84      @Test
85      public void testIncompatibleKeys() {
86          final String name = "/ccsds/adm/acm/incompatible-keys.txt";
87          final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
88          try {
89              new ParserBuilder().buildAcmParser().parseMessage(source);
90              Assertions.fail("an exception should have been thrown");
91          } catch (OrekitException oe) {
92              Assertions.assertEquals(OrekitMessages.CCSDS_INCOMPATIBLE_KEYS_BOTH_USED, oe.getSpecifier());
93              Assertions.assertEquals(AttitudeManeuverKey.MAN_END_TIME, oe.getParts()[0]);
94              Assertions.assertEquals(AttitudeManeuverKey.MAN_DURATION, oe.getParts()[1]);
95          }
96      }
97  
98      @Test
99      public void testSensorIndexAlreadyUsed() {
100         final String name = "/ccsds/adm/acm/sensor-index-already-used.txt";
101         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
102         try {
103             new ParserBuilder().buildAcmParser().parse(source);
104             Assertions.fail("an exception should have been thrown");
105         } catch (OrekitException oe) {
106             Assertions.assertEquals(OrekitMessages.CCSDS_SENSOR_INDEX_ALREADY_USED, oe.getSpecifier());
107             Assertions.assertEquals(2, ((Integer) oe.getParts()[0]).intValue());
108         }
109     }
110 
111     @Test
112     public void testMissingSensorIndex() {
113         final String name = "/ccsds/adm/acm/missing-sensor-index.txt";
114         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
115         try {
116             new ParserBuilder().buildAcmParser().parseMessage(source);
117             Assertions.fail("an exception should have been thrown");
118         } catch (OrekitException oe) {
119             Assertions.assertEquals(OrekitMessages.CCSDS_MISSING_SENSOR_INDEX, oe.getSpecifier());
120             Assertions.assertEquals(3, ((Integer) oe.getParts()[0]).intValue());
121         }
122     }
123 
124     @Test
125     public void testWrongStdDevNumber() {
126         final String name = "/ccsds/adm/acm/wrong-stddev-number.txt";
127         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
128         try {
129             new ParserBuilder().buildAcmParser().parseMessage(source);
130             Assertions.fail("an exception should have been thrown");
131         } catch (OrekitException oe) {
132             Assertions.assertEquals(OrekitMessages.INCONSISTENT_NUMBER_OF_ELEMENTS, oe.getSpecifier());
133             Assertions.assertEquals(1, ((Integer) oe.getParts()[0]).intValue());
134             Assertions.assertEquals(2, ((Integer) oe.getParts()[1]).intValue());
135         }
136     }
137 
138     @Test
139     public void testSpuriousMetaDataSection() {
140         final String name = "/ccsds/adm/acm/spurious-metadata.txt";
141         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
142         try {
143             new ParserBuilder().buildAcmParser().parseMessage(source);
144             Assertions.fail("an exception should have been thrown");
145         } catch (OrekitException oe) {
146             Assertions.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
147             Assertions.assertEquals(13, ((Integer) oe.getParts()[0]).intValue());
148             Assertions.assertEquals("META", oe.getParts()[2]);
149         }
150     }
151 
152     @Test
153     public void testMissingTargetMomentum() {
154         final String name = "/ccsds/adm/acm/missing-target-momentum.txt";
155         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
156         try {
157             new ParserBuilder().buildAcmParser().parseMessage(source);
158             Assertions.fail("an exception should have been thrown");
159         } catch (OrekitException oe) {
160             Assertions.assertEquals(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, oe.getSpecifier());
161             Assertions.assertEquals(AttitudeManeuverKey.TARGET_MOMENTUM.name(), oe.getParts()[0]);
162         }
163     }
164 
165     @Test
166     public void testMissingCenterOfPressure() {
167         final String name = "/ccsds/adm/acm/missing-center-of-pressure.txt";
168         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
169         try {
170             new ParserBuilder().buildAcmParser().parseMessage(source);
171             Assertions.fail("an exception should have been thrown");
172         } catch (OrekitException oe) {
173             Assertions.assertEquals(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, oe.getSpecifier());
174             Assertions.assertEquals(AttitudePhysicalPropertiesKey.CP.name(), oe.getParts()[0]);
175         }
176     }
177 
178     @Test
179     public void testParseACM01() {
180         final String   name  = "/ccsds/adm/acm/ACMExample01.txt";
181         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
182         final Acm    acm    = new ParserBuilder().buildAcmParser().parseMessage(source);
183 
184         // Check Header Block;
185         Assertions.assertEquals(2.0, acm.getHeader().getFormatVersion(), 1.0e-10);
186         Assertions.assertEquals("unrestricted", acm.getHeader().getClassification());
187         Assertions.assertEquals(new AbsoluteDate(1998, 11, 6, 9, 23, 57, TimeScalesFactory.getUTC()),
188                                 acm.getHeader().getCreationDate());
189         Assertions.assertEquals("JAXA", acm.getHeader().getOriginator());
190         Assertions.assertEquals("A7015Z4", acm.getHeader().getMessageId());
191 
192         // metadata
193         Assertions.assertEquals("EUROBIRD-4A", acm.getMetadata().getObjectName());
194         Assertions.assertEquals("2000-052A",   acm.getMetadata().getInternationalDesignator());
195         Assertions.assertEquals(2000,          acm.getMetadata().getLaunchYear());
196         Assertions.assertEquals(52,            acm.getMetadata().getLaunchNumber());
197         Assertions.assertEquals("A",           acm.getMetadata().getLaunchPiece());
198         Assertions.assertEquals("UTC",         acm.getMetadata().getTimeSystem().name());
199         Assertions.assertEquals(new AbsoluteDate(1998, 12, 18, 14, 28, new TimeOffset(15, TimeOffset.SECOND, 117200, TimeOffset.MICROSECOND), TimeScalesFactory.getUTC()),
200                                 acm.getMetadata().getEpochT0());        
201 
202         // attitude data
203         Assertions.assertEquals(1, acm.getData().getAttitudeBlocks().size());
204         AttitudeStateHistory history = acm.getData().getAttitudeBlocks().get(0);
205         Assertions.assertTrue(history.getMetadata().getComments().isEmpty());
206         Assertions.assertNull(history.getMetadata().getAttID());
207         Assertions.assertNull(history.getMetadata().getAttPrevID());
208         Assertions.assertNull(history.getMetadata().getAttBasis());
209         Assertions.assertNull(history.getMetadata().getAttBasisID());
210         Assertions.assertEquals("J2000", history.getMetadata().getEndpoints().getFrameA().getName());
211         Assertions.assertEquals(BaseEquipment.SC_BODY, history.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
212         Assertions.assertEquals("1", history.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
213         Assertions.assertEquals(4, history.getMetadata().getNbStates());
214         Assertions.assertEquals(AttitudeElementsType.QUATERNION, history.getMetadata().getAttitudeType());
215         Assertions.assertNull(history.getMetadata().getRateType());
216         List<AttitudeState> states = history.getAttitudeStates();
217         Assertions.assertEquals(3, states.size());
218 
219         Assertions.assertEquals(0.0, states.get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
220         Assertions.assertEquals(4,   states.get(0).getElements().length);
221         Assertions.assertEquals( 0.73566,  states.get(0).getElements()[0], 1.0e-15);
222         Assertions.assertEquals(-0.50547,  states.get(0).getElements()[1], 1.0e-15);
223         Assertions.assertEquals( 0.41309,  states.get(0).getElements()[2], 1.0e-15);
224         Assertions.assertEquals( 0.180707, states.get(0).getElements()[3], 1.0e-15);
225 
226         Assertions.assertEquals(0.25, states.get(1).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
227         Assertions.assertEquals(4,    states.get(1).getElements().length);
228         Assertions.assertEquals( 0.73529,  states.get(1).getElements()[0], 1.0e-15);
229         Assertions.assertEquals(-0.50531,  states.get(1).getElements()[1], 1.0e-15);
230         Assertions.assertEquals( 0.41375,  states.get(1).getElements()[2], 1.0e-15);
231         Assertions.assertEquals( 0.181158, states.get(1).getElements()[3], 1.0e-15);
232 
233         Assertions.assertEquals(0.50, states.get(2).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
234         Assertions.assertEquals(4,    states.get(2).getElements().length);
235         Assertions.assertEquals( 0.73492,  states.get(2).getElements()[0], 1.0e-15);
236         Assertions.assertEquals(-0.50515,  states.get(2).getElements()[1], 1.0e-15);
237         Assertions.assertEquals( 0.41441,  states.get(2).getElements()[2], 1.0e-15);
238         Assertions.assertEquals( 0.181610, states.get(2).getElements()[3], 1.0e-15);
239 
240         Assertions.assertNull(acm.getSegments().get(0).getData().getPhysicBlock());
241         Assertions.assertNull(acm.getSegments().get(0).getData().getCovarianceBlocks());
242         Assertions.assertNull(acm.getSegments().get(0).getData().getManeuverBlocks());
243         Assertions.assertNull(acm.getSegments().get(0).getData().getAttitudeDeterminationBlock());
244         Assertions.assertNull(acm.getSegments().get(0).getData().getUserDefinedBlock());
245 
246     }
247 
248     @Test
249     public void testParseACM02() {
250         final String   name  = "/ccsds/adm/acm/ACMExample02.txt";
251         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
252         final Acm    acm    = new ParserBuilder().buildAcmParser().parseMessage(source);
253 
254         // Check Header Block;
255         Assertions.assertEquals(2.0, acm.getHeader().getFormatVersion(), 1.0e-10);
256         Assertions.assertNull(acm.getHeader().getClassification());
257         Assertions.assertEquals(new AbsoluteDate(2017, 12, 1, TimeScalesFactory.getUTC()),
258                                 acm.getHeader().getCreationDate());
259         Assertions.assertEquals("NASA", acm.getHeader().getOriginator());
260         Assertions.assertEquals("A7015Z5", acm.getHeader().getMessageId());
261 
262         // metadata
263         Assertions.assertEquals("SDO",         acm.getMetadata().getObjectName());
264         Assertions.assertEquals("2010-005A",   acm.getMetadata().getInternationalDesignator());
265         Assertions.assertEquals(2010,          acm.getMetadata().getLaunchYear());
266         Assertions.assertEquals(5,             acm.getMetadata().getLaunchNumber());
267         Assertions.assertEquals("A",           acm.getMetadata().getLaunchPiece());
268         Assertions.assertEquals("UTC",         acm.getMetadata().getTimeSystem().name());
269         Assertions.assertEquals(new AbsoluteDate(2017, 12, 26, 19, 40, 0.0, TimeScalesFactory.getUTC()),
270                                 acm.getMetadata().getEpochT0());        
271 
272         // attitude data
273         Assertions.assertEquals(1, acm.getData().getAttitudeBlocks().size());
274         AttitudeStateHistory history = acm.getData().getAttitudeBlocks().get(0);
275         Assertions.assertEquals("OBC Attitude and Bias during momentum management maneuver",
276                                 history.getMetadata().getComments().get(0));
277         Assertions.assertNull(history.getMetadata().getAttID());
278         Assertions.assertNull(history.getMetadata().getAttPrevID());
279         Assertions.assertNull(history.getMetadata().getAttBasis());
280         Assertions.assertNull(history.getMetadata().getAttBasisID());
281         Assertions.assertEquals("J2000", history.getMetadata().getEndpoints().getFrameA().getName());
282         Assertions.assertEquals(BaseEquipment.SC_BODY, history.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
283         Assertions.assertEquals("1", history.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
284         Assertions.assertEquals(7, history.getMetadata().getNbStates());
285         Assertions.assertEquals(AttitudeElementsType.QUATERNION, history.getMetadata().getAttitudeType());
286         Assertions.assertEquals(RateElementsType.GYRO_BIAS, history.getMetadata().getRateType());
287         List<AttitudeState> states = history.getAttitudeStates();
288         Assertions.assertEquals(4, states.size());
289 
290         Assertions.assertEquals(0.0, states.get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
291         Assertions.assertEquals(7,   states.get(0).getElements().length);
292         Assertions.assertEquals( 0.1153,    states.get(0).getElements()[0], 1.0e-15);
293         Assertions.assertEquals(-0.1424,    states.get(0).getElements()[1], 1.0e-15);
294         Assertions.assertEquals( 0.8704,    states.get(0).getElements()[2], 1.0e-15);
295         Assertions.assertEquals( 0.4571,    states.get(0).getElements()[3], 1.0e-15);
296         Assertions.assertEquals( 2.271e-06, FastMath.toDegrees(states.get(0).getElements()[4]), 1.0e-15);
297         Assertions.assertEquals(-4.405e-06, FastMath.toDegrees(states.get(0).getElements()[5]), 1.0e-15);
298         Assertions.assertEquals(-3.785e-06, FastMath.toDegrees(states.get(0).getElements()[6]), 1.0e-15);
299 
300         Assertions.assertEquals(1, acm.getData().getManeuverBlocks().size());
301         AttitudeManeuver man = acm.getData().getManeuverBlocks().get(0);
302         Assertions.assertEquals("Momentum management maneuver", man.getComments().get(0));
303         Assertions.assertEquals("MOM_DESAT",                    man.getManPurpose());
304         Assertions.assertEquals(100.0,                          man.getBeginTime());
305         Assertions.assertTrue(Double.isNaN(man.getEndTime()));
306         Assertions.assertEquals(450.0,                          man.getDuration());
307         Assertions.assertEquals("ATT-THRUSTER",                 man.getActuatorUsed());
308         Assertions.assertEquals(  1.3,                          man.getTargetMomentum().getX(), 1.0e-10);
309         Assertions.assertEquals(-16.4,                          man.getTargetMomentum().getY(), 1.0e-10);
310         Assertions.assertEquals(-11.35,                         man.getTargetMomentum().getZ(), 1.0e-10);
311         Assertions.assertNull(man.getTargetAttitude());
312         Assertions.assertTrue(Double.isNaN(man.getTargetSpinRate()));
313 
314         AttitudeDetermination ad = acm.getData().getAttitudeDeterminationBlock();
315         Assertions.assertEquals("SDO Onboard Filter",    ad.getComments().get(0));
316         Assertions.assertEquals(AdMethodType.EKF,        ad.getMethod());
317         Assertions.assertEquals("OBC",                   ad.getSource());
318         Assertions.assertEquals(AttitudeElementsType.QUATERNION, ad.getAttitudeStates());
319         Assertions.assertEquals("J2000",                 ad.getEndpoints().getFrameA().getName());
320         Assertions.assertEquals(BaseEquipment.SC_BODY,   ad.getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
321         Assertions.assertEquals("1",                     ad.getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
322         Assertions.assertEquals(4,                       ad.getSensorsUsed().size());
323         Assertions.assertEquals("AST1",                  ad.getSensorsUsed().get(0).getSensorUsed());
324         Assertions.assertEquals("AST2",                  ad.getSensorsUsed().get(1).getSensorUsed());
325         Assertions.assertEquals("DSS",                   ad.getSensorsUsed().get(2).getSensorUsed());
326         Assertions.assertEquals("IMU",                   ad.getSensorsUsed().get(3).getSensorUsed());
327 
328     }
329 
330     @Test
331     public void testParseACM03() {
332         final String     name   = "/ccsds/adm/acm/ACMExample03.txt";
333         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
334         final Acm        acm    = new ParserBuilder().buildAcmParser().parseMessage(source);
335 
336         // Check Header Block;
337         Assertions.assertEquals(2.0, acm.getHeader().getFormatVersion(), 1.0e-10);
338        Assertions.assertEquals(new AbsoluteDate(1998, 11, 6, 9, 23, 57, TimeScalesFactory.getUTC()),
339                                 acm.getHeader().getCreationDate());
340         Assertions.assertEquals("JAXA", acm.getHeader().getOriginator());
341         Assertions.assertEquals("A7015Z6", acm.getHeader().getMessageId());
342 
343         // metadata
344         Assertions.assertEquals("TEST_SAT",    acm.getMetadata().getObjectName());
345         Assertions.assertNull(acm.getMetadata().getInternationalDesignator());
346         Assertions.assertEquals("TAI",         acm.getMetadata().getTimeSystem().name());
347         Assertions.assertEquals(new AbsoluteDate(1998, 12, 18, 14, 28, new TimeOffset(15, TimeOffset.SECOND, 117200, TimeOffset.MICROSECOND), TimeScalesFactory.getTAI()),
348                                 acm.getMetadata().getEpochT0());  
349         Assertions.assertEquals(36.0,          acm.getMetadata().getTaimutcT0(), 1.0e-15);
350 
351         Assertions.assertNull(acm.getData().getAttitudeBlocks());
352         AttitudePhysicalProperties phys = acm.getData().getPhysicBlock();
353         Assertions.assertEquals("Spacecraft Physical Parameters", phys.getComments().get(0));
354         Assertions.assertEquals(1916.0, phys.getWetMass(), 1.0e-15);
355         Assertions.assertEquals( 0.04,  phys.getCenterOfPressure().getX(),      1.0e-15);
356         Assertions.assertEquals(-0.78,  phys.getCenterOfPressure().getY(),      1.0e-15);
357         Assertions.assertEquals(-0.023, phys.getCenterOfPressure().getZ(),      1.0e-15);
358         Assertions.assertEquals( 752.0, phys.getInertiaMatrix().getEntry(0, 0), 1.0e-15);
359         Assertions.assertEquals(1305.0, phys.getInertiaMatrix().getEntry(1, 1), 1.0e-15);
360         Assertions.assertEquals(1490.0, phys.getInertiaMatrix().getEntry(2, 2), 1.0e-15);
361         Assertions.assertEquals(  81.1, phys.getInertiaMatrix().getEntry(0, 1), 1.0e-15);
362         Assertions.assertEquals(  81.1, phys.getInertiaMatrix().getEntry(1, 0), 1.0e-15);
363         Assertions.assertEquals( -25.7, phys.getInertiaMatrix().getEntry(0, 2), 1.0e-15);
364         Assertions.assertEquals( -25.7, phys.getInertiaMatrix().getEntry(2, 0), 1.0e-15);
365         Assertions.assertEquals(  74.1, phys.getInertiaMatrix().getEntry(1, 2), 1.0e-15);
366         Assertions.assertEquals(  74.1, phys.getInertiaMatrix().getEntry(2, 1), 1.0e-15);
367 
368     }
369 
370     @Test
371     public void testParseACM04() {
372         final String   name  = "/ccsds/adm/acm/ACMExample04.txt";
373         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
374         final Acm    acm    = new ParserBuilder().buildAcmParser().parseMessage(source);
375 
376         // Check Header Block;
377         Assertions.assertEquals(2.0, acm.getHeader().getFormatVersion(), 1.0e-10);
378         Assertions.assertEquals(new AbsoluteDate(2017, 12, 30, TimeScalesFactory.getUTC()),
379                                 acm.getHeader().getCreationDate());
380         Assertions.assertEquals("NASA", acm.getHeader().getOriginator());
381         Assertions.assertEquals("A7015Z7", acm.getHeader().getMessageId());
382 
383         // metadata
384         Assertions.assertEquals("LRO",         acm.getMetadata().getObjectName());
385         Assertions.assertEquals("2009-031A",   acm.getMetadata().getInternationalDesignator());
386         Assertions.assertEquals(2009,          acm.getMetadata().getLaunchYear());
387         Assertions.assertEquals(31,            acm.getMetadata().getLaunchNumber());
388         Assertions.assertEquals("A",           acm.getMetadata().getLaunchPiece());
389         Assertions.assertEquals("UTC",         acm.getMetadata().getTimeSystem().name());
390         Assertions.assertEquals(new AbsoluteDate(2017, 12, 30, 0, 0, 0.0, TimeScalesFactory.getUTC()),
391                                 acm.getMetadata().getEpochT0()); 
392         Assertions.assertEquals(2,             acm.getMetadata().getAcmDataElements().size());
393         Assertions.assertEquals(AcmElements.COV, acm.getMetadata().getAcmDataElements().get(0));
394         Assertions.assertEquals(AcmElements.AD,  acm.getMetadata().getAcmDataElements().get(1));
395 
396         // covariance data
397         Assertions.assertEquals(1, acm.getData().getCovarianceBlocks().size());
398         AttitudeCovarianceHistory history = acm.getData().getCovarianceBlocks().get(0);
399         Assertions.assertEquals("Diagonal Covariance for LRO Onboard Kalman Filter", history.getMetadata().getComments().get(0));
400         Assertions.assertEquals("DETERMINED_OBC", history.getMetadata().getCovBasis());
401         Assertions.assertEquals(BaseEquipment.SC_BODY, history.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getBaseEquipment());
402         Assertions.assertEquals("1", history.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getLabel());
403         Assertions.assertEquals(AttitudeCovarianceType.ANGLE_GYROBIAS, history.getMetadata().getCovType());
404         List<AttitudeCovariance> covariances = history.getCovariances();
405         Assertions.assertEquals(3, covariances.size());
406 
407         Assertions.assertEquals(0.0, covariances.get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
408         DiagonalMatrix m = covariances.get(0).getMatrix();
409         Assertions.assertEquals(6,   m.getRowDimension());
410         Assertions.assertEquals( 6.74E-11, FastMath.toDegrees(FastMath.toDegrees(m.getEntry(0, 0))), 1.0e-22);
411         Assertions.assertEquals( 8.10E-11, FastMath.toDegrees(FastMath.toDegrees(m.getEntry(1, 1))), 1.0e-22);
412         Assertions.assertEquals( 9.22E-11, FastMath.toDegrees(FastMath.toDegrees(m.getEntry(2, 2))), 1.0e-22);
413         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m.getEntry(3, 3))), 1.0e-22);
414         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m.getEntry(4, 4))), 1.0e-22);
415         Assertions.assertEquals( 1.12E-15, FastMath.toDegrees(FastMath.toDegrees(m.getEntry(5, 5))), 1.0e-22);
416 
417         AttitudeDetermination ad = acm.getData().getAttitudeDeterminationBlock();
418         Assertions.assertEquals("LRO Onboard Filter, A Multiplicative Extended Kalman Filter", ad.getComments().get(0));
419         Assertions.assertEquals(AdMethodType.EKF,                      ad.getMethod());
420         Assertions.assertEquals("OBC",                                 ad.getSource());
421         Assertions.assertEquals(7,                                     ad.getNbStates());
422         Assertions.assertEquals(AttitudeElementsType.QUATERNION,       ad.getAttitudeStates());
423         Assertions.assertEquals(AttitudeCovarianceType.ANGLE_GYROBIAS, ad.getCovarianceType());
424         Assertions.assertEquals("EME2000",                             ad.getEndpoints().getFrameA().getName());
425         Assertions.assertEquals(BaseEquipment.SC_BODY,                 ad.getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
426         Assertions.assertEquals("1",                                   ad.getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
427         Assertions.assertEquals(RateElementsType.GYRO_BIAS,            ad.getRateStates());
428         Assertions.assertEquals(3,                                     ad.getSensorsUsed().size());
429         Assertions.assertEquals("AST1",                                ad.getSensorsUsed().get(0).getSensorUsed());
430         Assertions.assertEquals("AST2",                                ad.getSensorsUsed().get(1).getSensorUsed());
431         Assertions.assertEquals("IMU",                                 ad.getSensorsUsed().get(2).getSensorUsed());
432 
433     }
434 
435     @Test
436     public void testParseACM05() {
437         final String   name  = "/ccsds/adm/acm/ACMExample05.txt";
438         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
439         validateAcm05(new ParserBuilder().buildAcmParser().parseMessage(source));
440     }
441 
442     private void validateAcm05(Acm acm) {
443 
444         final AbsoluteDate t0 = new AbsoluteDate(2016, 3, 15, 0, 0, 0.0, TimeScalesFactory.getUTC());
445 
446         // Check Header Block;
447         Assertions.assertEquals(2.0, acm.getHeader().getFormatVersion(), 1.0e-10);
448         Assertions.assertEquals(2, acm.getHeader().getComments().size());
449         Assertions.assertEquals("This is an arbitrary test file with probably inconsistent data",
450                                 acm.getHeader().getComments().get(0));
451         Assertions.assertEquals("its purpose is only to exercise all possible entries in ACM files",
452                                 acm.getHeader().getComments().get(1));
453         Assertions.assertEquals("free to use under Orekit license",  acm.getHeader().getClassification());
454         Assertions.assertEquals(new AbsoluteDate(2023, 4, 8, 14, 31, 0.0, TimeScalesFactory.getUTC()),
455                                 acm.getHeader().getCreationDate());
456         Assertions.assertEquals("OREKIT", acm.getHeader().getOriginator());
457         Assertions.assertEquals("a4830b29-a805-4d31-ab6e-06b57c843323", acm.getHeader().getMessageId());
458 
459         // metadata
460         Assertions.assertEquals("comment at metadata start",    acm.getMetadata().getComments().get(0));
461         Assertions.assertEquals("Korrigan",                     acm.getMetadata().getObjectName());
462         Assertions.assertEquals("1703-999Z",                    acm.getMetadata().getInternationalDesignator());
463         Assertions.assertEquals(1703,                           acm.getMetadata().getLaunchYear());
464         Assertions.assertEquals(999,                            acm.getMetadata().getLaunchNumber());
465         Assertions.assertEquals("Z",                            acm.getMetadata().getLaunchPiece());
466         Assertions.assertEquals("FAERY",                        acm.getMetadata().getCatalogName());
467         Assertions.assertEquals("Korrik-17",                    acm.getMetadata().getObjectDesignator());
468         Assertions.assertEquals("Melusine",                     acm.getMetadata().getOriginatorPOC());
469         Assertions.assertEquals("Odonatoptera-lead",            acm.getMetadata().getOriginatorPosition());
470         Assertions.assertEquals("+9911223344",                  acm.getMetadata().getOriginatorPhone());
471         Assertions.assertEquals("melusine@avalon.surreal",      acm.getMetadata().getOriginatorEmail());
472         Assertions.assertEquals("-1 dolmen avenue, Stonehenge", acm.getMetadata().getOriginatorAddress());
473         Assertions.assertEquals("odm-7c32f8a9c126432f",         acm.getMetadata().getOdmMessageLink());
474         Assertions.assertEquals(CenterName.MOON.name(),         acm.getMetadata().getCenter().getName());
475         Assertions.assertEquals("UTC",                          acm.getMetadata().getTimeSystem().name());
476         Assertions.assertEquals(t0,                             acm.getMetadata().getEpochT0()); 
477         Assertions.assertEquals(17, acm.getMetadata().getAcmDataElements().size());
478         Assertions.assertEquals(AcmElements.ATT,  acm.getMetadata().getAcmDataElements().get( 0));
479         Assertions.assertEquals(AcmElements.ATT,  acm.getMetadata().getAcmDataElements().get( 1));
480         Assertions.assertEquals(AcmElements.ATT,  acm.getMetadata().getAcmDataElements().get( 2));
481         Assertions.assertEquals(AcmElements.ATT,  acm.getMetadata().getAcmDataElements().get( 3));
482         Assertions.assertEquals(AcmElements.ATT,  acm.getMetadata().getAcmDataElements().get( 4));
483         Assertions.assertEquals(AcmElements.PHYS, acm.getMetadata().getAcmDataElements().get( 5));
484         Assertions.assertEquals(AcmElements.COV,  acm.getMetadata().getAcmDataElements().get( 6));
485         Assertions.assertEquals(AcmElements.COV,  acm.getMetadata().getAcmDataElements().get( 7));
486         Assertions.assertEquals(AcmElements.COV,  acm.getMetadata().getAcmDataElements().get( 8));
487         Assertions.assertEquals(AcmElements.COV,  acm.getMetadata().getAcmDataElements().get( 9));
488         Assertions.assertEquals(AcmElements.COV,  acm.getMetadata().getAcmDataElements().get(10));
489         Assertions.assertEquals(AcmElements.COV,  acm.getMetadata().getAcmDataElements().get(11));
490         Assertions.assertEquals(AcmElements.MAN,  acm.getMetadata().getAcmDataElements().get(12));
491         Assertions.assertEquals(AcmElements.MAN,  acm.getMetadata().getAcmDataElements().get(13));
492         Assertions.assertEquals(AcmElements.MAN,  acm.getMetadata().getAcmDataElements().get(14));
493         Assertions.assertEquals(AcmElements.AD,   acm.getMetadata().getAcmDataElements().get(15));
494         Assertions.assertEquals(AcmElements.USER, acm.getMetadata().getAcmDataElements().get(16));
495         Assertions.assertEquals(18600.0,          acm.getMetadata().getStartTime().durationFrom(t0), 1.0e-12);
496         Assertions.assertEquals(19000.0,          acm.getMetadata().getStopTime().durationFrom(t0), 1.0e-12);
497         Assertions.assertEquals(36,               acm.getMetadata().getTaimutcT0());
498         Assertions.assertEquals(0.0,
499                                 acm.getMetadata().getNextLeapEpoch().durationFrom(new AbsoluteDate("2017-01-01", TimeScalesFactory.getUTC())),
500                                 1.0e-12);
501         Assertions.assertEquals(37,               acm.getMetadata().getNextLeapTaimutc());
502 
503         Assertions.assertEquals(5, acm.getData().getAttitudeBlocks().size());
504 
505         // first attitude block
506         AttitudeStateHistory att1 = acm.getData().getAttitudeBlocks().get(0);
507         Assertions.assertEquals("first attitude block",          att1.getMetadata().getComments().get(0));
508         Assertions.assertEquals("ATT_1",                         att1.getMetadata().getAttID());
509         Assertions.assertEquals("ATT_0",                         att1.getMetadata().getAttPrevID());
510         Assertions.assertEquals("SIMULATED",                     att1.getMetadata().getAttBasis());
511         Assertions.assertEquals("rnd-25",                        att1.getMetadata().getAttBasisID());
512         Assertions.assertEquals("EME2000",                       att1.getMetadata().getEndpoints().getFrameA().getName());
513         Assertions.assertEquals(BaseEquipment.GYRO,              att1.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
514         Assertions.assertEquals("3",                             att1.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
515         Assertions.assertEquals(4,                               att1.getMetadata().getNbStates());
516         Assertions.assertEquals(AttitudeElementsType.QUATERNION, att1.getMetadata().getAttitudeType());
517         Assertions.assertEquals(RateElementsType.NONE,           att1.getMetadata().getRateType());
518         Assertions.assertEquals(2,                               att1.getAttitudeStates().size());
519         Assertions.assertEquals(0.0,       att1.getAttitudeStates().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
520         Assertions.assertEquals(4,         att1.getAttitudeStates().get(0).getElements().length);
521         Assertions.assertEquals( 0.73566,  att1.getAttitudeStates().get(0).getElements()[0], 1.0e-15);
522         Assertions.assertEquals(-0.50547,  att1.getAttitudeStates().get(0).getElements()[1], 1.0e-15);
523         Assertions.assertEquals( 0.41309,  att1.getAttitudeStates().get(0).getElements()[2], 1.0e-15);
524         Assertions.assertEquals( 0.180707, att1.getAttitudeStates().get(0).getElements()[3], 1.0e-15);
525         Assertions.assertEquals(0.25,      att1.getAttitudeStates().get(1).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
526         Assertions.assertEquals(4,         att1.getAttitudeStates().get(1).getElements().length);
527         Assertions.assertEquals( 0.73529,  att1.getAttitudeStates().get(1).getElements()[0], 1.0e-15);
528         Assertions.assertEquals(-0.50531,  att1.getAttitudeStates().get(1).getElements()[1], 1.0e-15);
529         Assertions.assertEquals( 0.41375,  att1.getAttitudeStates().get(1).getElements()[2], 1.0e-15);
530         Assertions.assertEquals( 0.181158, att1.getAttitudeStates().get(1).getElements()[3], 1.0e-15);
531         Assertions.assertEquals(0.0, att1.getAttitudeStates().get(0).toAngular(RotationOrder.XYZ).getRotationRate().getNorm(), 1.0e-10);
532 
533         // second attitude block
534         AttitudeStateHistory att2 = acm.getData().getAttitudeBlocks().get(1);
535         Assertions.assertEquals("second attitude block",           att2.getMetadata().getComments().get(0));
536         Assertions.assertEquals("ATT_2",                           att2.getMetadata().getAttID());
537         Assertions.assertEquals("ATT_1",                           att2.getMetadata().getAttPrevID());
538         Assertions.assertEquals("SIMULATED",                       att2.getMetadata().getAttBasis());
539         Assertions.assertEquals("rnd-25",                          att2.getMetadata().getAttBasisID());
540         Assertions.assertEquals("EME2000",                         att2.getMetadata().getEndpoints().getFrameA().getName());
541         Assertions.assertEquals(BaseEquipment.ACC,                 att2.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
542         Assertions.assertEquals("0",                               att2.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
543         Assertions.assertEquals(6,                                 att2.getMetadata().getNbStates());
544         Assertions.assertEquals(AttitudeElementsType.EULER_ANGLES, att2.getMetadata().getAttitudeType());
545         Assertions.assertEquals(RateElementsType.ANGVEL,           att2.getMetadata().getRateType());
546         Assertions.assertEquals(2,                                 att2.getAttitudeStates().size());
547         Assertions.assertEquals(0.50, att2.getAttitudeStates().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
548         Assertions.assertEquals(6,    att2.getAttitudeStates().get(0).getElements().length);
549         Assertions.assertEquals( 1.0, FastMath.toDegrees(att2.getAttitudeStates().get(0).getElements()[0]), 1.0e-15);
550         Assertions.assertEquals( 1.2, FastMath.toDegrees(att2.getAttitudeStates().get(0).getElements()[1]), 1.0e-15);
551         Assertions.assertEquals( 1.3, FastMath.toDegrees(att2.getAttitudeStates().get(0).getElements()[2]), 1.0e-15);
552         Assertions.assertEquals(-0.4, FastMath.toDegrees(att2.getAttitudeStates().get(0).getElements()[3]), 1.0e-15);
553         Assertions.assertEquals(-0.5, FastMath.toDegrees(att2.getAttitudeStates().get(0).getElements()[4]), 1.0e-15);
554         Assertions.assertEquals(-0.6, FastMath.toDegrees(att2.getAttitudeStates().get(0).getElements()[5]), 1.0e-15);
555         Assertions.assertEquals(0.75, att2.getAttitudeStates().get(1).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
556         Assertions.assertEquals(6,    att2.getAttitudeStates().get(1).getElements().length);
557         Assertions.assertEquals( 2.0, FastMath.toDegrees(att2.getAttitudeStates().get(1).getElements()[0]), 1.0e-15);
558         Assertions.assertEquals( 2.2, FastMath.toDegrees(att2.getAttitudeStates().get(1).getElements()[1]), 1.0e-15);
559         Assertions.assertEquals( 2.3, FastMath.toDegrees(att2.getAttitudeStates().get(1).getElements()[2]), 1.0e-15);
560         Assertions.assertEquals(-1.4, FastMath.toDegrees(att2.getAttitudeStates().get(1).getElements()[3]), 1.0e-15);
561         Assertions.assertEquals(-1.5, FastMath.toDegrees(att2.getAttitudeStates().get(1).getElements()[4]), 1.0e-15);
562         Assertions.assertEquals(-1.6, FastMath.toDegrees(att2.getAttitudeStates().get(1).getElements()[5]), 1.0e-15);
563         Assertions.assertEquals(0.0153152, att2.getAttitudeStates().get(0).toAngular(RotationOrder.XYZ).getRotationRate().getNorm(), 1.0e-7);
564 
565         // third attitude block
566         AttitudeStateHistory att3 = acm.getData().getAttitudeBlocks().get(2);
567         Assertions.assertEquals("third attitude block",           att3.getMetadata().getComments().get(0));
568         Assertions.assertEquals("ATT_3",                           att3.getMetadata().getAttID());
569         Assertions.assertEquals("ATT_2",                           att3.getMetadata().getAttPrevID());
570         Assertions.assertEquals("SIMULATED",                       att3.getMetadata().getAttBasis());
571         Assertions.assertEquals("rnd-25",                          att3.getMetadata().getAttBasisID());
572         Assertions.assertEquals("EME2000",                         att3.getMetadata().getEndpoints().getFrameA().getName());
573         Assertions.assertEquals(BaseEquipment.AST,                 att3.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
574         Assertions.assertEquals("1",                               att3.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
575         Assertions.assertEquals(8,                                 att3.getMetadata().getNbStates());
576         Assertions.assertEquals(AttitudeElementsType.QUATERNION,   att3.getMetadata().getAttitudeType());
577         Assertions.assertEquals(RateElementsType.Q_DOT,            att3.getMetadata().getRateType());
578         Assertions.assertEquals(2,                                 att3.getAttitudeStates().size());
579         Assertions.assertEquals(1.0,         att3.getAttitudeStates().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
580         Assertions.assertEquals(8,           att3.getAttitudeStates().get(0).getElements().length);
581         Assertions.assertEquals( 0.73566,    att3.getAttitudeStates().get(0).getElements()[0], 1.0e-15);
582         Assertions.assertEquals(-0.50547,    att3.getAttitudeStates().get(0).getElements()[1], 1.0e-15);
583         Assertions.assertEquals( 0.41309,    att3.getAttitudeStates().get(0).getElements()[2], 1.0e-15);
584         Assertions.assertEquals( 0.180707,   att3.getAttitudeStates().get(0).getElements()[3], 1.0e-15);
585         Assertions.assertEquals( 0.0073566,  att3.getAttitudeStates().get(0).getElements()[4], 1.0e-15);
586         Assertions.assertEquals(-0.0050547,  att3.getAttitudeStates().get(0).getElements()[5], 1.0e-15);
587         Assertions.assertEquals( 0.0041309,  att3.getAttitudeStates().get(0).getElements()[6], 1.0e-15);
588         Assertions.assertEquals( 0.00180707, att3.getAttitudeStates().get(0).getElements()[7], 1.0e-15);
589         Assertions.assertEquals(1.25,        att3.getAttitudeStates().get(1).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
590         Assertions.assertEquals(8,           att3.getAttitudeStates().get(1).getElements().length);
591         Assertions.assertEquals( 0.73529,    att3.getAttitudeStates().get(1).getElements()[0], 1.0e-15);
592         Assertions.assertEquals(-0.50531,    att3.getAttitudeStates().get(1).getElements()[1], 1.0e-15);
593         Assertions.assertEquals( 0.41375,    att3.getAttitudeStates().get(1).getElements()[2], 1.0e-15);
594         Assertions.assertEquals( 0.181158,   att3.getAttitudeStates().get(1).getElements()[3], 1.0e-15);
595         Assertions.assertEquals( 0.0073529,  att3.getAttitudeStates().get(1).getElements()[4], 1.0e-15);
596         Assertions.assertEquals(-0.0050531,  att3.getAttitudeStates().get(1).getElements()[5], 1.0e-15);
597         Assertions.assertEquals( 0.0041375,  att3.getAttitudeStates().get(1).getElements()[6], 1.0e-15);
598         Assertions.assertEquals( 0.00181158, att3.getAttitudeStates().get(1).getElements()[7], 1.0e-15);
599         Assertions.assertEquals(0.0, att3.getAttitudeStates().get(0).toAngular(RotationOrder.XYZ).getRotationRate().getNorm(), 1.0e-10);
600 
601         // fourth attitude block
602         AttitudeStateHistory att4 = acm.getData().getAttitudeBlocks().get(3);
603         Assertions.assertEquals("fourth attitude block",           att4.getMetadata().getComments().get(0));
604         Assertions.assertEquals("ATT_4",                           att4.getMetadata().getAttID());
605         Assertions.assertEquals("ATT_3",                           att4.getMetadata().getAttPrevID());
606         Assertions.assertEquals("SIMULATED",                       att4.getMetadata().getAttBasis());
607         Assertions.assertEquals("rnd-25",                          att4.getMetadata().getAttBasisID());
608         Assertions.assertEquals("EME2000",                         att4.getMetadata().getEndpoints().getFrameA().getName());
609         Assertions.assertEquals(BaseEquipment.CSS,                 att4.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
610         Assertions.assertEquals("7",                               att4.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
611         Assertions.assertEquals(13,                                att4.getMetadata().getNbStates());
612         Assertions.assertEquals(AttitudeElementsType.DCM,          att4.getMetadata().getAttitudeType());
613         Assertions.assertEquals(RateElementsType.Q_DOT,            att4.getMetadata().getRateType());
614         Assertions.assertEquals(2,                                 att4.getAttitudeStates().size());
615         Assertions.assertEquals(1.50, att4.getAttitudeStates().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
616         Assertions.assertEquals(13,   att4.getAttitudeStates().get(0).getElements().length);
617         Assertions.assertEquals(1.0,  att4.getAttitudeStates().get(0).getElements()[ 0], 1.0e-15);
618         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(0).getElements()[ 1], 1.0e-15);
619         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(0).getElements()[ 2], 1.0e-15);
620         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(0).getElements()[ 3], 1.0e-15);
621         Assertions.assertEquals(1.0,  att4.getAttitudeStates().get(0).getElements()[ 4], 1.0e-15);
622         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(0).getElements()[ 5], 1.0e-15);
623         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(0).getElements()[ 6], 1.0e-15);
624         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(0).getElements()[ 7], 1.0e-15);
625         Assertions.assertEquals(1.0,  att4.getAttitudeStates().get(0).getElements()[ 8], 1.0e-15);
626         Assertions.assertEquals(0.01, att4.getAttitudeStates().get(0).getElements()[ 9], 1.0e-15);
627         Assertions.assertEquals(0.02, att4.getAttitudeStates().get(0).getElements()[10], 1.0e-15);
628         Assertions.assertEquals(0.03, att4.getAttitudeStates().get(0).getElements()[11], 1.0e-15);
629         Assertions.assertEquals(0.04, att4.getAttitudeStates().get(0).getElements()[12], 1.0e-15);
630         Assertions.assertEquals(1.75, att4.getAttitudeStates().get(1).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
631         Assertions.assertEquals(13,   att4.getAttitudeStates().get(1).getElements().length);
632         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(1).getElements()[ 0], 1.0e-15);
633         Assertions.assertEquals(1.0,  att4.getAttitudeStates().get(1).getElements()[ 1], 1.0e-15);
634         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(1).getElements()[ 2], 1.0e-15);
635         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(1).getElements()[ 3], 1.0e-15);
636         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(1).getElements()[ 4], 1.0e-15);
637         Assertions.assertEquals(1.0,  att4.getAttitudeStates().get(1).getElements()[ 5], 1.0e-15);
638         Assertions.assertEquals(1.0,  att4.getAttitudeStates().get(1).getElements()[ 6], 1.0e-15);
639         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(1).getElements()[ 7], 1.0e-15);
640         Assertions.assertEquals(0.0,  att4.getAttitudeStates().get(1).getElements()[ 8], 1.0e-15);
641         Assertions.assertEquals(0.05, att4.getAttitudeStates().get(1).getElements()[ 9], 1.0e-15);
642         Assertions.assertEquals(0.06, att4.getAttitudeStates().get(1).getElements()[10], 1.0e-15);
643         Assertions.assertEquals(0.07, att4.getAttitudeStates().get(1).getElements()[11], 1.0e-15);
644         Assertions.assertEquals(0.08, att4.getAttitudeStates().get(1).getElements()[12], 1.0e-15);
645         Assertions.assertEquals(0.0748331, att4.getAttitudeStates().get(0).toAngular(RotationOrder.XYZ).getRotationRate().getNorm(), 1.0e-7);
646 
647         // fifth attitude block
648         AttitudeStateHistory att5 = acm.getData().getAttitudeBlocks().get(4);
649         Assertions.assertEquals("fifth attitude block",           att5.getMetadata().getComments().get(0));
650         Assertions.assertEquals("ATT_5",                           att5.getMetadata().getAttID());
651         Assertions.assertEquals("ATT_4",                           att5.getMetadata().getAttPrevID());
652         Assertions.assertEquals("SIMULATED",                       att5.getMetadata().getAttBasis());
653         Assertions.assertEquals("rnd-25",                          att5.getMetadata().getAttBasisID());
654         Assertions.assertEquals("EME2000",                         att5.getMetadata().getEndpoints().getFrameA().getName());
655         Assertions.assertEquals(BaseEquipment.ESA,                 att5.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
656         Assertions.assertEquals("9",                               att5.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
657         Assertions.assertEquals(6,                                 att5.getMetadata().getNbStates());
658         Assertions.assertEquals(AttitudeElementsType.EULER_ANGLES, att5.getMetadata().getAttitudeType());
659         Assertions.assertEquals(RateElementsType.GYRO_BIAS,        att5.getMetadata().getRateType());
660         Assertions.assertEquals(2,                                 att5.getAttitudeStates().size());
661         Assertions.assertEquals(2.00, att5.getAttitudeStates().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
662         Assertions.assertEquals(6,    att5.getAttitudeStates().get(0).getElements().length);
663         Assertions.assertEquals( 1.0, FastMath.toDegrees(att5.getAttitudeStates().get(0).getElements()[0]), 1.0e-15);
664         Assertions.assertEquals( 1.2, FastMath.toDegrees(att5.getAttitudeStates().get(0).getElements()[1]), 1.0e-15);
665         Assertions.assertEquals( 1.3, FastMath.toDegrees(att5.getAttitudeStates().get(0).getElements()[2]), 1.0e-15);
666         Assertions.assertEquals(-0.4, FastMath.toDegrees(att5.getAttitudeStates().get(0).getElements()[3]), 1.0e-15);
667         Assertions.assertEquals(-0.5, FastMath.toDegrees(att5.getAttitudeStates().get(0).getElements()[4]), 1.0e-15);
668         Assertions.assertEquals(-0.6, FastMath.toDegrees(att5.getAttitudeStates().get(0).getElements()[5]), 1.0e-15);
669         Assertions.assertEquals(2.25, att5.getAttitudeStates().get(1).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
670         Assertions.assertEquals(6,    att5.getAttitudeStates().get(1).getElements().length);
671         Assertions.assertEquals( 2.0, FastMath.toDegrees(att5.getAttitudeStates().get(1).getElements()[0]), 1.0e-15);
672         Assertions.assertEquals( 2.2, FastMath.toDegrees(att5.getAttitudeStates().get(1).getElements()[1]), 1.0e-15);
673         Assertions.assertEquals( 2.3, FastMath.toDegrees(att5.getAttitudeStates().get(1).getElements()[2]), 1.0e-15);
674         Assertions.assertEquals(-1.4, FastMath.toDegrees(att5.getAttitudeStates().get(1).getElements()[3]), 1.0e-15);
675         Assertions.assertEquals(-1.5, FastMath.toDegrees(att5.getAttitudeStates().get(1).getElements()[4]), 1.0e-15);
676         Assertions.assertEquals(-1.6, FastMath.toDegrees(att5.getAttitudeStates().get(1).getElements()[5]), 1.0e-15);
677         try {
678             att5.getAttitudeStates().get(0).toAngular(RotationOrder.XYZ);
679             Assertions.fail("an exception should have been thrown");
680         } catch (OrekitException oe) {
681             Assertions.assertEquals(OrekitMessages.CCSDS_UNSUPPORTED_ELEMENT_SET_TYPE, oe.getSpecifier());
682         }
683 
684         // physical properties
685         AttitudePhysicalProperties phys = acm.getData().getPhysicBlock();
686         Assertions.assertEquals("Spacecraft Physical Parameters", phys.getComments().get(0));
687         Assertions.assertEquals(1.8,    phys.getDragCoefficient(), 1.0e-15);
688         Assertions.assertEquals(1916.0, phys.getWetMass(), 1.0e-15);
689         Assertions.assertEquals(800.0,  phys.getDryMass(), 1.0e-15);
690         Assertions.assertEquals(1916.0, phys.getWetMass(), 1.0e-15);
691         Assertions.assertEquals(BaseEquipment.SC_BODY, phys.getCenterOfPressureReferenceFrame().asSpacecraftBodyFrame().getBaseEquipment());
692         Assertions.assertEquals("1", phys.getCenterOfPressureReferenceFrame().asSpacecraftBodyFrame().getLabel());
693         Assertions.assertEquals( 0.04,  phys.getCenterOfPressure().getX(),      1.0e-15);
694         Assertions.assertEquals(-0.78,  phys.getCenterOfPressure().getY(),      1.0e-15);
695         Assertions.assertEquals(-0.023, phys.getCenterOfPressure().getZ(),      1.0e-15);
696         Assertions.assertEquals(BaseEquipment.SC_BODY, phys.getInertiaReferenceFrame().asSpacecraftBodyFrame().getBaseEquipment());
697         Assertions.assertEquals("2", phys.getInertiaReferenceFrame().asSpacecraftBodyFrame().getLabel());
698         Assertions.assertEquals( 752.0, phys.getInertiaMatrix().getEntry(0, 0), 1.0e-15);
699         Assertions.assertEquals(1305.0, phys.getInertiaMatrix().getEntry(1, 1), 1.0e-15);
700         Assertions.assertEquals(1490.0, phys.getInertiaMatrix().getEntry(2, 2), 1.0e-15);
701         Assertions.assertEquals(  81.1, phys.getInertiaMatrix().getEntry(0, 1), 1.0e-15);
702         Assertions.assertEquals(  81.1, phys.getInertiaMatrix().getEntry(1, 0), 1.0e-15);
703         Assertions.assertEquals( -25.7, phys.getInertiaMatrix().getEntry(0, 2), 1.0e-15);
704         Assertions.assertEquals( -25.7, phys.getInertiaMatrix().getEntry(2, 0), 1.0e-15);
705         Assertions.assertEquals(  74.1, phys.getInertiaMatrix().getEntry(1, 2), 1.0e-15);
706         Assertions.assertEquals(  74.1, phys.getInertiaMatrix().getEntry(2, 1), 1.0e-15);
707 
708         Assertions.assertEquals(6, acm.getData().getCovarianceBlocks().size());
709 
710         // first covariance block
711         AttitudeCovarianceHistory cov1 = acm.getData().getCovarianceBlocks().get(0);
712         Assertions.assertEquals("first covariance block", cov1.getMetadata().getComments().get(0));
713         Assertions.assertEquals("COV_1", cov1.getMetadata().getCovID());
714         Assertions.assertEquals("COV_0", cov1.getMetadata().getCovPrevID());
715         Assertions.assertEquals("DETERMINED_OBC", cov1.getMetadata().getCovBasis());
716         Assertions.assertEquals("blip-12", cov1.getMetadata().getCovBasisID());
717         Assertions.assertEquals(BaseEquipment.SC_BODY, cov1.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getBaseEquipment());
718         Assertions.assertEquals("1", cov1.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getLabel());
719         Assertions.assertEquals(AttitudeCovarianceType.ANGLE_GYROBIAS, cov1.getMetadata().getCovType());
720         Assertions.assertEquals(2, cov1.getCovariances().size());
721         Assertions.assertEquals(0.0, cov1.getCovariances().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
722         DiagonalMatrix m1 = cov1.getCovariances().get(0).getMatrix();
723         Assertions.assertEquals(6,   m1.getRowDimension());
724         Assertions.assertEquals( 6.74E-11, FastMath.toDegrees(FastMath.toDegrees(m1.getEntry(0, 0))), 1.0e-22);
725         Assertions.assertEquals( 8.10E-11, FastMath.toDegrees(FastMath.toDegrees(m1.getEntry(1, 1))), 1.0e-22);
726         Assertions.assertEquals( 9.22E-11, FastMath.toDegrees(FastMath.toDegrees(m1.getEntry(2, 2))), 1.0e-22);
727         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m1.getEntry(3, 3))), 1.0e-22);
728         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m1.getEntry(4, 4))), 1.0e-22);
729         Assertions.assertEquals( 1.12E-15, FastMath.toDegrees(FastMath.toDegrees(m1.getEntry(5, 5))), 1.0e-22);
730 
731         // second covariance block
732         AttitudeCovarianceHistory cov2 = acm.getData().getCovarianceBlocks().get(1);
733         Assertions.assertEquals("second covariance block", cov2.getMetadata().getComments().get(0));
734         Assertions.assertEquals("COV_2", cov2.getMetadata().getCovID());
735         Assertions.assertEquals("COV_1", cov2.getMetadata().getCovPrevID());
736         Assertions.assertEquals("DETERMINED_OBC", cov2.getMetadata().getCovBasis());
737         Assertions.assertEquals("blip-12", cov2.getMetadata().getCovBasisID());
738         Assertions.assertEquals(BaseEquipment.SC_BODY, cov2.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getBaseEquipment());
739         Assertions.assertEquals("1", cov2.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getLabel());
740         Assertions.assertEquals(AttitudeCovarianceType.ANGLE, cov2.getMetadata().getCovType());
741         Assertions.assertEquals(2, cov2.getCovariances().size());
742         Assertions.assertEquals(0.0, cov2.getCovariances().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
743         DiagonalMatrix m2 = cov2.getCovariances().get(0).getMatrix();
744         Assertions.assertEquals(3,   m2.getRowDimension());
745         Assertions.assertEquals( 6.74E-11, FastMath.toDegrees(FastMath.toDegrees(m2.getEntry(0, 0))), 1.0e-22);
746         Assertions.assertEquals( 8.10E-11, FastMath.toDegrees(FastMath.toDegrees(m2.getEntry(1, 1))), 1.0e-22);
747         Assertions.assertEquals( 9.22E-11, FastMath.toDegrees(FastMath.toDegrees(m2.getEntry(2, 2))), 1.0e-22);
748 
749         // third covariance block
750         AttitudeCovarianceHistory cov3 = acm.getData().getCovarianceBlocks().get(2);
751         Assertions.assertEquals("third covariance block", cov3.getMetadata().getComments().get(0));
752         Assertions.assertEquals("COV_3", cov3.getMetadata().getCovID());
753         Assertions.assertEquals("COV_2", cov3.getMetadata().getCovPrevID());
754         Assertions.assertEquals("DETERMINED_OBC", cov3.getMetadata().getCovBasis());
755         Assertions.assertEquals("blip-12", cov3.getMetadata().getCovBasisID());
756         Assertions.assertEquals(BaseEquipment.SC_BODY, cov3.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getBaseEquipment());
757         Assertions.assertEquals("1", cov3.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getLabel());
758         Assertions.assertEquals(AttitudeCovarianceType.ANGLE_ANGVEL, cov3.getMetadata().getCovType());
759         Assertions.assertEquals(2, cov3.getCovariances().size());
760         Assertions.assertEquals(0.0, cov3.getCovariances().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
761         DiagonalMatrix m3 = cov3.getCovariances().get(0).getMatrix();
762         Assertions.assertEquals(6,   m3.getRowDimension());
763         Assertions.assertEquals( 6.74E-11, FastMath.toDegrees(FastMath.toDegrees(m3.getEntry(0, 0))), 1.0e-22);
764         Assertions.assertEquals( 8.10E-11, FastMath.toDegrees(FastMath.toDegrees(m3.getEntry(1, 1))), 1.0e-22);
765         Assertions.assertEquals( 9.22E-11, FastMath.toDegrees(FastMath.toDegrees(m3.getEntry(2, 2))), 1.0e-22);
766         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m3.getEntry(3, 3))), 1.0e-22);
767         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m3.getEntry(4, 4))), 1.0e-22);
768         Assertions.assertEquals( 1.12E-15, FastMath.toDegrees(FastMath.toDegrees(m3.getEntry(5, 5))), 1.0e-22);
769 
770         // fourth covariance block
771         AttitudeCovarianceHistory cov4 = acm.getData().getCovarianceBlocks().get(3);
772         Assertions.assertEquals("fourth covariance block", cov4.getMetadata().getComments().get(0));
773         Assertions.assertEquals("COV_4", cov4.getMetadata().getCovID());
774         Assertions.assertEquals("COV_3", cov4.getMetadata().getCovPrevID());
775         Assertions.assertEquals("DETERMINED_OBC", cov4.getMetadata().getCovBasis());
776         Assertions.assertEquals("blip-12", cov4.getMetadata().getCovBasisID());
777         Assertions.assertEquals(BaseEquipment.SC_BODY, cov4.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getBaseEquipment());
778         Assertions.assertEquals("1", cov4.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getLabel());
779         Assertions.assertEquals(AttitudeCovarianceType.QUATERNION, cov4.getMetadata().getCovType());
780         Assertions.assertEquals(2, cov4.getCovariances().size());
781         Assertions.assertEquals(0.0, cov4.getCovariances().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
782         DiagonalMatrix m4 = cov4.getCovariances().get(0).getMatrix();
783         Assertions.assertEquals(4,   m4.getRowDimension());
784         Assertions.assertEquals( 6.74E-11, m4.getEntry(0, 0), 1.0e-22);
785         Assertions.assertEquals( 8.10E-11, m4.getEntry(1, 1), 1.0e-22);
786         Assertions.assertEquals( 9.22E-11, m4.getEntry(2, 2), 1.0e-22);
787         Assertions.assertEquals( 2.17E-11, m4.getEntry(3, 3), 1.0e-22);
788 
789         // fifth covariance block
790         AttitudeCovarianceHistory cov5 = acm.getData().getCovarianceBlocks().get(4);
791         Assertions.assertEquals("fifth covariance block", cov5.getMetadata().getComments().get(0));
792         Assertions.assertEquals("COV_5", cov5.getMetadata().getCovID());
793         Assertions.assertEquals("COV_4", cov5.getMetadata().getCovPrevID());
794         Assertions.assertEquals("DETERMINED_OBC", cov5.getMetadata().getCovBasis());
795         Assertions.assertEquals("blip-12", cov5.getMetadata().getCovBasisID());
796         Assertions.assertEquals(BaseEquipment.SC_BODY, cov5.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getBaseEquipment());
797         Assertions.assertEquals("1", cov5.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getLabel());
798         Assertions.assertEquals(AttitudeCovarianceType.QUATERNION_GYROBIAS, cov5.getMetadata().getCovType());
799         Assertions.assertEquals(2, cov5.getCovariances().size());
800         Assertions.assertEquals(0.0, cov5.getCovariances().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
801         DiagonalMatrix m5 = cov5.getCovariances().get(0).getMatrix();
802         Assertions.assertEquals(7,   m5.getRowDimension());
803         Assertions.assertEquals( 6.74E-11, m5.getEntry(0, 0), 1.0e-22);
804         Assertions.assertEquals( 8.10E-11, m5.getEntry(1, 1), 1.0e-22);
805         Assertions.assertEquals( 9.22E-11, m5.getEntry(2, 2), 1.0e-22);
806         Assertions.assertEquals( 2.17E-11, m5.getEntry(3, 3), 1.0e-22);
807         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m5.getEntry(4, 4))), 1.0e-22);
808         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m5.getEntry(5, 5))), 1.0e-22);
809         Assertions.assertEquals( 1.12E-15, FastMath.toDegrees(FastMath.toDegrees(m5.getEntry(6, 6))), 1.0e-22);
810 
811         // sixth covariance block
812         AttitudeCovarianceHistory cov6 = acm.getData().getCovarianceBlocks().get(5);
813         Assertions.assertEquals("sixth covariance block", cov6.getMetadata().getComments().get(0));
814         Assertions.assertEquals("COV_6", cov6.getMetadata().getCovID());
815         Assertions.assertEquals("COV_5", cov6.getMetadata().getCovPrevID());
816         Assertions.assertEquals("DETERMINED_OBC", cov6.getMetadata().getCovBasis());
817         Assertions.assertEquals("blip-12", cov6.getMetadata().getCovBasisID());
818         Assertions.assertEquals(BaseEquipment.SC_BODY, cov6.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getBaseEquipment());
819         Assertions.assertEquals("1", cov6.getMetadata().getCovReferenceFrame().asSpacecraftBodyFrame().getLabel());
820         Assertions.assertEquals(AttitudeCovarianceType.QUATERNION_ANGVEL, cov6.getMetadata().getCovType());
821         Assertions.assertEquals(2, cov6.getCovariances().size());
822         Assertions.assertEquals(0.0, cov6.getCovariances().get(0).getDate().durationFrom(acm.getMetadata().getEpochT0()), 1.0e-15);
823         DiagonalMatrix m6 = cov6.getCovariances().get(0).getMatrix();
824         Assertions.assertEquals(7,   m6.getRowDimension());
825         Assertions.assertEquals( 6.74E-11, m6.getEntry(0, 0), 1.0e-22);
826         Assertions.assertEquals( 8.10E-11, m6.getEntry(1, 1), 1.0e-22);
827         Assertions.assertEquals( 9.22E-11, m6.getEntry(2, 2), 1.0e-22);
828         Assertions.assertEquals( 2.17E-11, m6.getEntry(3, 3), 1.0e-22);
829         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m6.getEntry(4, 4))), 1.0e-22);
830         Assertions.assertEquals( 1.11E-15, FastMath.toDegrees(FastMath.toDegrees(m6.getEntry(5, 5))), 1.0e-22);
831         Assertions.assertEquals( 1.12E-15, FastMath.toDegrees(FastMath.toDegrees(m6.getEntry(6, 6))), 1.0e-22);
832 
833         Assertions.assertEquals(3, acm.getData().getManeuverBlocks().size());
834 
835         // first maneuver
836         AttitudeManeuver man1 = acm.getData().getManeuverBlocks().get(0);
837         Assertions.assertEquals("first maneuver",               man1.getComments().get(0));
838         Assertions.assertEquals("MAN_1",                        man1.getID());
839         Assertions.assertEquals("MAN_0",                        man1.getPrevID());
840         Assertions.assertEquals("MOM_DESAT",                    man1.getManPurpose());
841         Assertions.assertEquals(100.0,                          man1.getBeginTime());
842         Assertions.assertTrue(Double.isNaN(man1.getEndTime()));
843         Assertions.assertEquals(450.0,                          man1.getDuration());
844         Assertions.assertEquals("ATT-THRUSTER",                 man1.getActuatorUsed());
845         Assertions.assertEquals(  1.3,                          man1.getTargetMomentum().getX(), 1.0e-10);
846         Assertions.assertEquals(-16.4,                          man1.getTargetMomentum().getY(), 1.0e-10);
847         Assertions.assertEquals(-11.35,                         man1.getTargetMomentum().getZ(), 1.0e-10);
848         Assertions.assertNull(man1.getTargetAttitude());
849         Assertions.assertTrue(Double.isNaN(man1.getTargetSpinRate()));
850 
851         // second maneuver
852         AttitudeManeuver man2 = acm.getData().getManeuverBlocks().get(1);
853         Assertions.assertEquals("second maneuver",              man2.getComments().get(0));
854         Assertions.assertEquals("MAN_2",                        man2.getID());
855         Assertions.assertEquals("MAN_1",                        man2.getPrevID());
856         Assertions.assertEquals("ATT_ADJUST",                   man2.getManPurpose());
857         Assertions.assertEquals(500.0,                          man2.getBeginTime());
858         Assertions.assertEquals(600.0,                          man2.getEndTime());
859         Assertions.assertTrue(Double.isNaN(man2.getDuration()));
860         Assertions.assertEquals("MAGNETOTORQUER",               man2.getActuatorUsed());
861         Assertions.assertNull(man2.getTargetMomentum());
862         Assertions.assertEquals(  0.0,                          man2.getTargetAttitude().getQ1(), 1.0e-10);
863         Assertions.assertEquals(  0.0,                          man2.getTargetAttitude().getQ2(), 1.0e-10);
864         Assertions.assertEquals(-0.707106781187,                man2.getTargetAttitude().getQ3(), 1.0e-10);
865         Assertions.assertEquals( 0.707106781187,                man2.getTargetAttitude().getQ0(), 1.0e-10);
866         Assertions.assertTrue(Double.isNaN(man2.getTargetSpinRate()));
867 
868         // third maneuver
869         AttitudeManeuver man3 = acm.getData().getManeuverBlocks().get(2);
870         Assertions.assertEquals("third maneuver",               man3.getComments().get(0));
871         Assertions.assertEquals("MAN_3",                        man3.getID());
872         Assertions.assertEquals("MAN_2",                        man3.getPrevID());
873         Assertions.assertEquals("SPIN_RATE_ADJUST",             man3.getManPurpose());
874         Assertions.assertEquals(700.0,                          man3.getBeginTime());
875         Assertions.assertTrue(Double.isNaN(man3.getEndTime()));
876         Assertions.assertEquals(200.0,                          man3.getDuration());
877         Assertions.assertEquals("REACTION-WHEEL",               man3.getActuatorUsed());
878         Assertions.assertNull(man3.getTargetMomentum());
879         Assertions.assertNull(man3.getTargetAttitude());
880         Assertions.assertEquals( 0.12,                          FastMath.toDegrees(man3.getTargetSpinRate()), 1.0e-10);
881 
882         // attitude determi nation
883         AttitudeDetermination ad = acm.getData().getAttitudeDeterminationBlock();
884         Assertions.assertEquals("attitude determination block",        ad.getComments().get(0));
885         Assertions.assertEquals("AD_1",                                ad.getId());
886         Assertions.assertEquals("AD_0",                                ad.getPrevId());
887         Assertions.assertEquals(AdMethodType.Q_METHOD,                 ad.getMethod());
888         Assertions.assertEquals("OBC",                                 ad.getSource());
889         Assertions.assertEquals(RotationOrder.XYZ,                     ad.getEulerRotSeq());
890         Assertions.assertEquals(7,                                     ad.getNbStates());
891         Assertions.assertEquals(AttitudeElementsType.QUATERNION,       ad.getAttitudeStates());
892         Assertions.assertEquals(AttitudeCovarianceType.ANGLE_GYROBIAS, ad.getCovarianceType());
893         Assertions.assertEquals("EME2000",                             ad.getEndpoints().getFrameA().getName());
894         Assertions.assertEquals(BaseEquipment.SC_BODY,                 ad.getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
895         Assertions.assertEquals("1",                                   ad.getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
896         Assertions.assertEquals(RateElementsType.ANGVEL,               ad.getRateStates());
897         Assertions.assertEquals(3,                                     ad.getSensorsUsed().size());
898         Assertions.assertEquals(1,                                     ad.getSensorsUsed().get(0).getSensorNumber());
899         Assertions.assertEquals("AST1",                                ad.getSensorsUsed().get(0).getSensorUsed());
900         Assertions.assertEquals( 2,                                    ad.getSensorsUsed().get(0).getNbSensorNoiseCovariance());
901         Assertions.assertEquals(0.0097, FastMath.toDegrees(ad.getSensorsUsed().get(0).getSensorNoiseCovariance()[0]), 1.0e-10);
902         Assertions.assertEquals(0.0098, FastMath.toDegrees(ad.getSensorsUsed().get(0).getSensorNoiseCovariance()[1]), 1.0e-10);
903         Assertions.assertEquals( 5.0, ad.getSensorsUsed().get(0).getSensorFrequency(), 1.0e-10);
904         Assertions.assertEquals(2,                                     ad.getSensorsUsed().get(1).getSensorNumber());
905         Assertions.assertEquals("AST2",                                ad.getSensorsUsed().get(1).getSensorUsed());
906         Assertions.assertEquals( 2,                                    ad.getSensorsUsed().get(1).getNbSensorNoiseCovariance());
907         Assertions.assertEquals(0.0079, FastMath.toDegrees(ad.getSensorsUsed().get(1).getSensorNoiseCovariance()[0]), 1.0e-10);
908         Assertions.assertEquals(0.0089, FastMath.toDegrees(ad.getSensorsUsed().get(1).getSensorNoiseCovariance()[1]), 1.0e-10);
909         Assertions.assertEquals(10.0, ad.getSensorsUsed().get(1).getSensorFrequency(), 1.0e-10);
910         Assertions.assertEquals(3,                                     ad.getSensorsUsed().get(2).getSensorNumber());
911         Assertions.assertEquals("IMU",                                 ad.getSensorsUsed().get(2).getSensorUsed());
912         Assertions.assertEquals(-1,                                    ad.getSensorsUsed().get(2).getNbSensorNoiseCovariance());
913         Assertions.assertNull(ad.getSensorsUsed().get(2).getSensorNoiseCovariance());
914         Assertions.assertTrue(Double.isNaN(ad.getSensorsUsed().get(2).getSensorFrequency()));
915 
916         Assertions.assertEquals(1, acm.getData().getUserDefinedBlock().getParameters().size());
917         Assertions.assertEquals("viscum-album", acm.getData().getUserDefinedBlock().getParameters().get("OXIDIZER"));
918 
919     }
920 
921     @Test
922     public void testWriteACM05() throws IOException {
923         final String name = "/ccsds/adm/acm/ACMExample05.txt";
924         final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
925         AcmParser parser = new ParserBuilder().buildAcmParser();
926         final Acm original = parser.parseMessage(source);
927 
928         // write the parsed file back to a characters array
929         final CharArrayWriter caw = new CharArrayWriter();
930         final Generator generator = new XmlGenerator(caw, 2, "dummy", Constants.JULIAN_DAY, true, null);
931         new WriterBuilder().buildAcmWriter().writeMessage(generator, original);
932 
933         // reparse the written file
934         final byte[]     bytes   = caw.toString().getBytes(StandardCharsets.UTF_8);
935         final DataSource source2 = new DataSource(name, () -> new ByteArrayInputStream(bytes));
936         final Acm    rebuilt = new ParserBuilder().buildAcmParser().parseMessage(source2);
937         validateAcm05(rebuilt);
938 
939     }
940 
941 }