1 /* Copyright 2002-2015 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 * @author Luc Maisonobe
42 */
43 public class InterpolatingTransformProvider implements TransformProvider {
44
45 /** Serializable UID. */
46 private static final long serialVersionUID = 20140723L;
47
48 /** Provider for raw (non-interpolated) transforms. */
49 private final TransformProvider rawProvider;
50
51 /** Filter for Cartesian derivatives to use in interpolation. */
52 private final CartesianDerivativesFilter cFilter;
53
54 /** Filter for angular derivatives to use in interpolation. */
55 private final AngularDerivativesFilter aFilter;
56
57 /** Earliest supported date. */
58 private final AbsoluteDate earliest;
59
60 /** Latest supported date. */
61 private final AbsoluteDate latest;
62
63 /** Grid points time step. */
64 private final double step;
65
66 /** Cache for sample points. */
67 private final transient GenericTimeStampedCache<Transform> cache;
68
69 /** Simple constructor.
70 * @param rawProvider provider for raw (non-interpolated) transforms
71 * @param useVelocities if true, use sample transforms velocities,
72 * otherwise ignore them and use only positions
73 * @param useRotationRates if true, use sample points rotation rates,
74 * otherwise ignore them and use only rotations
75 * @param earliest earliest supported date
76 * @param latest latest supported date
77 * @param gridPoints number of interpolation grid points
78 * @param step grid points time step
79 * @param maxSlots maximum number of independent cached time slots
80 * in the {@link GenericTimeStampedCache time-stamped cache}
81 * @param maxSpan maximum duration span in seconds of one slot
82 * in the {@link GenericTimeStampedCache time-stamped cache}
83 * @param newSlotInterval time interval above which a new slot is created
84 * in the {@link GenericTimeStampedCache time-stamped cache}
85 * @deprecated as of 7.0, replaced with {@link #InterpolatingTransformProvider(TransformProvider,
86 * CartesianDerivativesFilter, AngularDerivativesFilter, AbsoluteDate, AbsoluteDate,
87 * int, double, int, double, double)}
88 */
89 @Deprecated
90 public InterpolatingTransformProvider(final TransformProvider rawProvider,
91 final boolean useVelocities, final boolean useRotationRates,
92 final AbsoluteDate earliest, final AbsoluteDate latest,
93 final int gridPoints, final double step,
94 final int maxSlots, final double maxSpan, final double newSlotInterval) {
95 this(rawProvider,
96 useVelocities ? CartesianDerivativesFilter.USE_PV : CartesianDerivativesFilter.USE_P,
97 useRotationRates ? AngularDerivativesFilter.USE_RR : AngularDerivativesFilter.USE_R,
98 earliest, latest, gridPoints, step, maxSlots, maxSpan, newSlotInterval);
99 }
100
101 /** Simple constructor.
102 * @param rawProvider provider for raw (non-interpolated) transforms
103 * @param cFilter filter for derivatives from the sample to use in interpolation
104 * @param aFilter filter for derivatives from the sample to use in interpolation
105 * @param earliest earliest supported date
106 * @param latest latest supported date
107 * @param gridPoints number of interpolation grid points
108 * @param step grid points time step
109 * @param maxSlots maximum number of independent cached time slots
110 * in the {@link GenericTimeStampedCache time-stamped cache}
111 * @param maxSpan maximum duration span in seconds of one slot
112 * in the {@link GenericTimeStampedCache time-stamped cache}
113 * @param newSlotInterval time interval above which a new slot is created
114 * in the {@link GenericTimeStampedCache time-stamped cache}
115 */
116 public InterpolatingTransformProvider(final TransformProvider rawProvider,
117 final CartesianDerivativesFilter cFilter,
118 final AngularDerivativesFilter aFilter,
119 final AbsoluteDate earliest, final AbsoluteDate latest,
120 final int gridPoints, final double step,
121 final int maxSlots, final double maxSpan, final double newSlotInterval) {
122 this.rawProvider = rawProvider;
123 this.cFilter = cFilter;
124 this.aFilter = aFilter;
125 this.earliest = earliest;
126 this.latest = latest;
127 this.step = step;
128 this.cache = new GenericTimeStampedCache<Transform>(gridPoints, maxSlots, maxSpan, newSlotInterval,
129 new Generator(), Transform.class);
130 }
131
132 /** Get the underlying provider for raw (non-interpolated) transforms.
133 * @return provider for raw (non-interpolated) transforms
134 */
135 public TransformProvider getRawProvider() {
136 return rawProvider;
137 }
138
139 /** Get the number of interpolation grid points.
140 * @return number of interpolation grid points
141 */
142 public int getGridPoints() {
143 return cache.getNeighborsSize();
144 }
145
146 /** Get the grid points time step.
147 * @return grid points time step
148 */
149 public double getStep() {
150 return step;
151 }
152
153 /** {@inheritDoc} */
154 public Transform getTransform(final AbsoluteDate date) throws OrekitException {
155 try {
156
157 // retrieve a sample from the thread-safe cache
158 final List<Transform> sample = cache.getNeighbors(date);
159
160 // interpolate to specified date
161 return Transform.interpolate(date, cFilter, aFilter, sample);
162
163 } catch (OrekitExceptionWrapper oew) {
164 // something went wrong while generating the sample,
165 // we just forward the exception up
166 throw oew.getException();
167 }
168 }
169
170 /** Replace the instance with a data transfer object for serialization.
171 * <p>
172 * This intermediate class serializes only the data needed for generation,
173 * but does <em>not</em> serializes the cache itself (in fact the cache is
174 * not serializable).
175 * </p>
176 * @return data transfer object that will be serialized
177 */
178 private Object writeReplace() {
179 return new DTO(rawProvider, cFilter.getMaxOrder(), aFilter.getMaxOrder(),
180 earliest, latest, cache.getNeighborsSize(), step,
181 cache.getMaxSlots(), cache.getMaxSpan(), cache.getNewSlotQuantumGap());
182 }
183
184 /** Internal class used only for serialization. */
185 private static class DTO implements Serializable {
186
187 /** Serializable UID. */
188 private static final long serialVersionUID = 20140723L;
189
190 /** Provider for raw (non-interpolated) transforms. */
191 private final TransformProvider rawProvider;
192
193 /** Cartesian derivatives to use in interpolation. */
194 private final int cDerivatives;
195
196 /** Angular derivatives to use in interpolation. */
197 private final int aDerivatives;
198
199 /** Earliest supported date. */
200 private final AbsoluteDate earliest;
201
202 /** Latest supported date. */
203 private final AbsoluteDate latest;
204
205 /** Number of grid points. */
206 private final int gridPoints;
207
208 /** Grid points time step. */
209 private final double step;
210
211 /** Maximum number of independent cached time slots. */
212 private final int maxSlots;
213
214 /** Maximum duration span in seconds of one slot. */
215 private final double maxSpan;
216
217 /** Time interval above which a new slot is created. */
218 private final double newSlotInterval;
219
220 /** Simple constructor.
221 * @param rawProvider provider for raw (non-interpolated) transforms
222 * @param cDerivatives derivation order for Cartesian coordinates
223 * @param aDerivatives derivation order for angular coordinates
224 * @param earliest earliest supported date
225 * @param latest latest supported date
226 * @param gridPoints number of interpolation grid points
227 * @param step grid points time step
228 * @param maxSlots maximum number of independent cached time slots
229 * in the {@link GenericTimeStampedCache time-stamped cache}
230 * @param maxSpan maximum duration span in seconds of one slot
231 * in the {@link GenericTimeStampedCache time-stamped cache}
232 * @param newSlotInterval time interval above which a new slot is created
233 * in the {@link GenericTimeStampedCache time-stamped cache}
234 */
235 private DTO(final TransformProvider rawProvider, final int cDerivatives, final int aDerivatives,
236 final AbsoluteDate earliest, final AbsoluteDate latest,
237 final int gridPoints, final double step,
238 final int maxSlots, final double maxSpan, final double newSlotInterval) {
239 this.rawProvider = rawProvider;
240 this.cDerivatives = cDerivatives;
241 this.aDerivatives = aDerivatives;
242 this.earliest = earliest;
243 this.latest = latest;
244 this.gridPoints = gridPoints;
245 this.step = step;
246 this.maxSlots = maxSlots;
247 this.maxSpan = maxSpan;
248 this.newSlotInterval = newSlotInterval;
249 }
250
251 /** Replace the deserialized data transfer object with a {@link InterpolatingTransformProvider}.
252 * @return replacement {@link InterpolatingTransformProvider}
253 */
254 private Object readResolve() {
255 // build a new provider, with an empty cache
256 return new InterpolatingTransformProvider(rawProvider,
257 CartesianDerivativesFilter.getFilter(cDerivatives),
258 AngularDerivativesFilter.getFilter(aDerivatives),
259 earliest, latest, gridPoints, step,
260 maxSlots, maxSpan, newSlotInterval);
261 }
262
263 }
264
265 /** Local generator for thread-safe cache. */
266 private class Generator implements TimeStampedGenerator<Transform> {
267
268 /** {@inheritDoc} */
269 public List<Transform> generate(final Transform existing, final AbsoluteDate date) {
270
271 try {
272 final List<Transform> generated = new ArrayList<Transform>();
273
274 if (existing == null) {
275
276 // no prior existing transforms, just generate a first set
277 for (int i = 0; i < cache.getNeighborsSize(); ++i) {
278 generated.add(rawProvider.getTransform(date.shiftedBy(i * step)));
279 }
280
281 } else {
282
283 // some transforms have already been generated
284 // add the missing ones up to specified date
285
286 AbsoluteDate t = existing.getDate();
287 if (date.compareTo(t) > 0) {
288 // forward generation
289 do {
290 t = t.shiftedBy(step);
291 generated.add(generated.size(), rawProvider.getTransform(t));
292 } while (t.compareTo(date) <= 0);
293 } else {
294 // backward generation
295 do {
296 t = t.shiftedBy(-step);
297 generated.add(0, rawProvider.getTransform(t));
298 } while (t.compareTo(date) >= 0);
299 }
300 }
301
302 // return the generated transforms
303 return generated;
304 } catch (OrekitException oe) {
305 throw new OrekitExceptionWrapper(oe);
306 }
307
308 }
309
310 }
311
312 }