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  
18  package org.orekit.forces.maneuvers.propulsion;
19  
20  import java.util.Arrays;
21  import java.util.Collections;
22  import java.util.List;
23  
24  import org.hipparchus.CalculusFieldElement;
25  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26  import org.hipparchus.geometry.euclidean.threed.Vector3D;
27  import org.hipparchus.util.FastMath;
28  import org.orekit.forces.maneuvers.Control3DVectorCostType;
29  import org.orekit.time.AbsoluteDate;
30  import org.orekit.utils.ParameterDriver;
31  
32  /** Constant thrust propulsion model with:
33   *  - Constant thrust direction in spacecraft frame
34   *  - Parameter drivers (for estimation) for the thrust norm or the flow rate.
35   * Note that both parameters CANNOT be selected at the same time since they depend on one another.
36   * @author Maxime Journot
37   * @since 10.2
38   */
39  public class BasicConstantThrustPropulsionModel extends AbstractConstantThrustPropulsionModel {
40  
41      /** Parameter name for thrust. */
42      public static final String THRUST = "thrust";
43  
44      /** Parameter name for flow rate. */
45      public static final String FLOW_RATE = "flow rate";
46  
47      /** Thrust scaling factor.
48       * <p>
49       * We use a power of 2 to avoid numeric noise introduction
50       * in the multiplications/divisions sequences.
51       * </p>
52       */
53      public static final double THRUST_SCALE = FastMath.scalb(1.0, -5);
54  
55      /** Flow rate scaling factor.
56       * <p>
57       * We use a power of 2 to avoid numeric noise introduction
58       * in the multiplications/divisions sequences.
59       * </p>
60       */
61      public static final double FLOW_RATE_SCALE = FastMath.scalb(1.0, -12);
62  
63      /** Driver for thrust parameter. */
64      private final ParameterDriver thrustDriver;
65  
66      /** Driver for flow rate parameter. */
67      private final ParameterDriver flowRateDriver;
68  
69      /** Thrust direction in spacecraft frame. */
70      private final Vector3D direction;
71  
72      /** Generic constructor.
73       * @param thrust thrust (N)
74       * @param isp isp (s)
75       * @param direction direction in spacecraft frame
76       * @param control3DVectorCostType control cost type
77       * @param name name of the maneuver
78       * @since 12.0
79       */
80      public BasicConstantThrustPropulsionModel(final double thrust,
81                                                final double isp,
82                                                final Vector3D direction,
83                                                final Control3DVectorCostType control3DVectorCostType,
84                                                final String name) {
85          super(thrust, isp, direction, control3DVectorCostType, name);
86          this.direction = direction.normalize();
87  
88          final double initialFlowRate = super.getInitialFlowRate();
89  
90          // Build the parameter drivers, using maneuver name as prefix
91          this.thrustDriver   = new ParameterDriver(name + THRUST, thrust, THRUST_SCALE,
92                                                    0.0, Double.POSITIVE_INFINITY);
93          this.flowRateDriver = new ParameterDriver(name + FLOW_RATE, initialFlowRate, FLOW_RATE_SCALE,
94                                                    Double.NEGATIVE_INFINITY, 0.0 );
95      }
96  
97      /** Simple constructor.
98       * @param thrust thrust (N)
99       * @param isp isp (s)
100      * @param direction direction in spacecraft frame
101      * @param name name of the maneuver
102      */
103     public BasicConstantThrustPropulsionModel(final double thrust,
104                                               final double isp,
105                                               final Vector3D direction,
106                                               final String name) {
107         this(thrust, isp, direction, DEFAULT_CONTROL_3D_VECTOR_COST_TYPE, name);
108     }
109 
110     /** {@inheritDoc} */
111     @Override
112     public Vector3D getThrustVector() {
113         // Thrust vector does not depend on spacecraft state for a constant maneuver.
114         // thrustDriver as only 1 value estimated over the whole time period
115         // by construction thrustDriver has only 1 value estimated over the all period
116         // that is why no argument is acceptable
117         return direction.scalarMultiply(thrustDriver.getValue());
118     }
119 
120     /** {@inheritDoc} */
121     @Override
122     public Vector3D getThrustVector(final AbsoluteDate date) {
123         // Thrust vector does not depend on spacecraft state for a constant maneuver.
124         return direction.scalarMultiply(thrustDriver.getValue(date));
125     }
126 
127     /** {@inheritDoc} */
128     @Override
129     public double getFlowRate() {
130         // Thrust vector does not depend on spacecraft state for a constant maneuver.
131         // thrustDriver has only 1 value estimated over the whole time period
132         // by construction thrustDriver has only 1 value estimated over the all period
133         // that is why no argument is acceptable
134         return flowRateDriver.getValue();
135     }
136 
137     /** {@inheritDoc} */
138     @Override
139     public double getFlowRate(final AbsoluteDate date) {
140         return flowRateDriver.getValue(date);
141     }
142 
143     /** {@inheritDoc} */
144     @Override
145     public List<ParameterDriver> getParametersDrivers() {
146         return Collections.unmodifiableList(Arrays.asList(thrustDriver, flowRateDriver));
147     }
148 
149     /** {@inheritDoc} */
150     @Override
151     public Vector3D getThrustVector(final double[] parameters) {
152         // Thrust vector does not depend on spacecraft state for a constant maneuver.
153         return direction.scalarMultiply(parameters[0]);
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     public double getFlowRate(final double[] parameters) {
159         return parameters[1];
160     }
161 
162     /** {@inheritDoc} */
163     @Override
164     public <T extends CalculusFieldElement<T>> FieldVector3D<T> getThrustVector(final T[] parameters) {
165         return new FieldVector3D<>(parameters[0], direction);
166     }
167 
168     /** {@inheritDoc} */
169     @Override
170     public <T extends CalculusFieldElement<T>> T getFlowRate(final T[] parameters) {
171         return parameters[1];
172     }
173 }