1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.orekit.forces.maneuvers.propulsion;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.stream.Stream;
24
25 import org.hipparchus.CalculusFieldElement;
26 import org.hipparchus.Field;
27 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
28 import org.hipparchus.geometry.euclidean.threed.Vector3D;
29 import org.orekit.forces.maneuvers.Control3DVectorCostType;
30 import org.orekit.propagation.FieldSpacecraftState;
31 import org.orekit.propagation.SpacecraftState;
32 import org.orekit.propagation.events.DateDetector;
33 import org.orekit.propagation.events.EventDetector;
34 import org.orekit.propagation.events.FieldDateDetector;
35 import org.orekit.propagation.events.FieldEventDetector;
36 import org.orekit.time.AbsoluteDate;
37 import org.orekit.time.TimeStamped;
38 import org.orekit.utils.ParameterDriver;
39 import org.orekit.utils.TimeSpanMap;
40
41
42
43
44
45 public class ProfileThrustPropulsionModel implements ThrustPropulsionModel {
46
47
48 private final TimeSpanMap<ThrustVectorProvider> profile;
49
50
51 private final double isp;
52
53
54 private final String name;
55
56
57 private final Control3DVectorCostType control3DVectorCostType;
58
59
60
61
62
63
64
65 public ProfileThrustPropulsionModel(final TimeSpanMap<ThrustVectorProvider> profile, final double isp,
66 final String name) {
67 this(profile, isp, Control3DVectorCostType.TWO_NORM, name);
68 }
69
70
71
72
73
74
75
76
77 public ProfileThrustPropulsionModel(final TimeSpanMap<ThrustVectorProvider> profile, final double isp,
78 final Control3DVectorCostType control3DVectorCostType, final String name) {
79 this.name = name;
80 this.isp = isp;
81 this.profile = profile;
82 this.control3DVectorCostType = control3DVectorCostType;
83 }
84
85
86
87
88
89
90
91
92
93
94 public static <T extends ThrustVectorProvider> ProfileThrustPropulsionModel of(final TimeSpanMap<T> profile,
95 final double isp,
96 final Control3DVectorCostType control3DVectorCostType,
97 final String name) {
98 return new ProfileThrustPropulsionModel(buildSegments(profile), isp, control3DVectorCostType, name);
99 }
100
101
102
103
104
105
106
107
108 private static <T extends ThrustVectorProvider> TimeSpanMap<ThrustVectorProvider> buildSegments(final TimeSpanMap<T> timeSpanMap) {
109 TimeSpanMap.Span<T> span = timeSpanMap.getFirstSpan();
110 final TimeSpanMap<ThrustVectorProvider> segments = new TimeSpanMap<>(null);
111 while (span != null) {
112 segments.addValidBetween(span.getData(), span.getStart(), span.getEnd());
113 span = span.next();
114 }
115 return segments;
116 }
117
118
119 @Override
120 public String getName() {
121 return name;
122 }
123
124
125 @Override
126 public Control3DVectorCostType getControl3DVectorCostType() {
127 return control3DVectorCostType;
128 }
129
130
131
132
133
134
135
136 public ThrustVectorProvider getActiveProvider(final AbsoluteDate date) {
137 return profile.get(date);
138 }
139
140
141 @Override
142 public Vector3D getThrustVector(final SpacecraftState s) {
143 return getThrustVector(s, getParameters());
144 }
145
146
147 @Override
148 public double getFlowRate(final SpacecraftState s) {
149 return getFlowRate(s, getParameters());
150 }
151
152
153 @Override
154 public double getFlowRate(final SpacecraftState s, final double[] parameters) {
155 return -control3DVectorCostType.evaluate(getThrustVector(s, parameters)) / ThrustPropulsionModel.getExhaustVelocity(isp);
156 }
157
158
159 @Override
160 public Vector3D getThrustVector(final SpacecraftState s, final double[] parameters) {
161 final ThrustVectorProvider active = getActiveProvider(s.getDate());
162 return active == null ? Vector3D.ZERO : active.getThrustVector(s.getDate(), s.getMass());
163 }
164
165
166 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getThrustVector(final FieldSpacecraftState<T> s,
167 final T[] parameters) {
168 final ThrustVectorProvider active = getActiveProvider(s.getDate().toAbsoluteDate());
169 return active == null ? FieldVector3D.getZero(s.getDate().getField()) :
170 active.getThrustVector(s.getDate(), s.getMass());
171 }
172
173
174 public <T extends CalculusFieldElement<T>> T getFlowRate(final FieldSpacecraftState<T> s, final T[] parameters) {
175 return control3DVectorCostType.evaluate(getThrustVector(s, parameters)).divide(-ThrustPropulsionModel.getExhaustVelocity(isp));
176 }
177
178
179
180
181
182
183
184 @Override
185 public Stream<EventDetector> getEventDetectors() {
186
187 final List<AbsoluteDate> transitionDates = new ArrayList<>();
188 for (TimeSpanMap.Transition<ThrustVectorProvider> transition = profile.getFirstTransition();
189 transition != null;
190 transition = transition.next()) {
191 transitionDates.add(transition.getDate());
192 }
193 final DateDetector detector = getDateDetector(transitionDates.toArray(new TimeStamped[0]));
194 return Stream.of(detector);
195 }
196
197
198
199
200
201
202
203 @Override
204 public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventDetectors(final Field<T> field) {
205 final List<AbsoluteDate> transitionDates = new ArrayList<>();
206 for (TimeSpanMap.Transition<ThrustVectorProvider> transition = profile.getFirstTransition();
207 transition != null;
208 transition = transition.next()) {
209 transitionDates.add(transition.getDate());
210 }
211 final FieldDateDetector<T> detector = getFieldDateDetector(field, transitionDates.toArray(new AbsoluteDate[0]));
212 return Stream.of(detector);
213 }
214
215
216 @Override
217 public List<ParameterDriver> getParametersDrivers() {
218 return Collections.emptyList();
219 }
220 }