InterpolatingTransformProvider.java

  1. /* Copyright 2002-2018 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. package org.orekit.frames;

  18. import java.io.Serializable;
  19. import java.util.HashMap;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.stream.Collectors;
  23. import java.util.stream.Stream;

  24. import org.hipparchus.Field;
  25. import org.hipparchus.RealFieldElement;
  26. import org.orekit.errors.OrekitException;
  27. import org.orekit.errors.OrekitExceptionWrapper;
  28. import org.orekit.time.AbsoluteDate;
  29. import org.orekit.time.FieldAbsoluteDate;
  30. import org.orekit.utils.AngularDerivativesFilter;
  31. import org.orekit.utils.CartesianDerivativesFilter;
  32. import org.orekit.utils.GenericTimeStampedCache;

  33. /** Transform provider using thread-safe interpolation on transforms sample.
  34.  * <p>
  35.  * The interpolation is a polynomial Hermite interpolation, which
  36.  * can either use or ignore the derivatives provided by the raw
  37.  * provider. This means that simple raw providers that do not compute
  38.  * derivatives can be used, the derivatives will be added appropriately
  39.  * by the interpolation process.
  40.  * </p>
  41.  * @see GenericTimeStampedCache
  42.  * @see ShiftingTransformProvider
  43.  * @author Luc Maisonobe
  44.  */
  45. public class InterpolatingTransformProvider implements TransformProvider {

  46.     /** Serializable UID. */
  47.     private static final long serialVersionUID = 20140723L;

  48.     /** Provider for raw (non-interpolated) transforms. */
  49.     private final TransformProvider rawProvider;

  50.     /** Filter for Cartesian derivatives to use in interpolation. */
  51.     private final CartesianDerivativesFilter cFilter;

  52.     /** Filter for angular derivatives to use in interpolation. */
  53.     private final AngularDerivativesFilter aFilter;

  54.     /** Grid points time step. */
  55.     private final double step;

  56.     /** Cache for sample points. */
  57.     private final transient GenericTimeStampedCache<Transform> cache;

  58.     /** Field caches for sample points. */
  59.     // we use Object as the value of fieldCaches because despite numerous attempts,
  60.     // we could not find a way to use GenericTimeStampedCache<FieldTransform<? extends RealFieldElement<?>>
  61.     // without the compiler complaining
  62.     private final transient Map<Field<? extends RealFieldElement<?>>, Object> fieldCaches;

  63.     /** Simple constructor.
  64.      * @param rawProvider provider for raw (non-interpolated) transforms
  65.      * @param cFilter filter for derivatives from the sample to use in interpolation
  66.      * @param aFilter filter for derivatives from the sample to use in interpolation
  67.      * @param gridPoints number of interpolation grid points
  68.      * @param step grid points time step
  69.      * @param maxSlots maximum number of independent cached time slots
  70.      * in the {@link GenericTimeStampedCache time-stamped cache}
  71.      * @param maxSpan maximum duration span in seconds of one slot
  72.      * in the {@link GenericTimeStampedCache time-stamped cache}
  73.      * @param newSlotInterval time interval above which a new slot is created
  74.      * in the {@link GenericTimeStampedCache time-stamped cache}
  75.      * @since 9.1
  76.      */
  77.     public InterpolatingTransformProvider(final TransformProvider rawProvider,
  78.                                           final CartesianDerivativesFilter cFilter,
  79.                                           final AngularDerivativesFilter aFilter,
  80.                                           final int gridPoints, final double step,
  81.                                           final int maxSlots, final double maxSpan, final double newSlotInterval) {
  82.         this.rawProvider = rawProvider;
  83.         this.cFilter     = cFilter;
  84.         this.aFilter     = aFilter;
  85.         this.step        = step;
  86.         this.cache       = new GenericTimeStampedCache<Transform>(gridPoints, maxSlots, maxSpan, newSlotInterval,
  87.                                                                   new TransformGenerator(gridPoints,
  88.                                                                                          rawProvider,
  89.                                                                                          step));
  90.         this.fieldCaches = new HashMap<>();
  91.     }

  92.     /** Simple constructor.
  93.      * @param rawProvider provider for raw (non-interpolated) transforms
  94.      * @param cFilter filter for derivatives from the sample to use in interpolation
  95.      * @param aFilter filter for derivatives from the sample to use in interpolation
  96.      * @param earliest was earliest supported date, but is ignored now and can safely be null
  97.      * @param latest was latest supported date, but is ignored now and can safely be null
  98.      * @param gridPoints number of interpolation grid points
  99.      * @param step grid points time step
  100.      * @param maxSlots maximum number of independent cached time slots
  101.      * in the {@link GenericTimeStampedCache time-stamped cache}
  102.      * @param maxSpan maximum duration span in seconds of one slot
  103.      * in the {@link GenericTimeStampedCache time-stamped cache}
  104.      * @param newSlotInterval time interval above which a new slot is created
  105.      * in the {@link GenericTimeStampedCache time-stamped cache}
  106.      * @deprecated as of 9.1, replaced by {@link #InterpolatingTransformProvider(TransformProvider,
  107.      * CartesianDerivativesFilter, AngularDerivativesFilter, int, double, int, double, double)}
  108.      */
  109.     @Deprecated
  110.     public InterpolatingTransformProvider(final TransformProvider rawProvider,
  111.                                           final CartesianDerivativesFilter cFilter,
  112.                                           final AngularDerivativesFilter aFilter,
  113.                                           final AbsoluteDate earliest, final AbsoluteDate latest,
  114.                                           final int gridPoints, final double step,
  115.                                           final int maxSlots, final double maxSpan, final double newSlotInterval) {
  116.         this(rawProvider, cFilter, aFilter, gridPoints, step, maxSlots, maxSpan, newSlotInterval);
  117.     }

  118.     /** Get the underlying provider for raw (non-interpolated) transforms.
  119.      * @return provider for raw (non-interpolated) transforms
  120.      */
  121.     public TransformProvider getRawProvider() {
  122.         return rawProvider;
  123.     }

  124.     /** Get the number of interpolation grid points.
  125.      * @return number of interpolation grid points
  126.      */
  127.     public int getGridPoints() {
  128.         return cache.getNeighborsSize();
  129.     }

  130.     /** Get the grid points time step.
  131.      * @return grid points time step
  132.      */
  133.     public double getStep() {
  134.         return step;
  135.     }

  136.     /** {@inheritDoc} */
  137.     @Override
  138.     public Transform getTransform(final AbsoluteDate date) throws OrekitException {
  139.         try {

  140.             // retrieve a sample from the thread-safe cache
  141.             final List<Transform> sample = cache.getNeighbors(date).collect(Collectors.toList());

  142.             // interpolate to specified date
  143.             return Transform.interpolate(date, cFilter, aFilter, sample);

  144.         } catch (OrekitExceptionWrapper oew) {
  145.             // something went wrong while generating the sample,
  146.             // we just forward the exception up
  147.             throw oew.getException();
  148.         }
  149.     }

  150.     /** {@inheritDoc} */
  151.     @Override
  152.     public <T extends RealFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date)
  153.         throws OrekitException {
  154.         try {

  155.             @SuppressWarnings("unchecked")
  156.             GenericTimeStampedCache<FieldTransform<T>> fieldCache =
  157.                 (GenericTimeStampedCache<FieldTransform<T>>) fieldCaches.get(date.getField());
  158.             if (fieldCache == null) {
  159.                 fieldCache =
  160.                     new GenericTimeStampedCache<FieldTransform<T>>(cache.getNeighborsSize(),
  161.                                                                    cache.getMaxSlots(),
  162.                                                                    cache.getMaxSpan(),
  163.                                                                    cache.getNewSlotQuantumGap(),
  164.                                                                    new FieldTransformGenerator<>(date.getField(),
  165.                                                                                                  cache.getNeighborsSize(),
  166.                                                                                                  rawProvider,
  167.                                                                                                  step));
  168.                 fieldCaches.put(date.getField(), fieldCache);
  169.             }

  170.             // retrieve a sample from the thread-safe cache
  171.             final Stream<FieldTransform<T>> sample = fieldCache.getNeighbors(date.toAbsoluteDate());

  172.             // interpolate to specified date
  173.             return FieldTransform.interpolate(date, cFilter, aFilter, sample);

  174.         } catch (OrekitExceptionWrapper oew) {
  175.             // something went wrong while generating the sample,
  176.             // we just forward the exception up
  177.             throw oew.getException();
  178.         }
  179.     }

  180.     /** Replace the instance with a data transfer object for serialization.
  181.      * <p>
  182.      * This intermediate class serializes only the data needed for generation,
  183.      * but does <em>not</em> serializes the cache itself (in fact the cache is
  184.      * not serializable).
  185.      * </p>
  186.      * @return data transfer object that will be serialized
  187.      */
  188.     private Object writeReplace() {
  189.         return new DTO(rawProvider, cFilter.getMaxOrder(), aFilter.getMaxOrder(),
  190.                        cache.getNeighborsSize(), step,
  191.                        cache.getMaxSlots(), cache.getMaxSpan(), cache.getNewSlotQuantumGap());
  192.     }

  193.     /** Internal class used only for serialization. */
  194.     private static class DTO implements Serializable {

  195.         /** Serializable UID. */
  196.         private static final long serialVersionUID = 20170823L;

  197.         /** Provider for raw (non-interpolated) transforms. */
  198.         private final TransformProvider rawProvider;

  199.         /** Cartesian derivatives to use in interpolation. */
  200.         private final int cDerivatives;

  201.         /** Angular derivatives to use in interpolation. */
  202.         private final int aDerivatives;

  203.         /** Number of grid points. */
  204.         private final int gridPoints;

  205.         /** Grid points time step. */
  206.         private final double step;

  207.         /** Maximum number of independent cached time slots. */
  208.         private final int maxSlots;

  209.         /** Maximum duration span in seconds of one slot. */
  210.         private final double maxSpan;

  211.         /** Time interval above which a new slot is created. */
  212.         private final double newSlotInterval;

  213.         /** Simple constructor.
  214.          * @param rawProvider provider for raw (non-interpolated) transforms
  215.          * @param cDerivatives derivation order for Cartesian coordinates
  216.          * @param aDerivatives derivation order for angular coordinates
  217.          * @param gridPoints number of interpolation grid points
  218.          * @param step grid points time step
  219.          * @param maxSlots maximum number of independent cached time slots
  220.          * in the {@link GenericTimeStampedCache time-stamped cache}
  221.          * @param maxSpan maximum duration span in seconds of one slot
  222.          * in the {@link GenericTimeStampedCache time-stamped cache}
  223.          * @param newSlotInterval time interval above which a new slot is created
  224.          * in the {@link GenericTimeStampedCache time-stamped cache}
  225.          */
  226.         private DTO(final TransformProvider rawProvider, final int cDerivatives, final int aDerivatives,
  227.                     final int gridPoints, final double step,
  228.                     final int maxSlots, final double maxSpan, final double newSlotInterval) {
  229.             this.rawProvider     = rawProvider;
  230.             this.cDerivatives    = cDerivatives;
  231.             this.aDerivatives    = aDerivatives;
  232.             this.gridPoints      = gridPoints;
  233.             this.step            = step;
  234.             this.maxSlots        = maxSlots;
  235.             this.maxSpan         = maxSpan;
  236.             this.newSlotInterval = newSlotInterval;
  237.         }

  238.         /** Replace the deserialized data transfer object with a {@link InterpolatingTransformProvider}.
  239.          * @return replacement {@link InterpolatingTransformProvider}
  240.          */
  241.         private Object readResolve() {
  242.             // build a new provider, with an empty cache
  243.             return new InterpolatingTransformProvider(rawProvider,
  244.                                                       CartesianDerivativesFilter.getFilter(cDerivatives),
  245.                                                       AngularDerivativesFilter.getFilter(aDerivatives),
  246.                                                       gridPoints, step,
  247.                                                       maxSlots, maxSpan, newSlotInterval);
  248.         }

  249.     }

  250. }