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 }