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.Rotation;
23  import org.hipparchus.geometry.euclidean.threed.Vector3D;
24  import org.orekit.annotation.Nullable;
25  import org.orekit.errors.OrekitException;
26  import org.orekit.errors.OrekitMessages;
27  import org.orekit.files.ccsds.definitions.FrameFacade;
28  import org.orekit.files.ccsds.section.CommentsContainer;
29  
30  /** Maneuver entry.
31   * <p>
32   * Beware that the Orekit getters and setters all rely on SI units. The parsers
33   * and writers take care of converting these SI units into CCSDS mandatory units.
34   * The {@link org.orekit.utils.units.Unit Unit} class provides useful
35   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
36   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
37   * already use CCSDS units instead of the API SI units. The general-purpose
38   * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
39   * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
40   * (with an 's') also provide some predefined units. These predefined units and the
41   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
42   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
43   * what the parsers and writers use for the conversions.
44   * </p>
45   * @author Luc Maisonobe
46   * @since 12.0
47   */
48  public class AttitudeManeuver extends CommentsContainer {
49  
50      /** Maneuver identification number. */
51      @Nullable
52      private String id;
53  
54      /** Identification number of previous maneuver. */
55      @Nullable
56      private String prevID;
57  
58      /** Purpose of the maneuver. */
59      private String manPurpose;
60  
61      /** Start time of actual maneuver, relative to t₀. */
62      private double beginTime;
63  
64      /** End time of actual maneuver, relative to t₀. */
65      @Nullable
66      private Double endTime;
67  
68      /** Duration. */
69      @Nullable
70      private Double duration;
71  
72      /** Actuator used. */
73      @Nullable
74      private String actuatorUsed;
75  
76      /** Target momentum (if purpose is momentum desaturation). */
77      @Nullable
78      private Vector3D targetMomentum;
79  
80      /** Reference frame for {@link #targetMomentum}. */
81      @Nullable
82      private FrameFacade targetMomFrame;
83  
84      /** Target attitude (if purpose is attitude adjustment). */
85      @Nullable
86      private Rotation targetAttitude;
87  
88      /** Target spin rate (if purpose is spin rate adjustment). */
89      @Nullable
90      private Double targetSpinRate;
91  
92      /** Build an uninitialized maneuver.
93       */
94      public AttitudeManeuver() {
95      }
96  
97      /** {@inheritDoc} */
98      @Override
99      public void validate(final double version) {
100         checkNotNull(manPurpose, AttitudeManeuverKey.MAN_PURPOSE.name());
101         checkNotNaN(beginTime,   AttitudeManeuverKey.MAN_BEGIN_TIME.name());
102         if (endTime != null && duration != null) {
103             throw new OrekitException(OrekitMessages.CCSDS_INCOMPATIBLE_KEYS_BOTH_USED,
104                                       AttitudeManeuverKey.MAN_END_TIME,
105                                       AttitudeManeuverKey.MAN_DURATION);
106         }
107         if (targetMomFrame != null) {
108             checkNotNull(targetMomentum, AttitudeManeuverKey.TARGET_MOMENTUM.name());
109         }
110     }
111 
112     /** Get maneuver identification number.
113      * @return maneuver identification number
114      */
115     public Optional<String> getID() {
116         return Optional.ofNullable(id);
117     }
118 
119     /** Set maneuver identification number.
120      * @param manId maneuver identification number
121      */
122     public void setID(final String manId) {
123         refuseFurtherComments();
124         this.id = manId;
125     }
126 
127     /** Get identification number of previous maneuver.
128      * @return identification number of previous maneuver
129      */
130     public Optional<String> getPrevID() {
131         return Optional.ofNullable(prevID);
132     }
133 
134     /** Set identification number of previous maneuver.
135      * @param prevID identification number of previous maneuver
136      */
137     public void setPrevID(final String prevID) {
138         refuseFurtherComments();
139         this.prevID = prevID;
140     }
141 
142     /** Get purpose of maneuver.
143      * @return purpose of maneuver
144      */
145     public String getManPurpose() {
146         return manPurpose;
147     }
148 
149     /** Set purpose of maneuver.
150      * @param manPurpose purpose of maneuver
151      */
152     public void setManPurpose(final String manPurpose) {
153         refuseFurtherComments();
154         this.manPurpose = manPurpose;
155     }
156 
157     /** Get start time of actual maneuver, relative to t₀.
158      * @return start time of actual maneuver, relative to t₀
159      */
160     public double getBeginTime() {
161         return beginTime;
162     }
163 
164     /** Set start time of actual maneuver, relative to t₀.
165      * @param beginTime start time of actual maneuver, relative to t₀
166      */
167     public void setBeginTime(final double beginTime) {
168         this.beginTime = beginTime;
169     }
170 
171     /** Get end time of actual maneuver, relative to t₀.
172      * @return end time of actual maneuver, relative to t₀
173      */
174     public Optional<Double> getEndTime() {
175         return Optional.ofNullable(endTime);
176     }
177 
178     /** Set end time of actual maneuver, relative to t₀.
179      * @param endTime end time of actual maneuver, relative to t₀
180      */
181     public void setEndTime(final double endTime) {
182         this.endTime = endTime;
183     }
184 
185     /** Get duration.
186      * @return duration
187      */
188     public Optional<Double> getDuration() {
189         return Optional.ofNullable(duration);
190     }
191 
192     /** Set duration.
193      * @param duration duration
194      */
195     public void setDuration(final double duration) {
196         this.duration = duration;
197     }
198 
199     /** Get the actuator used.
200      * @return actuator used
201      */
202     public Optional<String> getActuatorUsed() {
203         return Optional.ofNullable(actuatorUsed);
204     }
205 
206     /** Set actuator used.
207      * @param actuatorUsed actuator used
208      */
209     public void setActuatorUsed(final String actuatorUsed) {
210         this.actuatorUsed = actuatorUsed;
211     }
212 
213     /** Get target momentum (if purpose is momentum desaturation).
214      * @return target momentum
215      */
216     public Optional<Vector3D> getTargetMomentum() {
217         return Optional.ofNullable(targetMomentum);
218     }
219 
220     /** Set target momentum (if purpose is momentum desaturation).
221      * @param targetMomentum target momentum
222      */
223     public void setTargetMomentum(final Vector3D targetMomentum) {
224         this.targetMomentum = targetMomentum;
225     }
226 
227     /** Get reference frame for {@link #getTargetMomentum()}.
228      * @return reference frame for {@link #getTargetMomentum()}
229      */
230     public Optional<FrameFacade> getTargetMomFrame() {
231         return Optional.ofNullable(targetMomFrame);
232     }
233 
234     /** Set reference frame for {@link #getTargetMomentum()}.
235      * @param targetMomFrame reference frame for {@link #getTargetMomentum()}
236      */
237     public void setTargetMomFrame(final FrameFacade targetMomFrame) {
238         this.targetMomFrame = targetMomFrame;
239     }
240 
241     /** Get target attitude (if purpose is attitude adjustment).
242      * @return target attitude
243      */
244     public Optional<Rotation> getTargetAttitude() {
245         return Optional.ofNullable(targetAttitude);
246     }
247 
248     /** Set target attitude (if purpose is attitude adjustment).
249      * @param targetAttitude target attitude
250      */
251     public void setTargetAttitude(final Rotation targetAttitude) {
252         this.targetAttitude = targetAttitude;
253     }
254 
255     /** Get target spin rate (if purpose is spin rate adjustment).
256      * @return target spin rate
257      */
258     public Optional<Double> getTargetSpinRate() {
259         return Optional.ofNullable(targetSpinRate);
260     }
261 
262     /** Set target spin rate (if purpose is spin rate adjustment).
263      * @param targetSpinRate target spin rate
264      */
265     public void setTargetSpinRate(final double targetSpinRate) {
266         this.targetSpinRate = targetSpinRate;
267     }
268 
269 }