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.Field;
21 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
22 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
23 import org.hipparchus.ode.events.Action;
24 import org.hipparchus.util.FastMath;
25 import org.orekit.attitudes.AttitudeProvider;
26 import org.orekit.orbits.FieldCartesianOrbit;
27 import org.orekit.orbits.FieldOrbit;
28 import org.orekit.propagation.FieldSpacecraftState;
29 import org.orekit.propagation.events.FieldDetectorModifier;
30 import org.orekit.propagation.events.FieldEventDetectionSettings;
31 import org.orekit.propagation.events.FieldEventDetector;
32 import org.orekit.propagation.events.handlers.EventHandler;
33 import org.orekit.propagation.events.handlers.FieldEventHandler;
34 import org.orekit.propagation.events.handlers.FieldResetDerivativesOnEvent;
35 import org.orekit.propagation.events.handlers.FieldStopOnDecreasing;
36 import org.orekit.propagation.events.handlers.FieldStopOnEvent;
37 import org.orekit.propagation.events.handlers.FieldStopOnIncreasing;
38 import org.orekit.propagation.events.handlers.ResetDerivativesOnEvent;
39 import org.orekit.propagation.events.handlers.StopOnDecreasing;
40 import org.orekit.propagation.events.handlers.StopOnIncreasing;
41 import org.orekit.time.FieldAbsoluteDate;
42 import org.orekit.utils.Constants;
43 import org.orekit.utils.FieldAbsolutePVCoordinates;
44 import org.orekit.utils.FieldPVCoordinates;
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
77
78
79
80
81
82
83
84
85 public class FieldImpulseManeuver<T extends CalculusFieldElement<T>> extends AbstractImpulseManeuver
86 implements FieldDetectorModifier<T> {
87
88
89 private final FieldEventDetector<T> trigger;
90
91
92 private final T isp;
93
94
95 private final T vExhaust;
96
97
98 private final FieldEventDetectionSettings<T> detectionSettings;
99
100
101 private final Handler handler;
102
103
104 private final FieldImpulseProvider<T> fieldImpulseProvider;
105
106
107 private boolean forward;
108
109
110
111
112
113
114 public FieldImpulseManeuver(final FieldEventDetector<T> trigger, final FieldVector3D<T> deltaVSat, final T isp) {
115 this(trigger, null, deltaVSat, isp);
116 }
117
118
119
120
121
122
123
124 public FieldImpulseManeuver(final FieldEventDetector<T> trigger, final AttitudeProvider attitudeOverride,
125 final FieldVector3D<T> deltaVSat, final T isp) {
126 this(trigger, attitudeOverride, FieldImpulseProvider.of(deltaVSat), isp, Control3DVectorCostType.TWO_NORM);
127 }
128
129
130
131
132
133
134
135
136 public FieldImpulseManeuver(final FieldEventDetector<T> trigger, final AttitudeProvider attitudeOverride,
137 final FieldImpulseProvider<T> fieldImpulseProvider, final T isp,
138 final Control3DVectorCostType control3DVectorCostType) {
139 this(trigger, trigger.getDetectionSettings(), attitudeOverride, fieldImpulseProvider, isp, control3DVectorCostType);
140 }
141
142
143
144
145
146
147
148
149
150 private FieldImpulseManeuver(final FieldEventDetector<T> trigger,
151 final FieldEventDetectionSettings<T> detectionSettings,
152 final AttitudeProvider attitudeOverride, final FieldImpulseProvider<T> fieldImpulseProvider,
153 final T isp, final Control3DVectorCostType control3DVectorCostType) {
154 super(attitudeOverride, control3DVectorCostType);
155 this.trigger = trigger;
156 this.detectionSettings = detectionSettings;
157 this.fieldImpulseProvider = fieldImpulseProvider;
158 this.isp = isp;
159 this.vExhaust = this.isp.multiply(Constants.G0_STANDARD_GRAVITY);
160 this.handler = new Handler();
161 }
162
163
164
165
166
167
168
169
170 public FieldImpulseManeuver(final Field<T> field, final ImpulseManeuver maneuver) {
171 this(FieldEventDetector.of(field, convertHandler(maneuver.getDetector().getHandler()), maneuver.getDetector()),
172 maneuver.getAttitudeOverride(), FieldImpulseProvider.of(maneuver.getImpulseProvider()),
173 field.getZero().newInstance(maneuver.getIsp()), maneuver.getControl3DVectorCostType());
174 }
175
176 private static <T extends CalculusFieldElement<T>> FieldEventHandler<T> convertHandler(final EventHandler eventHandler) {
177 if (eventHandler instanceof StopOnDecreasing) {
178 return new FieldStopOnDecreasing<>();
179 } else if (eventHandler instanceof StopOnIncreasing) {
180 return new FieldStopOnIncreasing<>();
181 } else if (eventHandler instanceof ResetDerivativesOnEvent) {
182 return new FieldResetDerivativesOnEvent<>();
183 } else {
184 return new FieldStopOnEvent<>();
185 }
186 }
187
188
189
190
191
192
193 public FieldImpulseManeuver<T> withDetectionSettings(final FieldEventDetectionSettings<T> eventDetectionSettings) {
194 return new FieldImpulseManeuver<>(trigger, eventDetectionSettings, getAttitudeOverride(), fieldImpulseProvider, isp,
195 getControl3DVectorCostType());
196 }
197
198
199 @Override
200 public void init(final FieldSpacecraftState<T> s0, final FieldAbsoluteDate<T> t) {
201 FieldDetectorModifier.super.init(s0, t);
202 forward = t.durationFrom(s0.getDate()).getReal() >= 0;
203 fieldImpulseProvider.init(s0, t);
204 }
205
206
207 @Override
208 public void finish(final FieldSpacecraftState<T> state) {
209 FieldDetectorModifier.super.finish(state);
210 fieldImpulseProvider.finish(state);
211 }
212
213
214 @Override
215 public FieldEventDetectionSettings<T> getDetectionSettings() {
216 return detectionSettings;
217 }
218
219
220 @Override
221 public FieldEventDetector<T> getDetector() {
222 return trigger;
223 }
224
225
226
227
228 public FieldEventDetector<T> getTrigger() {
229 return getDetector();
230 }
231
232
233
234
235
236
237 public FieldImpulseProvider<T> getFieldImpulseProvider() {
238 return fieldImpulseProvider;
239 }
240
241
242
243
244 public T getIsp() {
245 return isp;
246 }
247
248 @Override
249 public FieldEventHandler<T> getHandler() {
250 return handler;
251 }
252
253
254 private class Handler implements FieldEventHandler<T> {
255
256 @Override
257 public void init(final FieldSpacecraftState<T> initialState, final FieldAbsoluteDate<T> target,
258 final FieldEventDetector<T> detector) {
259 getDetector().getHandler().init(initialState, target, getDetector());
260 }
261
262 @Override
263 public void finish(final FieldSpacecraftState<T> finalState, final FieldEventDetector<T> detector) {
264 getDetector().getHandler().finish(finalState, getDetector());
265 }
266
267
268 @Override
269 public Action eventOccurred(final FieldSpacecraftState<T> s,
270 final FieldEventDetector<T> detector,
271 final boolean increasing) {
272 final Action action = getDetector().getHandler().eventOccurred(s, getDetector(), increasing);
273 return action == Action.CONTINUE ? action : Action.RESET_STATE;
274 }
275
276
277 @Override
278 public FieldSpacecraftState<T> resetState(final FieldEventDetector<T> detector,
279 final FieldSpacecraftState<T> oldState) {
280
281 final FieldImpulseManeuver<T> im = (FieldImpulseManeuver<T>) detector;
282 final FieldAbsoluteDate<T> date = oldState.getDate();
283 final boolean isStateOrbitDefined = oldState.isOrbitDefined();
284
285 final FieldRotation<T> rotation;
286 if (im.getAttitudeOverride() == null) {
287 rotation = oldState.getAttitude().getRotation();
288 } else {
289 rotation = im.getAttitudeOverride().getAttitudeRotation(isStateOrbitDefined ? oldState.getOrbit() : oldState.getAbsPVA(),
290 date, oldState.getFrame());
291 }
292
293
294 final FieldVector3D<T> deltaVSat = im.fieldImpulseProvider.getImpulse(oldState, im.forward);
295 final FieldVector3D<T> deltaV = rotation.applyInverseTo(deltaVSat);
296 final T one = oldState.getMass().getField().getOne();
297 final T sign = (im.forward) ? one : one.negate();
298
299
300 final FieldPVCoordinates<T> oldPV = oldState.getPVCoordinates();
301 final FieldVector3D<T> newVelocity = oldPV.getVelocity().add(deltaV);
302 final FieldPVCoordinates<T> newPV = new FieldPVCoordinates<>(oldPV.getPosition(), newVelocity);
303
304
305 final T normDeltaV = im.getControl3DVectorCostType().evaluate(deltaVSat);
306 final T newMass = oldState.getMass().multiply(FastMath.exp(normDeltaV.multiply(sign.negate()).divide(im.vExhaust)));
307
308
309 if (oldState.isOrbitDefined()) {
310 final FieldOrbit<T> newOrbit = new FieldCartesianOrbit<>(newPV, oldState.getFrame(), oldState.getDate(),
311 oldState.getOrbit().getMu());
312 return new FieldSpacecraftState<>(oldState.getOrbit().getType().normalize(newOrbit, oldState.getOrbit()),
313 oldState.getAttitude(), newMass, oldState.getAdditionalDataValues(),
314 oldState.getAdditionalStatesDerivatives());
315 } else {
316 final FieldAbsolutePVCoordinates<T> newAbsPVA = new FieldAbsolutePVCoordinates<>(oldState.getFrame(),
317 oldState.getDate(), newPV);
318 return new FieldSpacecraftState<>(newAbsPVA, oldState.getAttitude(), newMass,
319 oldState.getAdditionalDataValues(), oldState.getAdditionalStatesDerivatives());
320 }
321 }
322
323 }
324 }