1   /* Copyright 2022-2026 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.util.Optional;
21  
22  import org.hipparchus.geometry.euclidean.threed.RotationOrder;
23  import org.orekit.annotation.Nullable;
24  import org.orekit.errors.OrekitException;
25  import org.orekit.errors.OrekitMessages;
26  import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
27  import org.orekit.files.ccsds.ndm.adm.AttitudeEndpoints;
28  import org.orekit.files.ccsds.section.CommentsContainer;
29  import org.orekit.frames.Frame;
30  
31  /** Metadata for attitude state history.
32   * <p>
33   * Beware that the Orekit getters and setters all rely on SI units. The parsers
34   * and writers take care of converting these SI units into CCSDS mandatory units.
35   * The {@link org.orekit.utils.units.Unit Unit} class provides useful
36   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
37   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
38   * already use CCSDS units instead of the API SI units. The general-purpose
39   * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
40   * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
41   * (with an 's') also provide some predefined units. These predefined units and the
42   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
43   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
44   * what the parsers and writers use for the conversions.
45   * </p>
46   * @author Luc Maisonobe
47   * @since 12.0
48   */
49  public class AttitudeStateHistoryMetadata extends CommentsContainer {
50  
51      /** Endpoints (i.e. frames A, B and their relationship). */
52      private final AttitudeEndpoints endpoints;
53  
54      /** Attitude identification number. */
55      @Nullable
56      private String attID;
57  
58      /** Identification number of previous attitude. */
59      @Nullable
60      private String attPrevID;
61  
62      /** Basis of this attitude state time history data. */
63      @Nullable
64      private String attBasis;
65  
66      /** Identification number of the attitude determination or simulation upon which this attitude is based. */
67      @Nullable
68      private String attBasisID;
69  
70      /** Rotation order for Euler angles. */
71      @Nullable
72      private RotationOrder eulerRotSeq;
73  
74      /** Number of data states included (attitude components plus rates components). */
75      private int nbStates;
76  
77      /** Attitude element set type. */
78      private AttitudeElementsType attitudeType;
79  
80      /** Attitude rate element set type. */
81      @Nullable
82      private RateElementsType rateType;
83  
84      /**
85       * Simple constructor.
86       *
87       * @param frameMapper for creating a {@link Frame}.
88       * @since 13.1.5
89       */
90      public AttitudeStateHistoryMetadata(final CcsdsFrameMapper frameMapper) {
91          endpoints = new AttitudeEndpoints(frameMapper);
92      }
93  
94      /** {@inheritDoc} */
95      @Override
96      public void validate(final double version) {
97          super.validate(version);
98          endpoints.checkExternalFrame(AttitudeStateHistoryMetadataKey.REF_FRAME_A,
99                                       AttitudeStateHistoryMetadataKey.REF_FRAME_B);
100         checkNotNull(attitudeType, AttitudeStateHistoryMetadataKey.ATT_TYPE.name());
101         final int rateSize = rateType == null ? 0 : rateType.getUnits().size();
102         if (nbStates != attitudeType.getUnits().size() + rateSize) {
103             throw new OrekitException(OrekitMessages.CCSDS_INCONSISTENT_NUMBER_OF_ATTITUDE_STATES,
104                                       attitudeType.toString(), rateType.toString(),
105                                       attitudeType.getUnits().size() + rateSize, nbStates);
106         }
107         if (attitudeType == AttitudeElementsType.EULER_ANGLES) {
108             checkNotNull(eulerRotSeq, AttitudeStateHistoryMetadataKey.EULER_ROT_SEQ.name());
109         }
110     }
111 
112     /** Get the endpoints (i.e. frames A, B and their relationship).
113      * @return endpoints
114      */
115     public AttitudeEndpoints getEndpoints() {
116         return endpoints;
117     }
118 
119     /** Get attitude identification number.
120      * @return attitude identification number
121      */
122     public Optional<String> getAttID() {
123         return Optional.ofNullable(attID);
124     }
125 
126     /** Set attitude identification number.
127      * @param attID attitude identification number
128      */
129     public void setAttID(final String attID) {
130         refuseFurtherComments();
131         this.attID = attID;
132     }
133 
134     /** Get identification number of previous attitude.
135      * @return identification number of previous attitude
136      */
137     public Optional<String> getAttPrevID() {
138         return Optional.ofNullable(attPrevID);
139     }
140 
141     /** Set identification number of previous attitude.
142      * @param attPrevID identification number of previous attitude
143      */
144     public void setAttPrevID(final String attPrevID) {
145         refuseFurtherComments();
146         this.attPrevID = attPrevID;
147     }
148 
149     /** Get basis of this attitude state time history data.
150      * @return basis of this attitude state time history data
151      */
152     public Optional<String> getAttBasis() {
153         return Optional.ofNullable(attBasis);
154     }
155 
156     /** Set basis of this attitude state time history data.
157      * @param attBasis basis of this attitude state time history data
158      */
159     public void setAttBasis(final String attBasis) {
160         refuseFurtherComments();
161         this.attBasis = attBasis;
162     }
163 
164     /** Get identification number of the orbit determination or simulation upon which this attitude is based.
165      * @return identification number of the orbit determination or simulation upon which this attitude is based
166      */
167     public Optional<String> getAttBasisID() {
168         return Optional.ofNullable(attBasisID);
169     }
170 
171     /** Set identification number of the orbit determination or simulation upon which this attitude is based.
172      * @param attBasisID identification number of the orbit determination or simulation upon which this attitude is based
173      */
174     public void setAttBasisID(final String attBasisID) {
175         refuseFurtherComments();
176         this.attBasisID = attBasisID;
177     }
178 
179     /** Get the rotation order for Euler angles.
180      * @return rotation order for Euler angles
181      */
182     public Optional<RotationOrder> getEulerRotSeq() {
183         return Optional.ofNullable(eulerRotSeq);
184     }
185 
186     /** Set the rotation order for Euler angles.
187      * @param eulerRotSeq rotation order for Euler angles
188      */
189     public void setEulerRotSeq(final RotationOrder eulerRotSeq) {
190         this.eulerRotSeq = eulerRotSeq;
191     }
192 
193     /** Get the number of data states included (attitude components plus rates components).
194      * @return number of data states included (attitude components plus rates components)
195      */
196     public int getNbStates() {
197         return nbStates;
198     }
199 
200     /** Set the number of data states included (attitude components plus rates components).
201      * @param nbStates number of data states included (attitude components plus rates components)
202      */
203     public void setNbStates(final int nbStates) {
204         this.nbStates = nbStates;
205     }
206 
207     /** Get attitude element set type.
208      * @return attitude element set type
209      */
210     public AttitudeElementsType getAttitudeType() {
211         return attitudeType;
212     }
213 
214     /** Set attitude element set type.
215      * @param attitudeType attitude element set type
216      */
217     public void setAttitudeType(final AttitudeElementsType attitudeType) {
218         refuseFurtherComments();
219         this.attitudeType = attitudeType;
220     }
221 
222     /** Get attitude rate element set type.
223      * @return attitude rate element set type
224      */
225     public Optional<RateElementsType> getRateType() {
226         return Optional.ofNullable(rateType);
227     }
228 
229     /** Set attitude rate element set type.
230      * @param rateType attitude rate element set type
231      */
232     public void setRateType(final RateElementsType rateType) {
233         refuseFurtherComments();
234         this.rateType = rateType;
235     }
236 
237 }