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.forces.maneuvers;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.geometry.euclidean.threed.Vector3D;
21  import org.orekit.attitudes.AttitudeProvider;
22  import org.orekit.forces.maneuvers.propulsion.AbstractConstantThrustPropulsionModel;
23  import org.orekit.forces.maneuvers.propulsion.BasicConstantThrustPropulsionModel;
24  import org.orekit.forces.maneuvers.trigger.DateBasedManeuverTriggers;
25  import org.orekit.propagation.FieldSpacecraftState;
26  import org.orekit.propagation.SpacecraftState;
27  import org.orekit.time.AbsoluteDate;
28  
29  /** This class implements a simple maneuver with constant thrust.
30   * <p>The maneuver is defined by a direction in satellite frame.
31   * The current attitude of the spacecraft, defined by the current
32   * spacecraft state, will be used to compute the thrust direction in
33   * inertial frame. A typical case for tangential maneuvers is to use a
34   * {@link org.orekit.attitudes.LofOffset LOF aligned} attitude provider
35   * for state propagation and a velocity increment along the +X satellite axis.</p>
36   * @author Fabien Maussion
37   * @author V&eacute;ronique Pommier-Maurussane
38   * @author Luc Maisonobe
39   * @author Maxime Journot
40   */
41  public class ConstantThrustManeuver extends Maneuver {
42  
43      /** Simple constructor for a constant direction and constant thrust.
44       * <p>
45       * It uses the propulsion model {@link BasicConstantThrustPropulsionModel} and
46       * the maneuver triggers {@link DateBasedManeuverTriggers}
47       * </p><p>
48       * Calling this constructor is equivalent to call {@link
49       * #ConstantThrustManeuver(AbsoluteDate, double, double, double, Vector3D, String)
50       * ConstantThrustManeuver(date, duration, thrust, isp, direction, "")},
51       * hence not using any prefix for the parameters drivers names.
52       * </p>
53       * @param date maneuver date
54       * @param duration the duration of the thrust (s) (if negative,
55       * the date is considered to be the stop date)
56       * @param thrust the thrust force (N)
57       * @param isp engine specific impulse (s)
58       * @param direction the acceleration direction in satellite frame.
59       */
60      public ConstantThrustManeuver(final AbsoluteDate date, final double duration,
61                                    final double thrust, final double isp,
62                                    final Vector3D direction) {
63          this(date, duration, thrust, isp, direction, "");
64      }
65  
66      /** Simple constructor for a constant direction and constant thrust.
67       * <p>
68       * It uses the propulsion model {@link BasicConstantThrustPropulsionModel} and
69       * the maneuver triggers {@link DateBasedManeuverTriggers}
70       * </p><p>
71       * Calling this constructor is equivalent to call {@link
72       * #ConstantThrustManeuver(AbsoluteDate, double, double, double, Vector3D, String)
73       * ConstantThrustManeuver(date, duration, thrust, isp, direction, "")},
74       * hence not using any prefix for the parameters drivers names.
75       * </p>
76       * @param date maneuver date
77       * @param duration the duration of the thrust (s) (if negative,
78       * the date is considered to be the stop date)
79       * @param thrust the thrust force (N)
80       * @param isp engine specific impulse (s)
81       * @param attitudeOverride the attitude provider to use for the maneuver, or
82       * null if the attitude from the propagator should be used
83       * @param direction the acceleration direction in satellite frame.
84       * @param name name of the maneuver, used as a prefix for the {@link #getParametersDrivers() parameters drivers}
85       * @since 12.0
86       */
87      public ConstantThrustManeuver(final AbsoluteDate date, final double duration,
88                                    final double thrust, final double isp,
89                                    final AttitudeProvider attitudeOverride,
90                                    final Vector3D direction,
91                                    final String name) {
92          this(date, duration, thrust, isp, attitudeOverride, direction, Control3DVectorCostType.TWO_NORM, name);
93      }
94  
95      /** Simple constructor for a constant direction and constant thrust.
96       * <p>
97       * It uses the propulsion model {@link BasicConstantThrustPropulsionModel} and
98       * the maneuver triggers {@link DateBasedManeuverTriggers}
99       * </p><p>
100      * Calling this constructor is equivalent to call {@link
101      * #ConstantThrustManeuver(AbsoluteDate, double, double, double, Vector3D, String)
102      * ConstantThrustManeuver(date, duration, thrust, isp, direction, "")},
103      * hence not using any prefix for the parameters drivers names.
104      * </p>
105      * @param date maneuver date
106      * @param duration the duration of the thrust (s) (if negative,
107      * the date is considered to be the stop date)
108      * @param thrust the thrust force (N)
109      * @param isp engine specific impulse (s)
110      * @param attitudeOverride the attitude provider to use for the maneuver, or
111      * null if the attitude from the propagator should be used
112      * @param direction the acceleration direction in satellite frame.
113      * @since 9.2
114      */
115     public ConstantThrustManeuver(final AbsoluteDate date, final double duration,
116                                   final double thrust, final double isp,
117                                   final AttitudeProvider attitudeOverride, final Vector3D direction) {
118         this(date, duration, thrust, isp, attitudeOverride, direction, "");
119     }
120 
121     /** Simple constructor for a constant direction and constant thrust.
122      * <p>
123      * It uses the propulsion model {@link BasicConstantThrustPropulsionModel} and
124      * the maneuver triggers {@link DateBasedManeuverTriggers}
125      * </p><p>
126      * The name of the maneuver is used to distinguish the parameter drivers.
127      * A typical use case is to use something like "1A-" or "2B-" as a prefix corresponding to the
128      * name of the thruster to use, so separate parameters can be adjusted
129      * for the different thrusters involved during an orbit determination
130      * where maneuvers parameters are estimated.
131      * </p>
132      * @param date maneuver date
133      * @param duration the duration of the thrust (s) (if negative,
134      * the date is considered to be the stop date)
135      * @param thrust the thrust force (N)
136      * @param isp engine specific impulse (s)
137      * @param direction the acceleration direction in satellite frame
138      * @param name name of the maneuver, used as a prefix for the {@link #getParametersDrivers() parameters drivers}
139      * @since 9.0
140      */
141     public ConstantThrustManeuver(final AbsoluteDate date, final double duration,
142                                   final double thrust, final double isp,
143                                   final Vector3D direction,
144                                   final String name) {
145         this(date, duration, thrust, isp, null, direction, name);
146     }
147 
148     /** Simple constructor for a constant direction and constant thrust.
149      * <p>
150      * It uses the propulsion model {@link BasicConstantThrustPropulsionModel} and
151      * the maneuver triggers {@link DateBasedManeuverTriggers}
152      * </p><p>
153      * The name of the maneuver is used to distinguish the parameter drivers.
154      * A typical use case is to use something like "1A-" or "2B-" as a prefix corresponding to the
155      * name of the thruster to use, so separate parameters can be adjusted
156      * for the different thrusters involved during an orbit determination
157      * where maneuvers parameters are estimated.
158      * </p>
159      * @param date maneuver date
160      * @param duration the duration of the thrust (s) (if negative,
161      * the date is considered to be the stop date)
162      * @param thrust the thrust force (N)
163      * @param isp engine specific impulse (s)
164      * @param attitudeOverride the attitude provider to use for the maneuver, or
165      * null if the attitude from the propagator should be used
166      * @param direction the acceleration direction in satellite frame
167      * @param control3DVectorCostType control vector's cost type
168      * @param name name of the maneuver, used as a prefix for the {@link #getParametersDrivers() parameters drivers}
169      * @since 12.0
170      */
171     public ConstantThrustManeuver(final AbsoluteDate date, final double duration,
172                                   final double thrust, final double isp, final AttitudeProvider attitudeOverride,
173                                   final Vector3D direction, final Control3DVectorCostType control3DVectorCostType,
174                                   final String name) {
175         this(date, duration, attitudeOverride,
176                 new BasicConstantThrustPropulsionModel(thrust, isp, direction, control3DVectorCostType, name));
177     }
178 
179     /** Simple constructor for a constant direction and constant thrust.
180      * <p>
181      * It uses an {@link AbstractConstantThrustPropulsionModel} and
182      * the maneuver triggers {@link DateBasedManeuverTriggers}
183      * </p><p>
184      * The names of the maneuver (and thus its parameter drivers) are extracted
185      * from the propulsion model.
186      * </p>
187      * @param date maneuver date
188      * @param duration the duration of the thrust (s) (if negative,
189      * the date is considered to be the stop date)
190      * @param attitudeOverride the attitude provider to use for the maneuver, or
191      * null if the attitude from the propagator should be used
192      * @param constantThrustPropulsionModel user-defined constant thrust propulsion model
193      */
194     public ConstantThrustManeuver(final AbsoluteDate date, final double duration,
195                                   final AttitudeProvider attitudeOverride,
196                                   final AbstractConstantThrustPropulsionModel constantThrustPropulsionModel) {
197         this(attitudeOverride,
198              new DateBasedManeuverTriggers(constantThrustPropulsionModel.getName(), date, duration),
199              constantThrustPropulsionModel);
200     }
201 
202     /** Simple constructor for a constant direction and constant thrust.
203      * <p>
204      * It uses an {@link AbstractConstantThrustPropulsionModel} and
205      * the maneuver triggers {@link DateBasedManeuverTriggers}
206      * </p><p>
207      * The names of the maneuver (and thus its parameter drivers) are extracted
208      * from the propulsion model or the maneuver triggers.
209      * Propulsion model name is evaluated first, if it isn't empty, it becomes the name of the maneuver.
210      * In that case the name in the maneuver triggers should be the same or empty, otherwise this could be
211      * misleading when retrieving estimated parameters by their names.
212      * </p>
213      * @param attitudeOverride the attitude provider to use for the maneuver, or
214      * null if the attitude from the propagator should be used
215      * @param dateBasedManeuverTriggers user-defined maneuver triggers object based on a start and end date
216      * @param constantThrustPropulsionModel user-defined constant thrust propulsion model
217      */
218     public ConstantThrustManeuver(final AttitudeProvider attitudeOverride,
219                                   final DateBasedManeuverTriggers dateBasedManeuverTriggers,
220                                   final AbstractConstantThrustPropulsionModel constantThrustPropulsionModel) {
221         super(attitudeOverride, dateBasedManeuverTriggers, constantThrustPropulsionModel);
222     }
223 
224     /** Get the thrust vector (N) in S/C frame.
225      * @param date date at which the thrust vector wants to be known,
226      * often the date parameter will not be important and can be whatever
227      * if the thrust parameter driver as only value estimated over the all
228      * orbit determination interval
229      * @return thrust vector (N) in S/C frame.
230      */
231     public Vector3D getThrustVector(final AbsoluteDate date) {
232         return ((AbstractConstantThrustPropulsionModel) getPropulsionModel()).getThrustVector(date);
233     }
234 
235     /** Get the thrust vector (N) in S/C frame.
236      * @return thrust vector (N) in S/C frame.
237      */
238     public Vector3D getThrustVector() {
239         return ((AbstractConstantThrustPropulsionModel) getPropulsionModel()).getThrustVector();
240     }
241 
242     /** Get the thrust magnitude.
243      * @param date date at which the thrust vector wants to be known,
244      * often the date parameter will not be important and can be whatever
245      * if the thrust parameter driver as only value estimated over the all
246      * orbit determination interval
247      * @return thrust force (N).
248      */
249     public double getThrustMagnitude(final AbsoluteDate date) {
250         return getThrustVector(date).getNorm();
251     }
252 
253     /** Get the thrust magnitude.
254      * @return thrust force (N).
255      */
256     public double getThrustMagnitude() {
257         return getThrustVector().getNorm();
258     }
259 
260     /** Get the specific impulse at given date.
261      * @param date date at which the thrust vector wants to be known,
262      * often the date parameter will not be important and can be whatever
263      * if the thrust parameter driver as only value estimated over the all
264      * orbit determination interval
265      * @return specific impulse (s).
266      */
267     public double getIsp(final AbsoluteDate date) {
268         return ((AbstractConstantThrustPropulsionModel) getPropulsionModel()).getIsp(date);
269     }
270 
271     /** Get the specific impulse.
272      * @return specific impulse (s).
273      */
274     public double getIsp() {
275         return ((AbstractConstantThrustPropulsionModel) getPropulsionModel()).getIsp();
276     }
277 
278     /** Get the flow rate at given date.
279      * @param date at which the Thrust wants to be known
280      * @return flow rate (negative, kg/s).
281      */
282     public double getFlowRate(final AbsoluteDate date) {
283         return ((AbstractConstantThrustPropulsionModel) getPropulsionModel()).getFlowRate(date);
284     }
285 
286     /** Get the flow rate.
287      * @return flow rate (negative, kg/s).
288      */
289     public double getFlowRate() {
290         return ((AbstractConstantThrustPropulsionModel) getPropulsionModel()).getFlowRate();
291     }
292 
293     /** Get the direction.
294      * @param date at which the Thrust wants to be known
295      * @return the direction
296      * @since 9.2
297      */
298     public Vector3D getDirection(final AbsoluteDate date) {
299         return getThrustVector(date).normalize();
300     }
301 
302     /** Get the direction.
303      * @return the direction
304      * @since 9.2
305      */
306     public Vector3D getDirection() {
307         return getThrustVector().normalize();
308     }
309 
310     /** Get the start date.
311      * @return the start date
312      * @since 9.2
313      */
314     public AbsoluteDate getStartDate() {
315         return ((DateBasedManeuverTriggers) getManeuverTriggers()).getStartDate();
316     }
317 
318     /** Get the end date.
319      * @return the end date
320      * @since 9.2
321      */
322     public AbsoluteDate getEndDate() {
323         return ((DateBasedManeuverTriggers) getManeuverTriggers()).getEndDate();
324     }
325 
326     /** Get the duration of the maneuver (s).
327      * duration = endDate - startDate
328      * @return the duration of the maneuver (s)
329      * @since 9.2
330      */
331     public double getDuration() {
332         return ((DateBasedManeuverTriggers) getManeuverTriggers()).getDuration();
333     }
334 
335     /** Check if maneuvering is on.
336      * @param s current state
337      * @return true if maneuver is on at this state
338      * @since 10.1
339      */
340     public boolean isFiring(final SpacecraftState s) {
341         return isFiring(s.getDate());
342     }
343 
344     /** Check if maneuvering is on.
345      * @param s current state
346      * @param <T> type of the field elements
347      * @return true if maneuver is on at this state
348      * @since 10.1
349      */
350     public <T extends CalculusFieldElement<T>> boolean isFiring(final FieldSpacecraftState<T> s) {
351         return isFiring(s.getDate().toAbsoluteDate());
352     }
353 
354     /** Check if maneuvering is on.
355      * @param date current date
356      * @return true if maneuver is on at this date
357      * @since 10.1
358      */
359     public boolean isFiring(final AbsoluteDate date) {
360         return getManeuverTriggers().isFiring(date, new double[] {});
361     }
362 }