1   /* Copyright 2002-2026 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 java.util.Arrays;
20  import java.util.Optional;
21  
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.orekit.annotation.Nullable;
24  import org.orekit.files.ccsds.definitions.FrameFacade;
25  import org.orekit.files.ccsds.section.CommentsContainer;
26  import org.orekit.time.AbsoluteDate;
27  
28  /**
29   * Maneuver in an APM file.
30   * <p>
31   * Beware that the Orekit getters and setters all rely on SI units. The parsers
32   * and writers take care of converting these SI units into CCSDS mandatory units.
33   * The {@link org.orekit.utils.units.Unit Unit} class provides useful
34   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
35   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
36   * already use CCSDS units instead of the API SI units. The general-purpose
37   * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
38   * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
39   * (with an 's') also provide some predefined units. These predefined units and the
40   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
41   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
42   * what the parsers and writers use for the conversions.
43   * </p>
44   * @author Bryan Cazabonne
45   * @since 10.2
46   */
47  public class Maneuver extends CommentsContainer {
48  
49      /** Epoch of start of maneuver . */
50      private AbsoluteDate epochStart;
51  
52      /** Coordinate system for the torque vector. */
53      private FrameFacade frame;
54  
55      /** Duration (value is 0 for impulsive maneuver). */
56      private double duration;
57  
58      /** Torque vector (N.m). */
59      private final double[] torque;
60  
61      /** Mass change during maneuver (kg).
62       * @since 12.0
63       */
64      @Nullable
65      private Double deltaMass;
66  
67      /**
68       * Simple constructor.
69       */
70      public Maneuver() {
71          duration  = Double.NaN;
72          torque    = new double[3];
73          Arrays.fill(torque, Double.NaN);
74      }
75  
76      /** {@inheritDoc} */
77      @Override
78      public void validate(final double version) {
79          super.validate(version);
80          checkNotNull(epochStart, ManeuverKey.MAN_EPOCH_START.name());
81          checkNotNaN(duration,    ManeuverKey.MAN_DURATION.name());
82          checkNotNull(frame,      ManeuverKey.MAN_REF_FRAME.name());
83          checkNotNaN(torque[0],   ManeuverKey.MAN_TOR_1.name());
84          checkNotNaN(torque[1],   ManeuverKey.MAN_TOR_2.name());
85          checkNotNaN(torque[2],   ManeuverKey.MAN_TOR_3.name());
86      }
87  
88      /**
89       * Get epoch start.
90       * @return epoch start
91       */
92      public AbsoluteDate getEpochStart() {
93          return epochStart;
94      }
95  
96      /**
97       * Set epoch start.
98       * @param epochStart epoch start
99       */
100     public void setEpochStart(final AbsoluteDate epochStart) {
101         refuseFurtherComments();
102         this.epochStart = epochStart;
103     }
104 
105     /**
106      * Get Coordinate system for the torque vector.
107      * @return coordinate system for the torque vector
108      */
109     public FrameFacade getFrame() {
110         return frame;
111     }
112 
113     /**
114      * Set Coordinate system for the torque vector.
115      * @param frame coordinate system for the torque vector
116      */
117     public void setFrame(final FrameFacade frame) {
118         refuseFurtherComments();
119         this.frame = frame;
120     }
121 
122     /**
123      * Get duration (value is 0 for impulsive maneuver).
124      * @return duration (value is 0 for impulsive maneuver)
125      */
126     public double getDuration() {
127         return duration;
128     }
129 
130     /**
131      * Set duration (value is 0 for impulsive maneuver).
132      * @param duration duration (value is 0 for impulsive maneuver)
133      */
134     public void setDuration(final double duration) {
135         refuseFurtherComments();
136         this.duration = duration;
137     }
138 
139     /**
140      * Get the torque vector (N.m).
141      * @return torque vector
142      */
143     public Vector3D getTorque() {
144         return new Vector3D(torque);
145     }
146 
147     /**
148      * Set the torque vector (N.m).
149      * @param index vector component index (counting from 0)
150      * @param value component value
151      */
152     public void setTorque(final int index, final double value) {
153         refuseFurtherComments();
154         this.torque[index] = value;
155     }
156 
157     /**
158      * Get mass change during maneuver.
159      * @return mass change during maneuver (kg, negative)
160      * @since 12.0
161      */
162     public Optional<Double> getDeltaMass() {
163         return Optional.ofNullable(deltaMass);
164     }
165 
166     /**
167      * Set mass change during maneuver.
168      * @param deltaMass mass change during maneuver (kg)
169      * @since 12.0
170      */
171     public void setDeltaMass(final double deltaMass) {
172         refuseFurtherComments();
173         this.deltaMass = deltaMass;
174     }
175 
176 }