1 /* Copyright 2002-2016 CS Systèmes d'Information
2 * Licensed to CS Systèmes d'Information (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.orekit.frames;
19
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitExceptionWrapper;
26 import org.orekit.time.AbsoluteDate;
27 import org.orekit.utils.AngularDerivativesFilter;
28 import org.orekit.utils.CartesianDerivativesFilter;
29 import org.orekit.utils.GenericTimeStampedCache;
30 import org.orekit.utils.TimeStampedGenerator;
31
32 /** Transform provider using thread-safe interpolation on transforms sample.
33 * <p>
34 * The interpolation is a polynomial Hermite interpolation, which
35 * can either use or ignore the derivatives provided by the raw
36 * provider. This means that simple raw providers that do not compute
37 * derivatives can be used, the derivatives will be added appropriately
38 * by the interpolation process.
39 * </p>
40 * @see GenericTimeStampedCache
41 * @see ShiftingTransformProvider
42 * @author Luc Maisonobe
43 */
44 public class InterpolatingTransformProvider implements TransformProvider {
45
46 /** Serializable UID. */
47 private static final long serialVersionUID = 20140723L;
48
49 /** Provider for raw (non-interpolated) transforms. */
50 private final TransformProvider rawProvider;
51
52 /** Filter for Cartesian derivatives to use in interpolation. */
53 private final CartesianDerivativesFilter cFilter;
54
55 /** Filter for angular derivatives to use in interpolation. */
56 private final AngularDerivativesFilter aFilter;
57
58 /** Earliest supported date. */
59 private final AbsoluteDate earliest;
60
61 /** Latest supported date. */
62 private final AbsoluteDate latest;
63
64 /** Grid points time step. */
65 private final double step;
66
67 /** Cache for sample points. */
68 private final transient GenericTimeStampedCache<Transform> cache;
69
70 /** Simple constructor.
71 * @param rawProvider provider for raw (non-interpolated) transforms
72 * @param useVelocities if true, use sample transforms velocities,
73 * otherwise ignore them and use only positions
74 * @param useRotationRates if true, use sample points rotation rates,
75 * otherwise ignore them and use only rotations
76 * @param earliest earliest supported date
77 * @param latest latest supported date
78 * @param gridPoints number of interpolation grid points
79 * @param step grid points time step
80 * @param maxSlots maximum number of independent cached time slots
81 * in the {@link GenericTimeStampedCache time-stamped cache}
82 * @param maxSpan maximum duration span in seconds of one slot
83 * in the {@link GenericTimeStampedCache time-stamped cache}
84 * @param newSlotInterval time interval above which a new slot is created
85 * in the {@link GenericTimeStampedCache time-stamped cache}
86 * @deprecated as of 7.0, replaced with {@link #InterpolatingTransformProvider(TransformProvider,
87 * CartesianDerivativesFilter, AngularDerivativesFilter, AbsoluteDate, AbsoluteDate,
88 * int, double, int, double, double)}
89 */
90 @Deprecated
91 public InterpolatingTransformProvider(final TransformProvider rawProvider,
92 final boolean useVelocities, final boolean useRotationRates,
93 final AbsoluteDate earliest, final AbsoluteDate latest,
94 final int gridPoints, final double step,
95 final int maxSlots, final double maxSpan, final double newSlotInterval) {
96 this(rawProvider,
97 useVelocities ? CartesianDerivativesFilter.USE_PV : CartesianDerivativesFilter.USE_P,
98 useRotationRates ? AngularDerivativesFilter.USE_RR : AngularDerivativesFilter.USE_R,
99 earliest, latest, gridPoints, step, maxSlots, maxSpan, newSlotInterval);
100 }
101
102 /** Simple constructor.
103 * @param rawProvider provider for raw (non-interpolated) transforms
104 * @param cFilter filter for derivatives from the sample to use in interpolation
105 * @param aFilter filter for derivatives from the sample to use in interpolation
106 * @param earliest earliest supported date
107 * @param latest latest supported date
108 * @param gridPoints number of interpolation grid points
109 * @param step grid points time step
110 * @param maxSlots maximum number of independent cached time slots
111 * in the {@link GenericTimeStampedCache time-stamped cache}
112 * @param maxSpan maximum duration span in seconds of one slot
113 * in the {@link GenericTimeStampedCache time-stamped cache}
114 * @param newSlotInterval time interval above which a new slot is created
115 * in the {@link GenericTimeStampedCache time-stamped cache}
116 */
117 public InterpolatingTransformProvider(final TransformProvider rawProvider,
118 final CartesianDerivativesFilter cFilter,
119 final AngularDerivativesFilter aFilter,
120 final AbsoluteDate earliest, final AbsoluteDate latest,
121 final int gridPoints, final double step,
122 final int maxSlots, final double maxSpan, final double newSlotInterval) {
123 this.rawProvider = rawProvider;
124 this.cFilter = cFilter;
125 this.aFilter = aFilter;
126 this.earliest = earliest;
127 this.latest = latest;
128 this.step = step;
129 this.cache = new GenericTimeStampedCache<Transform>(gridPoints, maxSlots, maxSpan, newSlotInterval,
130 new Generator(), Transform.class);
131 }
132
133 /** Get the underlying provider for raw (non-interpolated) transforms.
134 * @return provider for raw (non-interpolated) transforms
135 */
136 public TransformProvider getRawProvider() {
137 return rawProvider;
138 }
139
140 /** Get the number of interpolation grid points.
141 * @return number of interpolation grid points
142 */
143 public int getGridPoints() {
144 return cache.getNeighborsSize();
145 }
146
147 /** Get the grid points time step.
148 * @return grid points time step
149 */
150 public double getStep() {
151 return step;
152 }
153
154 /** {@inheritDoc} */
155 public Transform getTransform(final AbsoluteDate date) throws OrekitException {
156 try {
157
158 // retrieve a sample from the thread-safe cache
159 final List<Transform> sample = cache.getNeighbors(date);
160
161 // interpolate to specified date
162 return Transform.interpolate(date, cFilter, aFilter, sample);
163
164 } catch (OrekitExceptionWrapper oew) {
165 // something went wrong while generating the sample,
166 // we just forward the exception up
167 throw oew.getException();
168 }
169 }
170
171 /** Replace the instance with a data transfer object for serialization.
172 * <p>
173 * This intermediate class serializes only the data needed for generation,
174 * but does <em>not</em> serializes the cache itself (in fact the cache is
175 * not serializable).
176 * </p>
177 * @return data transfer object that will be serialized
178 */
179 private Object writeReplace() {
180 return new DTO(rawProvider, cFilter.getMaxOrder(), aFilter.getMaxOrder(),
181 earliest, latest, cache.getNeighborsSize(), step,
182 cache.getMaxSlots(), cache.getMaxSpan(), cache.getNewSlotQuantumGap());
183 }
184
185 /** Internal class used only for serialization. */
186 private static class DTO implements Serializable {
187
188 /** Serializable UID. */
189 private static final long serialVersionUID = 20140723L;
190
191 /** Provider for raw (non-interpolated) transforms. */
192 private final TransformProvider rawProvider;
193
194 /** Cartesian derivatives to use in interpolation. */
195 private final int cDerivatives;
196
197 /** Angular derivatives to use in interpolation. */
198 private final int aDerivatives;
199
200 /** Earliest supported date. */
201 private final AbsoluteDate earliest;
202
203 /** Latest supported date. */
204 private final AbsoluteDate latest;
205
206 /** Number of grid points. */
207 private final int gridPoints;
208
209 /** Grid points time step. */
210 private final double step;
211
212 /** Maximum number of independent cached time slots. */
213 private final int maxSlots;
214
215 /** Maximum duration span in seconds of one slot. */
216 private final double maxSpan;
217
218 /** Time interval above which a new slot is created. */
219 private final double newSlotInterval;
220
221 /** Simple constructor.
222 * @param rawProvider provider for raw (non-interpolated) transforms
223 * @param cDerivatives derivation order for Cartesian coordinates
224 * @param aDerivatives derivation order for angular coordinates
225 * @param earliest earliest supported date
226 * @param latest latest supported date
227 * @param gridPoints number of interpolation grid points
228 * @param step grid points time step
229 * @param maxSlots maximum number of independent cached time slots
230 * in the {@link GenericTimeStampedCache time-stamped cache}
231 * @param maxSpan maximum duration span in seconds of one slot
232 * in the {@link GenericTimeStampedCache time-stamped cache}
233 * @param newSlotInterval time interval above which a new slot is created
234 * in the {@link GenericTimeStampedCache time-stamped cache}
235 */
236 private DTO(final TransformProvider rawProvider, final int cDerivatives, final int aDerivatives,
237 final AbsoluteDate earliest, final AbsoluteDate latest,
238 final int gridPoints, final double step,
239 final int maxSlots, final double maxSpan, final double newSlotInterval) {
240 this.rawProvider = rawProvider;
241 this.cDerivatives = cDerivatives;
242 this.aDerivatives = aDerivatives;
243 this.earliest = earliest;
244 this.latest = latest;
245 this.gridPoints = gridPoints;
246 this.step = step;
247 this.maxSlots = maxSlots;
248 this.maxSpan = maxSpan;
249 this.newSlotInterval = newSlotInterval;
250 }
251
252 /** Replace the deserialized data transfer object with a {@link InterpolatingTransformProvider}.
253 * @return replacement {@link InterpolatingTransformProvider}
254 */
255 private Object readResolve() {
256 // build a new provider, with an empty cache
257 return new InterpolatingTransformProvider(rawProvider,
258 CartesianDerivativesFilter.getFilter(cDerivatives),
259 AngularDerivativesFilter.getFilter(aDerivatives),
260 earliest, latest, gridPoints, step,
261 maxSlots, maxSpan, newSlotInterval);
262 }
263
264 }
265
266 /** Local generator for thread-safe cache. */
267 private class Generator implements TimeStampedGenerator<Transform> {
268
269 /** {@inheritDoc} */
270 public List<Transform> generate(final Transform existing, final AbsoluteDate date) {
271
272 try {
273 final List<Transform> generated = new ArrayList<Transform>();
274
275 if (existing == null) {
276
277 // no prior existing transforms, just generate a first set
278 for (int i = 0; i < cache.getNeighborsSize(); ++i) {
279 generated.add(rawProvider.getTransform(date.shiftedBy(i * step)));
280 }
281
282 } else {
283
284 // some transforms have already been generated
285 // add the missing ones up to specified date
286
287 AbsoluteDate t = existing.getDate();
288 if (date.compareTo(t) > 0) {
289 // forward generation
290 do {
291 t = t.shiftedBy(step);
292 generated.add(generated.size(), rawProvider.getTransform(t));
293 } while (t.compareTo(date) <= 0);
294 } else {
295 // backward generation
296 do {
297 t = t.shiftedBy(-step);
298 generated.add(0, rawProvider.getTransform(t));
299 } while (t.compareTo(date) >= 0);
300 }
301 }
302
303 // return the generated transforms
304 return generated;
305 } catch (OrekitException oe) {
306 throw new OrekitExceptionWrapper(oe);
307 }
308
309 }
310
311 }
312
313 }