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