InterpolatingTransformProvider.java

  1. /* Copyright 2002-2022 CS GROUP
  2.  * Licensed to CS GROUP (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.CalculusFieldElement;
  26. import org.orekit.time.AbsoluteDate;
  27. import org.orekit.time.FieldAbsoluteDate;
  28. import org.orekit.utils.AngularDerivativesFilter;
  29. import org.orekit.utils.CartesianDerivativesFilter;
  30. import org.orekit.utils.GenericTimeStampedCache;

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

  44.     /** Serializable UID. */
  45.     private static final long serialVersionUID = 20140723L;

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

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

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

  52.     /** Grid points time step. */
  53.     private final double step;

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

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

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

  90.     /** Get the underlying provider for raw (non-interpolated) transforms.
  91.      * @return provider for raw (non-interpolated) transforms
  92.      */
  93.     public TransformProvider getRawProvider() {
  94.         return rawProvider;
  95.     }

  96.     /** Get the number of interpolation grid points.
  97.      * @return number of interpolation grid points
  98.      */
  99.     public int getGridPoints() {
  100.         return cache.getNeighborsSize();
  101.     }

  102.     /** Get the grid points time step.
  103.      * @return grid points time step
  104.      */
  105.     public double getStep() {
  106.         return step;
  107.     }

  108.     /** {@inheritDoc} */
  109.     @Override
  110.     public Transform getTransform(final AbsoluteDate date) {
  111.         // retrieve a sample from the thread-safe cache
  112.         final List<Transform> sample = cache.getNeighbors(date).collect(Collectors.toList());

  113.         // interpolate to specified date
  114.         return Transform.interpolate(date, cFilter, aFilter, sample);
  115.     }

  116.     /** {@inheritDoc} */
  117.     @Override
  118.     public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
  119.         @SuppressWarnings("unchecked")
  120.         GenericTimeStampedCache<FieldTransform<T>> fieldCache =
  121.             (GenericTimeStampedCache<FieldTransform<T>>) fieldCaches.get(date.getField());
  122.         if (fieldCache == null) {
  123.             fieldCache =
  124.                 new GenericTimeStampedCache<FieldTransform<T>>(cache.getNeighborsSize(),
  125.                                                                cache.getMaxSlots(),
  126.                                                                cache.getMaxSpan(),
  127.                                                                cache.getNewSlotQuantumGap(),
  128.                                                                new FieldTransformGenerator<>(date.getField(),
  129.                                                                                              cache.getNeighborsSize(),
  130.                                                                                              rawProvider,
  131.                                                                                              step));
  132.             fieldCaches.put(date.getField(), fieldCache);
  133.         }

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

  136.         // interpolate to specified date
  137.         return FieldTransform.interpolate(date, cFilter, aFilter, sample);
  138.     }

  139.     /** Replace the instance with a data transfer object for serialization.
  140.      * <p>
  141.      * This intermediate class serializes only the data needed for generation,
  142.      * but does <em>not</em> serializes the cache itself (in fact the cache is
  143.      * not serializable).
  144.      * </p>
  145.      * @return data transfer object that will be serialized
  146.      */
  147.     private Object writeReplace() {
  148.         return new DTO(rawProvider, cFilter.getMaxOrder(), aFilter.getMaxOrder(),
  149.                        cache.getNeighborsSize(), step,
  150.                        cache.getMaxSlots(), cache.getMaxSpan(), cache.getNewSlotQuantumGap());
  151.     }

  152.     /** Internal class used only for serialization. */
  153.     private static class DTO implements Serializable {

  154.         /** Serializable UID. */
  155.         private static final long serialVersionUID = 20170823L;

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

  158.         /** Cartesian derivatives to use in interpolation. */
  159.         private final int cDerivatives;

  160.         /** Angular derivatives to use in interpolation. */
  161.         private final int aDerivatives;

  162.         /** Number of grid points. */
  163.         private final int gridPoints;

  164.         /** Grid points time step. */
  165.         private final double step;

  166.         /** Maximum number of independent cached time slots. */
  167.         private final int maxSlots;

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

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

  172.         /** Simple constructor.
  173.          * @param rawProvider provider for raw (non-interpolated) transforms
  174.          * @param cDerivatives derivation order for Cartesian coordinates
  175.          * @param aDerivatives derivation order for angular coordinates
  176.          * @param gridPoints number of interpolation grid points
  177.          * @param step grid points time step
  178.          * @param maxSlots maximum number of independent cached time slots
  179.          * in the {@link GenericTimeStampedCache time-stamped cache}
  180.          * @param maxSpan maximum duration span in seconds of one slot
  181.          * in the {@link GenericTimeStampedCache time-stamped cache}
  182.          * @param newSlotInterval time interval above which a new slot is created
  183.          * in the {@link GenericTimeStampedCache time-stamped cache}
  184.          */
  185.         private DTO(final TransformProvider rawProvider, final int cDerivatives, final int aDerivatives,
  186.                     final int gridPoints, final double step,
  187.                     final int maxSlots, final double maxSpan, final double newSlotInterval) {
  188.             this.rawProvider     = rawProvider;
  189.             this.cDerivatives    = cDerivatives;
  190.             this.aDerivatives    = aDerivatives;
  191.             this.gridPoints      = gridPoints;
  192.             this.step            = step;
  193.             this.maxSlots        = maxSlots;
  194.             this.maxSpan         = maxSpan;
  195.             this.newSlotInterval = newSlotInterval;
  196.         }

  197.         /** Replace the deserialized data transfer object with a {@link InterpolatingTransformProvider}.
  198.          * @return replacement {@link InterpolatingTransformProvider}
  199.          */
  200.         private Object readResolve() {
  201.             // build a new provider, with an empty cache
  202.             return new InterpolatingTransformProvider(rawProvider,
  203.                                                       CartesianDerivativesFilter.getFilter(cDerivatives),
  204.                                                       AngularDerivativesFilter.getFilter(aDerivatives),
  205.                                                       gridPoints, step,
  206.                                                       maxSlots, maxSpan, newSlotInterval);
  207.         }

  208.     }

  209. }