1   /* Copyright 2022-2025 Luc Maisonobe
2    * Licensed to CS GROUP (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  
18  package org.orekit.files.ccsds.ndm.adm.acm;
19  
20  import java.io.IOException;
21  
22  import org.orekit.files.ccsds.definitions.Units;
23  import org.orekit.files.ccsds.section.AbstractWriter;
24  import org.orekit.files.ccsds.utils.generation.Generator;
25  
26  import org.orekit.utils.units.Unit;
27  
28  /** Writer for attitude determination data.
29   * @author Luc Maisonobe
30   * @since 12.0
31   */
32  class AttitudeDeterminationWriter extends AbstractWriter {
33  
34      /** Attitude determination block. */
35      private final AttitudeDetermination ad;
36  
37      /** Create a writer.
38       * @param attitudeDetermination attitude determination to write
39       */
40      AttitudeDeterminationWriter(final AttitudeDetermination attitudeDetermination) {
41          super(AcmDataSubStructureKey.ad.name(), AcmDataSubStructureKey.AD.name());
42          this.ad = attitudeDetermination;
43      }
44  
45      /** {@inheritDoc} */
46      @Override
47      protected void writeContent(final Generator generator) throws IOException {
48  
49          // attitude determination block
50          generator.writeComments(ad.getComments());
51  
52          // identifiers
53          generator.writeEntry(AttitudeDeterminationKey.AD_ID.name(),      ad.getId(),            null, false);
54          generator.writeEntry(AttitudeDeterminationKey.AD_PREV_ID.name(), ad.getPrevId(),        null, false);
55          if (ad.getMethod() != null) {
56              generator.writeEntry(AttitudeDeterminationKey.AD_METHOD.name(), ad.getMethod().name(), null, false);
57          }
58  
59          generator.writeEntry(AttitudeDeterminationKey.ATTITUDE_SOURCE.name(), ad.getSource(), null, false);
60  
61          // parameters
62          generator.writeEntry(AttitudeDeterminationKey.EULER_ROT_SEQ.name(),             ad.getEulerRotSeq(),    false);
63          generator.writeEntry(AttitudeDeterminationKey.NUMBER_STATES.name(),             ad.getNbStates(),       false);
64          generator.writeEntry(AttitudeDeterminationKey.ATTITUDE_STATES.name(),           ad.getAttitudeStates(), true);
65          generator.writeEntry(AttitudeDeterminationKey.COV_TYPE.name(),                  ad.getCovarianceType(), false);
66          generator.writeEntry(AttitudeDeterminationKey.REF_FRAME_A.name(),               ad.getEndpoints().getFrameA().getName(), null, false);
67          generator.writeEntry(AttitudeDeterminationKey.REF_FRAME_B.name(),               ad.getEndpoints().getFrameB().getName(), null, false);
68          generator.writeEntry(AttitudeDeterminationKey.RATE_STATES.name(),               ad.getRateStates(),                  false);
69          generator.writeEntry(AttitudeDeterminationKey.SIGMA_U.name(),                   ad.getSigmaU(), Units.DEG_PER_S_3_2, false);
70          generator.writeEntry(AttitudeDeterminationKey.SIGMA_V.name(),                   ad.getSigmaV(), Units.DEG_PER_S_1_2, false);
71          generator.writeEntry(AttitudeDeterminationKey.RATE_PROCESS_NOISE_STDDEV.name(), ad.getRateProcessNoiseStdDev(), Units.DEG_PER_S_3_2, false);
72  
73          // sensors
74          for (final AttitudeDeterminationSensor sensor : ad.getSensorsUsed()) {
75              generator.enterSection(AttitudeDeterminationKey.SENSOR.name());
76              generator.writeEntry(AttitudeDeterminationSensorKey.SENSOR_NUMBER.name(), sensor.getSensorNumber(),   true);
77              generator.writeEntry(AttitudeDeterminationSensorKey.SENSOR_USED.name(), sensor.getSensorUsed(), null, true);
78              final double[] stddevDouble = sensor.getSensorNoiseCovariance();
79              if (stddevDouble != null) {
80                  generator.writeEntry(AttitudeDeterminationSensorKey.NUMBER_SENSOR_NOISE_COVARIANCE.name(), stddevDouble.length, true);
81                  final StringBuilder stddev = new StringBuilder();
82                  for (int k = 0; k < stddevDouble.length; ++k) {
83                      if (k > 0) {
84                          stddev.append(' ');
85                      }
86                      stddev.append(generator.doubleToString(Unit.DEGREE.fromSI(stddevDouble[k])));
87                  }
88                  generator.writeEntry(AttitudeDeterminationSensorKey.SENSOR_NOISE_STDDEV.name(),
89                                       stddev.toString(), Unit.DEGREE, false);
90              }
91              generator.writeEntry(AttitudeDeterminationSensorKey.SENSOR_FREQUENCY.name(), sensor.getSensorFrequency(), Unit.HERTZ, false);
92              generator.exitSection();
93          }
94  
95      }
96  
97  }