1 /* Copyright 2002-2024 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 org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.hipparchus.util.Precision;
24 import org.orekit.attitudes.Attitude;
25 import org.orekit.attitudes.FieldAttitude;
26 import org.orekit.propagation.FieldSpacecraftState;
27 import org.orekit.propagation.SpacecraftState;
28 import org.orekit.utils.Constants;
29
30 /** Interface for a thrust-based propulsion model.
31 * @author Maxime Journot
32 * @since 10.2
33 */
34 public interface ThrustPropulsionModel extends PropulsionModel {
35
36 /** Get the specific impulse (s).
37 * @param s current spacecraft state
38 * @return specific impulse (s).
39 */
40 default double getIsp(SpacecraftState s) {
41 final double flowRate = getFlowRate(s);
42 return -getControl3DVectorCostType().evaluate(getThrustVector(s)) / (Constants.G0_STANDARD_GRAVITY * flowRate);
43 }
44
45 /** Get the thrust direction in spacecraft frame.
46 * <p>
47 * Return a zero vector if there is no thrust for given spacecraft state.
48 * @param s current spacecraft state
49 * @return thrust direction in spacecraft frame
50 */
51 default Vector3D getDirection(SpacecraftState s) {
52 final Vector3D thrustVector = getThrustVector(s);
53 final double norm = thrustVector.getNorm();
54 if (norm <= Precision.EPSILON) {
55 return Vector3D.ZERO;
56 }
57 return thrustVector.scalarMultiply(1. / norm);
58 }
59
60 /** Get the thrust vector in spacecraft frame (N).
61 * @param s current spacecraft state
62 * @return thrust vector in spacecraft frame (N)
63 */
64 Vector3D getThrustVector(SpacecraftState s);
65
66 /** Get the flow rate (kg/s).
67 * @param s current spacecraft state
68 * @return flow rate (kg/s)
69 */
70 double getFlowRate(SpacecraftState s);
71
72 /** Get the thrust vector in spacecraft frame (N).
73 * @param s current spacecraft state
74 * @param parameters propulsion model parameters
75 * @return thrust vector in spacecraft frame (N)
76 */
77 Vector3D getThrustVector(SpacecraftState s, double[] parameters);
78
79 /** Get the flow rate (kg/s).
80 * @param s current spacecraft state
81 * @param parameters propulsion model parameters
82 * @return flow rate (kg/s)
83 */
84 double getFlowRate(SpacecraftState s, double[] parameters);
85
86 /** Get the thrust vector in spacecraft frame (N).
87 * @param s current spacecraft state
88 * @param parameters propulsion model parameters
89 * @param <T> extends CalculusFieldElement<T>
90 * @return thrust vector in spacecraft frame (N)
91 */
92 <T extends CalculusFieldElement<T>> FieldVector3D<T> getThrustVector(FieldSpacecraftState<T> s, T[] parameters);
93
94 /** Get the flow rate (kg/s).
95 * @param s current spacecraft state
96 * @param parameters propulsion model parameters
97 * @param <T> extends CalculusFieldElement<T>
98 * @return flow rate (kg/s)
99 */
100 <T extends CalculusFieldElement<T>> T getFlowRate(FieldSpacecraftState<T> s, T[] parameters);
101
102 /** {@inheritDoc}
103 * Acceleration is computed here using the thrust vector in S/C frame.
104 */
105 @Override
106 default Vector3D getAcceleration(SpacecraftState s,
107 final Attitude maneuverAttitude,
108 double[] parameters) {
109
110 final Vector3D thrustVector = getThrustVector(s, parameters);
111 final double thrust = thrustVector.getNorm();
112 if (thrust == 0) {
113 return Vector3D.ZERO;
114 }
115 final Vector3D direction = thrustVector.normalize();
116
117 // Compute thrust acceleration in inertial frame
118 // It seems under-efficient to rotate direction and apply thrust
119 // instead of just rotating the whole thrust vector itself.
120 // However it has to be done that way to avoid numerical discrepancies with legacy tests.
121 return new Vector3D(thrust / s.getMass(),
122 maneuverAttitude.getRotation().applyInverseTo(direction));
123 }
124
125 /** {@inheritDoc}
126 * Acceleration is computed here using the thrust vector in S/C frame.
127 */
128 @Override
129 default <T extends CalculusFieldElement<T>> FieldVector3D<T> getAcceleration(FieldSpacecraftState<T> s,
130 final FieldAttitude<T> maneuverAttitude,
131 T[] parameters) {
132 // Extract thrust & direction from thrust vector
133 final FieldVector3D<T> thrustVector = getThrustVector(s, parameters);
134 final T thrust = thrustVector.getNorm();
135 if (thrust.isZero()) {
136 return FieldVector3D.getZero(s.getDate().getField());
137 }
138 final FieldVector3D<T> direction = thrustVector.normalize();
139
140 // Compute thrust acceleration in inertial frame
141 // It seems under-efficient to rotate direction and apply thrust
142 // instead of just rotating the whole thrust vector itself.
143 // However it has to be done that way to avoid numerical discrepancies with legacy tests.
144 return new FieldVector3D<>(thrust.divide(s.getMass()),
145 maneuverAttitude.getRotation().applyInverseTo(direction));
146 }
147
148 /** {@inheritDoc}
149 * Mass derivatives are directly extracted here from the flow rate value.
150 */
151 @Override
152 default double getMassDerivatives(SpacecraftState s, double[] parameters) {
153 return getFlowRate(s, parameters);
154 }
155
156 /** {@inheritDoc}
157 * Mass derivatives are directly extracted here from the flow rate value.
158 */
159 @Override
160 default <T extends CalculusFieldElement<T>> T getMassDerivatives(FieldSpacecraftState<T> s, T[] parameters) {
161 return getFlowRate(s, parameters);
162 }
163
164 }