1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.rugged.utils;
18
19 import org.hipparchus.util.FastMath;
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.stream.Collectors;
24
25 import org.orekit.errors.OrekitException;
26 import org.orekit.frames.Frame;
27 import org.orekit.frames.Transform;
28 import org.orekit.rugged.errors.DumpManager;
29 import org.orekit.rugged.errors.RuggedException;
30 import org.orekit.rugged.errors.RuggedMessages;
31 import org.orekit.time.AbsoluteDate;
32 import org.orekit.utils.AngularDerivativesFilter;
33 import org.orekit.utils.CartesianDerivativesFilter;
34 import org.orekit.utils.ImmutableTimeStampedCache;
35 import org.orekit.utils.TimeStampedAngularCoordinates;
36 import org.orekit.utils.TimeStampedCache;
37 import org.orekit.utils.TimeStampedPVCoordinates;
38
39
40
41
42
43 public class SpacecraftToObservedBody implements Serializable {
44
45
46 private static final long serialVersionUID = 20140909L;
47
48
49 private final Frame inertialFrame;
50
51
52 private final Frame bodyFrame;
53
54
55 private final AbsoluteDate minDate;
56
57
58 private final AbsoluteDate maxDate;
59
60
61 private final double tStep;
62
63
64 private final double overshootTolerance;
65
66
67 private final List<Transform> bodyToInertial;
68
69
70 private final List<Transform> inertialToBody;
71
72
73 private final List<Transform> scToInertial;
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public SpacecraftToObservedBody(final Frame inertialFrame, final Frame bodyFrame,
94 final AbsoluteDate minDate, final AbsoluteDate maxDate, final double tStep,
95 final double overshootTolerance,
96 final List<TimeStampedPVCoordinates> positionsVelocities, final int pvInterpolationNumber,
97 final CartesianDerivativesFilter pvFilter,
98 final List<TimeStampedAngularCoordinates> quaternions, final int aInterpolationNumber,
99 final AngularDerivativesFilter aFilter)
100 throws RuggedException {
101 try {
102
103 this.inertialFrame = inertialFrame;
104 this.bodyFrame = bodyFrame;
105 this.minDate = minDate;
106 this.maxDate = maxDate;
107 this.overshootTolerance = overshootTolerance;
108
109
110 final AbsoluteDate minPVDate = positionsVelocities.get(0).getDate();
111 final AbsoluteDate maxPVDate = positionsVelocities.get(positionsVelocities.size() - 1).getDate();
112 if (minPVDate.durationFrom(minDate) > overshootTolerance) {
113 throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, minDate, minPVDate, maxPVDate);
114 }
115 if (maxDate.durationFrom(maxPVDate) > overshootTolerance) {
116 throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, maxDate, minPVDate, maxPVDate);
117 }
118
119 final AbsoluteDate minQDate = quaternions.get(0).getDate();
120 final AbsoluteDate maxQDate = quaternions.get(quaternions.size() - 1).getDate();
121 if (minQDate.durationFrom(minDate) > overshootTolerance) {
122 throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, minDate, minQDate, maxQDate);
123 }
124 if (maxDate.durationFrom(maxQDate) > overshootTolerance) {
125 throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, maxDate, minQDate, maxQDate);
126 }
127
128
129 final TimeStampedCache<TimeStampedPVCoordinates> pvCache =
130 new ImmutableTimeStampedCache<TimeStampedPVCoordinates>(pvInterpolationNumber, positionsVelocities);
131
132
133 final TimeStampedCache<TimeStampedAngularCoordinates> aCache =
134 new ImmutableTimeStampedCache<TimeStampedAngularCoordinates>(aInterpolationNumber, quaternions);
135
136 final int n = (int) FastMath.ceil(maxDate.durationFrom(minDate) / tStep);
137 this.tStep = tStep;
138 this.bodyToInertial = new ArrayList<Transform>(n);
139 this.inertialToBody = new ArrayList<Transform>(n);
140 this.scToInertial = new ArrayList<Transform>(n);
141 for (AbsoluteDate date = minDate; bodyToInertial.size() < n; date = date.shiftedBy(tStep)) {
142
143
144 final AbsoluteDate pvInterpolationDate;
145 if (date.compareTo(pvCache.getEarliest().getDate()) < 0) {
146 pvInterpolationDate = pvCache.getEarliest().getDate();
147 } else if (date.compareTo(pvCache.getLatest().getDate()) > 0) {
148 pvInterpolationDate = pvCache.getLatest().getDate();
149 } else {
150 pvInterpolationDate = date;
151 }
152 final TimeStampedPVCoordinates interpolatedPV =
153 TimeStampedPVCoordinates.interpolate(pvInterpolationDate, pvFilter,
154 pvCache.getNeighbors(pvInterpolationDate));
155 final TimeStampedPVCoordinates pv = interpolatedPV.shiftedBy(date.durationFrom(pvInterpolationDate));
156
157
158 final AbsoluteDate aInterpolationDate;
159 if (date.compareTo(aCache.getEarliest().getDate()) < 0) {
160 aInterpolationDate = aCache.getEarliest().getDate();
161 } else if (date.compareTo(aCache.getLatest().getDate()) > 0) {
162 aInterpolationDate = aCache.getLatest().getDate();
163 } else {
164 aInterpolationDate = date;
165 }
166 final TimeStampedAngularCoordinates interpolatedQuaternion =
167 TimeStampedAngularCoordinates.interpolate(aInterpolationDate, aFilter,
168 aCache.getNeighbors(aInterpolationDate).collect(Collectors.toList()));
169 final TimeStampedAngularCoordinates quaternion = interpolatedQuaternion.shiftedBy(date.durationFrom(aInterpolationDate));
170
171
172 scToInertial.add(new Transform(date,
173 new Transform(date, quaternion.revert()),
174 new Transform(date, pv)));
175
176
177 final Transform b2i = bodyFrame.getTransformTo(inertialFrame, date);
178 bodyToInertial.add(b2i);
179 inertialToBody.add(b2i.getInverse());
180
181 }
182
183 } catch (OrekitException oe) {
184 throw new RuggedException(oe, oe.getSpecifier(), oe.getParts());
185 }
186 }
187
188
189
190
191
192
193
194
195
196
197
198
199 public SpacecraftToObservedBody(final Frame inertialFrame, final Frame bodyFrame,
200 final AbsoluteDate minDate, final AbsoluteDate maxDate, final double tStep,
201 final double overshootTolerance,
202 final List<Transform> bodyToInertial, final List<Transform> scToInertial) {
203
204 this.inertialFrame = inertialFrame;
205 this.bodyFrame = bodyFrame;
206 this.minDate = minDate;
207 this.maxDate = maxDate;
208 this.tStep = tStep;
209 this.overshootTolerance = overshootTolerance;
210 this.bodyToInertial = bodyToInertial;
211 this.scToInertial = scToInertial;
212
213 this.inertialToBody = new ArrayList<Transform>(bodyToInertial.size());
214 for (final Transform b2i : bodyToInertial) {
215 inertialToBody.add(b2i.getInverse());
216 }
217
218 }
219
220
221
222
223 public Frame getInertialFrame() {
224 return inertialFrame;
225 }
226
227
228
229
230 public Frame getBodyFrame() {
231 return bodyFrame;
232 }
233
234
235
236
237 public AbsoluteDate getMinDate() {
238 return minDate;
239 }
240
241
242
243
244 public AbsoluteDate getMaxDate() {
245 return maxDate;
246 }
247
248
249
250
251 public double getTStep() {
252 return tStep;
253 }
254
255
256
257
258 public double getOvershootTolerance() {
259 return overshootTolerance;
260 }
261
262
263
264
265
266
267 public Transform getScToInertial(final AbsoluteDate date)
268 throws RuggedException {
269 return interpolate(date, scToInertial);
270 }
271
272
273
274
275
276
277 public Transform getInertialToBody(final AbsoluteDate date)
278 throws RuggedException {
279 return interpolate(date, inertialToBody);
280 }
281
282
283
284
285
286
287 public Transform getBodyToInertial(final AbsoluteDate date)
288 throws RuggedException {
289 return interpolate(date, bodyToInertial);
290 }
291
292
293
294
295
296
297
298 private Transform interpolate(final AbsoluteDate date, final List<Transform> list)
299 throws RuggedException {
300
301
302 if (!isInRange(date)) {
303 throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, date, minDate, maxDate);
304 }
305
306 final double s = date.durationFrom(list.get(0).getDate()) / tStep;
307 final int index = FastMath.max(0, FastMath.min(list.size() - 1, (int) FastMath.rint(s)));
308
309 DumpManager.dumpTransform(this, index, bodyToInertial.get(index), scToInertial.get(index));
310
311 final Transform close = list.get(index);
312 return close.shiftedBy(date.durationFrom(close.getDate()));
313
314 }
315
316
317
318
319
320 public boolean isInRange(final AbsoluteDate date) {
321 return (minDate.durationFrom(date) <= overshootTolerance) &&
322 (date.durationFrom(maxDate) <= overshootTolerance);
323 }
324
325 }