1   /* Copyright 2002-2025 CS GROUP
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  package org.orekit.files.ccsds.ndm.adm.apm;
18  
19  import org.orekit.errors.OrekitException;
20  import org.orekit.errors.OrekitMessages;
21  import org.orekit.files.ccsds.ndm.adm.AttitudeEndpoints;
22  import org.orekit.files.ccsds.section.CommentsContainer;
23  
24  /**
25   * Container for Attitude Parameter Message data lines.
26   * <p>
27   * Beware that the Orekit getters and setters all rely on SI units. The parsers
28   * and writers take care of converting these SI units into CCSDS mandatory units.
29   * The {@link org.orekit.utils.units.Unit Unit} class provides useful
30   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
31   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
32   * already use CCSDS units instead of the API SI units. The general-purpose
33   * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
34   * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
35   * (with an 's') also provide some predefined units. These predefined units and the
36   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
37   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
38   * what the parsers and writers use for the conversions.
39   * </p>
40   * @author Bryan Cazabonne
41   * @since 10.2
42   */
43  public class SpinStabilized extends CommentsContainer {
44  
45      /** Endpoints (i.e. frames A, B and their relationship). */
46      private final AttitudeEndpoints endpoints;
47  
48      /** Right ascension of spin axis vector (rad). */
49      private double spinAlpha;
50  
51      /** Declination of the spin axis vector (rad). */
52      private double spinDelta;
53  
54      /** Phase of the satellite about the spin axis (rad). */
55      private double spinAngle;
56  
57      /** Angular velocity of satellite around spin axis (rad/s). */
58      private double spinAngleVel;
59  
60      /** Nutation angle of spin axis (rad). */
61      private double nutation;
62  
63      /** Body nutation period of the spin axis (s). */
64      private double nutationPer;
65  
66      /** Inertial nutation phase (rad). */
67      private double nutationPhase;
68  
69      /** Right ascension of angular momentum vector (rad).
70       * @since 12.0
71       */
72      private double momentumAlpha;
73  
74      /** Declination of the angular momentum vector (rad).
75       * @since 12.0
76       */
77      private double momentumDelta;
78  
79      /** Angular velocity of spin vector around the angular momentum vector (rad/s).
80       * @since 12.0
81       */
82      private double nutationVel;
83  
84      /** Simple constructor.
85       */
86      public SpinStabilized() {
87          endpoints      = new AttitudeEndpoints();
88          spinAlpha      = Double.NaN;
89          spinDelta      = Double.NaN;
90          spinAngle      = Double.NaN;
91          spinAngleVel   = Double.NaN;
92          nutation       = Double.NaN;
93          nutationPer    = Double.NaN;
94          nutationPhase  = Double.NaN;
95          momentumAlpha  = Double.NaN;
96          momentumDelta  = Double.NaN;
97          nutationVel    = Double.NaN;
98      }
99  
100     /** {@inheritDoc} */
101     @Override
102     public void validate(final double version) {
103         super.validate(version);
104         endpoints.checkMandatoryEntriesExceptExternalFrame(version,
105                                                            SpinStabilizedKey.SPIN_FRAME_A,
106                                                            SpinStabilizedKey.SPIN_FRAME_B,
107                                                            SpinStabilizedKey.SPIN_DIR);
108         endpoints.checkExternalFrame(SpinStabilizedKey.SPIN_FRAME_A, SpinStabilizedKey.SPIN_FRAME_B);
109         checkNotNaN(spinAlpha,    SpinStabilizedKey.SPIN_ALPHA.name());
110         checkNotNaN(spinDelta,    SpinStabilizedKey.SPIN_DELTA.name());
111         checkNotNaN(spinAngle,    SpinStabilizedKey.SPIN_ANGLE.name());
112         checkNotNaN(spinAngleVel, SpinStabilizedKey.SPIN_ANGLE_VEL.name());
113         if (Double.isNaN(nutation + nutationPer + nutationPhase)) {
114             // if at least one is NaN, all must be NaN (i.e. not initialized)
115             if (!(Double.isNaN(nutation) && Double.isNaN(nutationPer) && Double.isNaN(nutationPhase))) {
116                 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, "NUTATION*");
117             }
118         }
119         if (Double.isNaN(momentumAlpha + momentumDelta + nutationVel)) {
120             // if at least one is NaN, all must be NaN (i.e. not initialized)
121             if (!(Double.isNaN(momentumAlpha) && Double.isNaN(momentumDelta) && Double.isNaN(nutationVel))) {
122                 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, "MOMENTUM*/NUTATION_VEL");
123             }
124         }
125     }
126 
127     /** Get the endpoints (i.e. frames A, B and their relationship).
128      * @return endpoints
129      */
130     public AttitudeEndpoints getEndpoints() {
131         return endpoints;
132     }
133 
134     /**
135      * Get the right ascension of spin axis vector (rad).
136      * @return the right ascension of spin axis vector
137      */
138     public double getSpinAlpha() {
139         return spinAlpha;
140     }
141 
142     /**
143      * Set the right ascension of spin axis vector (rad).
144      * @param spinAlpha value to be set
145      */
146     public void setSpinAlpha(final double spinAlpha) {
147         refuseFurtherComments();
148         this.spinAlpha = spinAlpha;
149     }
150 
151     /**
152      * Get the declination of the spin axis vector (rad).
153      * @return the declination of the spin axis vector (rad).
154      */
155     public double getSpinDelta() {
156         return spinDelta;
157     }
158 
159     /**
160      * Set the declination of the spin axis vector (rad).
161      * @param spinDelta value to be set
162      */
163     public void setSpinDelta(final double spinDelta) {
164         refuseFurtherComments();
165         this.spinDelta = spinDelta;
166     }
167 
168     /**
169      * Get the phase of the satellite about the spin axis (rad).
170      * @return the phase of the satellite about the spin axis
171      */
172     public double getSpinAngle() {
173         return spinAngle;
174     }
175 
176     /**
177      * Set the phase of the satellite about the spin axis (rad).
178      * @param spinAngle value to be set
179      */
180     public void setSpinAngle(final double spinAngle) {
181         refuseFurtherComments();
182         this.spinAngle = spinAngle;
183     }
184 
185     /**
186      * Get the angular velocity of satellite around spin axis (rad/s).
187      * @return the angular velocity of satellite around spin axis
188      */
189     public double getSpinAngleVel() {
190         return spinAngleVel;
191     }
192 
193     /**
194      * Set the angular velocity of satellite around spin axis (rad/s).
195      * @param spinAngleVel value to be set
196      */
197     public void setSpinAngleVel(final double spinAngleVel) {
198         refuseFurtherComments();
199         this.spinAngleVel = spinAngleVel;
200     }
201 
202     /**
203      * Get the nutation angle of spin axis (rad).
204      * @return the nutation angle of spin axis
205      */
206     public double getNutation() {
207         return nutation;
208     }
209 
210     /**
211      * Set the nutation angle of spin axis (rad).
212      * @param nutation the nutation angle to be set
213      */
214     public void setNutation(final double nutation) {
215         refuseFurtherComments();
216         this.nutation = nutation;
217     }
218 
219     /**
220      * Get the body nutation period of the spin axis (s).
221      * @return the body nutation period of the spin axis
222      */
223     public double getNutationPeriod() {
224         return nutationPer;
225     }
226 
227     /**
228      * Set the body nutation period of the spin axis (s).
229      * @param period the nutation period to be set
230      */
231     public void setNutationPeriod(final double period) {
232         refuseFurtherComments();
233         this.nutationPer = period;
234     }
235 
236     /**
237      * Get the inertial nutation phase (rad).
238      * @return the inertial nutation phase
239      */
240     public double getNutationPhase() {
241         return nutationPhase;
242     }
243 
244     /**
245      * Set the inertial nutation phase (rad).
246      * @param nutationPhase the nutation phase to be set
247      */
248     public void setNutationPhase(final double nutationPhase) {
249         refuseFurtherComments();
250         this.nutationPhase = nutationPhase;
251     }
252 
253     /**
254      * Get the right ascension of angular momentum vector (rad).
255      * @return the right ascension of angular momentum vector
256      * @since 12.0
257      */
258     public double getMomentumAlpha() {
259         return momentumAlpha;
260     }
261 
262     /**
263      * Set the right ascension of angular momentum vector (rad).
264      * @param momentumAlpha value to be set
265      * @since 12.0
266      */
267     public void setMomentumAlpha(final double momentumAlpha) {
268         refuseFurtherComments();
269         this.momentumAlpha = momentumAlpha;
270     }
271 
272     /**
273      * Get the declination of the angular momentum vector (rad).
274      * @return the declination of the angular momentum vector (rad).
275      * @since 12.0
276      */
277     public double getMomentumDelta() {
278         return momentumDelta;
279     }
280 
281     /**
282      * Set the declination of the angular momentum vector (rad).
283      * @param momentumDelta value to be set
284      * @since 12.0
285      */
286     public void setMomentumDelta(final double momentumDelta) {
287         refuseFurtherComments();
288         this.momentumDelta = momentumDelta;
289     }
290 
291     /**
292      * Get the angular velocity of spin vector around angular momentum vector.
293      * @return angular velocity of spin vector around angular momentum vector (rad/s)
294      * @since 12.0
295      */
296     public double getNutationVel() {
297         return nutationVel;
298     }
299 
300     /**
301      * Set the angular velocity of spin vector around angular momentum vector.
302      * @param nutationVel angular velocity of spin vector around angular momentum vector (rad/s)
303      * @since 12.0
304      */
305     public void setNutationVel(final double nutationVel) {
306         refuseFurtherComments();
307         this.nutationVel = nutationVel;
308     }
309 
310     /** Check if the logical block includes nutation.
311      * @return true if logical block includes nutation
312      * @since 12.0
313      */
314     public boolean hasNutation() {
315         return !Double.isNaN(nutation + nutationPer + nutationPhase);
316     }
317 
318     /** Check if the logical block includes momentum.
319      * @return true if logical block includes momentum
320      * @since 12.0
321      */
322     public boolean hasMomentum() {
323         return !Double.isNaN(momentumAlpha + momentumDelta + nutationVel);
324     }
325 
326 }