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.geometry.euclidean.threed.Rotation;
20 import org.hipparchus.geometry.euclidean.threed.Vector3D;
21 import org.hipparchus.ode.events.Action;
22 import org.hipparchus.util.FastMath;
23 import org.orekit.attitudes.AttitudeProvider;
24 import org.orekit.forces.maneuvers.propulsion.ThrustPropulsionModel;
25 import org.orekit.orbits.CartesianOrbit;
26 import org.orekit.propagation.SpacecraftState;
27 import org.orekit.propagation.events.DetectorModifier;
28 import org.orekit.propagation.events.EventDetectionSettings;
29 import org.orekit.propagation.events.EventDetector;
30 import org.orekit.propagation.events.handlers.EventHandler;
31 import org.orekit.time.AbsoluteDate;
32 import org.orekit.utils.AbsolutePVCoordinates;
33 import org.orekit.utils.PVCoordinates;
34
35
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 public class ImpulseManeuver extends AbstractImpulseManeuver implements DetectorModifier {
72
73
74 private final EventDetector trigger;
75
76
77 private final double isp;
78
79
80 private final double vExhaust;
81
82
83 private final EventDetectionSettings detectionSettings;
84
85
86 private final Handler handler;
87
88
89 private final ImpulseProvider impulseProvider;
90
91
92 private boolean forward;
93
94
95
96
97
98
99 public ImpulseManeuver(final EventDetector trigger, final Vector3D deltaVSat, final double isp) {
100 this(trigger, null, deltaVSat, isp);
101 }
102
103
104
105
106
107
108
109 public ImpulseManeuver(final EventDetector trigger, final AttitudeProvider attitudeOverride,
110 final Vector3D deltaVSat, final double isp) {
111 this(trigger, attitudeOverride, ImpulseProvider.of(deltaVSat), isp, Control3DVectorCostType.TWO_NORM);
112 }
113
114
115
116
117
118
119
120
121
122 public ImpulseManeuver(final EventDetector trigger, final AttitudeProvider attitudeOverride,
123 final ImpulseProvider impulseProvider, final double isp, final Control3DVectorCostType control3DVectorCostType) {
124 this(trigger, trigger.getDetectionSettings(), attitudeOverride, impulseProvider, isp, control3DVectorCostType);
125 }
126
127
128
129
130
131
132
133
134
135
136 private ImpulseManeuver(final EventDetector trigger, final EventDetectionSettings detectionSettings,
137 final AttitudeProvider attitudeOverride, final ImpulseProvider impulseProvider,
138 final double isp, final Control3DVectorCostType control3DVectorCostType) {
139 super(attitudeOverride, control3DVectorCostType);
140 this.trigger = trigger;
141 this.detectionSettings = detectionSettings;
142 this.impulseProvider = impulseProvider;
143 this.isp = isp;
144 this.vExhaust = ThrustPropulsionModel.getExhaustVelocity(isp);
145 this.handler = new Handler();
146 }
147
148
149
150
151
152
153 public ImpulseManeuver withDetectionSettings(final EventDetectionSettings eventDetectionSettings) {
154 return new ImpulseManeuver(trigger, eventDetectionSettings, getAttitudeOverride(), impulseProvider, isp,
155 getControl3DVectorCostType());
156 }
157
158
159 @Override
160 public void init(final SpacecraftState s0, final AbsoluteDate t) {
161 DetectorModifier.super.init(s0, t);
162 forward = t.durationFrom(s0.getDate()) >= 0;
163 impulseProvider.init(s0, t);
164 }
165
166
167 @Override
168 public void finish(final SpacecraftState state) {
169 DetectorModifier.super.finish(state);
170 impulseProvider.finish(state);
171 }
172
173
174 @Override
175 public EventDetector getDetector() {
176 return getTrigger();
177 }
178
179
180 @Override
181 public EventHandler getHandler() {
182 return handler;
183 }
184
185
186 @Override
187 public EventDetectionSettings getDetectionSettings() {
188 return detectionSettings;
189 }
190
191
192
193
194 public EventDetector getTrigger() {
195 return trigger;
196 }
197
198
199
200
201
202
203 public ImpulseProvider getImpulseProvider() {
204 return impulseProvider;
205 }
206
207
208
209
210 public double getIsp() {
211 return isp;
212 }
213
214
215 private class Handler implements EventHandler {
216
217 @Override
218 public void init(final SpacecraftState initialState, final AbsoluteDate target, final EventDetector detector) {
219 getDetector().getHandler().init(initialState, target, getDetector());
220 }
221
222 @Override
223 public void finish(final SpacecraftState finalState, final EventDetector detector) {
224 getDetector().getHandler().finish(finalState, getDetector());
225 }
226
227
228 public Action eventOccurred(final SpacecraftState s, final EventDetector detector,
229 final boolean increasing) {
230 final Action action = getDetector().getHandler().eventOccurred(s, getDetector(), increasing);
231 return action == Action.CONTINUE ? action : Action.RESET_STATE;
232 }
233
234
235 @Override
236 public SpacecraftState resetState(final EventDetector detector, final SpacecraftState oldState) {
237
238 final ImpulseManeuver im = (ImpulseManeuver) detector;
239 final AbsoluteDate date = oldState.getDate();
240 final AttitudeProvider override = im.getAttitudeOverride();
241 final boolean isStateOrbitDefined = oldState.isOrbitDefined();
242
243 final Rotation rotation;
244 if (override == null) {
245 rotation = oldState.getAttitude().getRotation();
246 } else {
247 rotation = override.getAttitudeRotation(isStateOrbitDefined ? oldState.getOrbit() : oldState.getAbsPVA(),
248 date, oldState.getFrame());
249 }
250
251
252 final Vector3D deltaVSat = im.impulseProvider.getImpulse(oldState, im.forward);
253 final Vector3D deltaV = rotation.applyInverseTo(deltaVSat);
254
255
256 final PVCoordinates oldPV = oldState.getPVCoordinates();
257 final Vector3D newVelocity = oldPV.getVelocity().add(deltaV);
258 final PVCoordinates newPV = new PVCoordinates(oldPV.getPosition(), newVelocity);
259
260
261 final double normDeltaV = im.getControl3DVectorCostType().evaluate(deltaVSat);
262 final double sign = im.forward ? +1 : -1;
263 final double newMass = oldState.getMass() * FastMath.exp(-sign * normDeltaV / im.vExhaust);
264
265
266 if (oldState.isOrbitDefined()) {
267 final CartesianOrbit newOrbit = new CartesianOrbit(newPV, oldState.getFrame(), oldState.getDate(),
268 oldState.getOrbit().getMu());
269 return new SpacecraftState(oldState.getOrbit().getType().normalize(newOrbit, oldState.getOrbit()),
270 oldState.getAttitude(), newMass, oldState.getAdditionalDataValues(), oldState.getAdditionalStatesDerivatives());
271 } else {
272 final AbsolutePVCoordinates newAPV = new AbsolutePVCoordinates(oldState.getFrame(), oldState.getDate(),
273 newPV);
274 return new SpacecraftState(newAPV, oldState.getAttitude(), newMass,
275 oldState.getAdditionalDataValues(), oldState.getAdditionalStatesDerivatives());
276 }
277 }
278
279 }
280
281 }