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 }