1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.maneuvers;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
21 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22 import org.hipparchus.ode.events.Action;
23 import org.hipparchus.util.FastMath;
24 import org.orekit.attitudes.AttitudeProvider;
25 import org.orekit.orbits.FieldCartesianOrbit;
26 import org.orekit.orbits.FieldOrbit;
27 import org.orekit.propagation.FieldSpacecraftState;
28 import org.orekit.propagation.events.FieldDetectorModifier;
29 import org.orekit.propagation.events.FieldEventDetectionSettings;
30 import org.orekit.propagation.events.FieldEventDetector;
31 import org.orekit.propagation.events.handlers.FieldEventHandler;
32 import org.orekit.time.FieldAbsoluteDate;
33 import org.orekit.utils.Constants;
34 import org.orekit.utils.FieldAbsolutePVCoordinates;
35 import org.orekit.utils.FieldPVCoordinates;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 public class FieldImpulseManeuver<T extends CalculusFieldElement<T>> extends AbstractImpulseManeuver
77 implements FieldDetectorModifier<T> {
78
79
80 private final FieldEventDetector<T> trigger;
81
82
83 private final T isp;
84
85
86 private final T vExhaust;
87
88
89 private final FieldEventDetectionSettings<T> detectionSettings;
90
91
92 private final Handler<T> handler;
93
94
95 private final FieldImpulseProvider<T> fieldImpulseProvider;
96
97
98 private boolean forward;
99
100
101
102
103
104
105 public FieldImpulseManeuver(final FieldEventDetector<T> trigger, final FieldVector3D<T> deltaVSat, final T isp) {
106 this(trigger, null, deltaVSat, isp);
107 }
108
109
110
111
112
113
114
115 public FieldImpulseManeuver(final FieldEventDetector<T> trigger, final AttitudeProvider attitudeOverride,
116 final FieldVector3D<T> deltaVSat, final T isp) {
117 this(trigger, attitudeOverride, FieldImpulseProvider.of(deltaVSat), isp, Control3DVectorCostType.TWO_NORM);
118 }
119
120
121
122
123
124
125
126
127
128 @Deprecated
129 public FieldImpulseManeuver(final FieldEventDetector<T> trigger, final AttitudeProvider attitudeOverride,
130 final FieldVector3D<T> deltaVSat, final T isp,
131 final Control3DVectorCostType control3DVectorCostType) {
132 this(trigger, trigger.getDetectionSettings(), attitudeOverride,
133 FieldImpulseProvider.of(deltaVSat), isp, control3DVectorCostType);
134 }
135
136
137
138
139
140
141
142
143 public FieldImpulseManeuver(final FieldEventDetector<T> trigger, final AttitudeProvider attitudeOverride,
144 final FieldImpulseProvider<T> fieldImpulseProvider, final T isp,
145 final Control3DVectorCostType control3DVectorCostType) {
146 this(trigger, trigger.getDetectionSettings(), attitudeOverride, fieldImpulseProvider, isp, control3DVectorCostType);
147 }
148
149
150
151
152
153
154
155
156
157 private FieldImpulseManeuver(final FieldEventDetector<T> trigger,
158 final FieldEventDetectionSettings<T> detectionSettings,
159 final AttitudeProvider attitudeOverride, final FieldImpulseProvider<T> fieldImpulseProvider,
160 final T isp, final Control3DVectorCostType control3DVectorCostType) {
161 super(attitudeOverride, control3DVectorCostType);
162 this.trigger = trigger;
163 this.detectionSettings = detectionSettings;
164 this.fieldImpulseProvider = fieldImpulseProvider;
165 this.isp = isp;
166 this.vExhaust = this.isp.multiply(Constants.G0_STANDARD_GRAVITY);
167 this.handler = new Handler<>();
168 }
169
170
171
172
173
174
175 public FieldImpulseManeuver<T> withDetectionSettings(final FieldEventDetectionSettings<T> eventDetectionSettings) {
176 return new FieldImpulseManeuver<>(trigger, eventDetectionSettings, getAttitudeOverride(), fieldImpulseProvider, isp,
177 getControl3DVectorCostType());
178 }
179
180
181 @Override
182 public void init(final FieldSpacecraftState<T> s0, final FieldAbsoluteDate<T> t) {
183 FieldDetectorModifier.super.init(s0, t);
184 forward = t.durationFrom(s0.getDate()).getReal() >= 0;
185 fieldImpulseProvider.init(s0, t);
186 }
187
188
189 @Override
190 public void finish(final FieldSpacecraftState<T> state) {
191 FieldDetectorModifier.super.finish(state);
192 fieldImpulseProvider.finish(state);
193 }
194
195
196 @Override
197 public FieldEventDetectionSettings<T> getDetectionSettings() {
198 return detectionSettings;
199 }
200
201
202 @Override
203 public FieldEventDetector<T> getDetector() {
204 return trigger;
205 }
206
207
208
209
210 public FieldEventDetector<T> getTrigger() {
211 return getDetector();
212 }
213
214
215
216
217
218
219 public FieldImpulseProvider<T> getFieldImpulseProvider() {
220 return fieldImpulseProvider;
221 }
222
223
224
225
226 public T getIsp() {
227 return isp;
228 }
229
230 @Override
231 public FieldEventHandler<T> getHandler() {
232 return handler;
233 }
234
235
236 private static class Handler<T extends CalculusFieldElement<T>> implements FieldEventHandler<T> {
237
238
239 @Override
240 public Action eventOccurred(final FieldSpacecraftState<T> s,
241 final FieldEventDetector<T> detector,
242 final boolean increasing) {
243 final FieldImpulseManeuver<T> im = (FieldImpulseManeuver<T>) detector;
244 im.trigger.getHandler().eventOccurred(s, im.trigger, increasing);
245 return Action.RESET_STATE;
246 }
247
248
249 @Override
250 public FieldSpacecraftState<T> resetState(final FieldEventDetector<T> detector,
251 final FieldSpacecraftState<T> oldState) {
252
253 final FieldImpulseManeuver<T> im = (FieldImpulseManeuver<T>) detector;
254 final FieldAbsoluteDate<T> date = oldState.getDate();
255 final boolean isStateOrbitDefined = oldState.isOrbitDefined();
256
257 final FieldRotation<T> rotation;
258 if (im.getAttitudeOverride() == null) {
259 rotation = oldState.getAttitude().getRotation();
260 } else {
261 rotation = im.getAttitudeOverride().getAttitudeRotation(isStateOrbitDefined ? oldState.getOrbit() : oldState.getAbsPVA(),
262 date, oldState.getFrame());
263 }
264
265
266 final FieldVector3D<T> deltaVSat = im.fieldImpulseProvider.getImpulse(oldState, im.forward);
267 final FieldVector3D<T> deltaV = rotation.applyInverseTo(deltaVSat);
268 final T one = oldState.getMass().getField().getOne();
269 final T sign = (im.forward) ? one : one.negate();
270
271
272 final FieldPVCoordinates<T> oldPV = oldState.getPVCoordinates();
273 final FieldVector3D<T> newVelocity = oldPV.getVelocity().add(deltaV);
274 final FieldPVCoordinates<T> newPV = new FieldPVCoordinates<>(oldPV.getPosition(), newVelocity);
275
276
277 final T normDeltaV = im.getControl3DVectorCostType().evaluate(deltaVSat);
278 final T newMass = oldState.getMass().multiply(FastMath.exp(normDeltaV.multiply(sign.negate()).divide(im.vExhaust)));
279
280
281 if (oldState.isOrbitDefined()) {
282 final FieldOrbit<T> newOrbit = new FieldCartesianOrbit<>(newPV, oldState.getFrame(), oldState.getDate(),
283 oldState.getOrbit().getMu());
284 return new FieldSpacecraftState<>(oldState.getOrbit().getType().normalize(newOrbit, oldState.getOrbit()),
285 oldState.getAttitude(), newMass, oldState.getAdditionalDataValues(),
286 oldState.getAdditionalStatesDerivatives());
287 } else {
288 final FieldAbsolutePVCoordinates<T> newAbsPVA = new FieldAbsolutePVCoordinates<>(oldState.getFrame(),
289 oldState.getDate(), newPV);
290 return new FieldSpacecraftState<>(newAbsPVA, oldState.getAttitude(), newMass,
291 oldState.getAdditionalDataValues(), oldState.getAdditionalStatesDerivatives());
292 }
293 }
294
295 }
296 }