ShiftingTransformProvider.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.Map;

  21. import org.hipparchus.Field;
  22. import org.hipparchus.RealFieldElement;
  23. import org.hipparchus.util.FastMath;
  24. import org.orekit.errors.OrekitException;
  25. import org.orekit.errors.OrekitExceptionWrapper;
  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 shifts on transforms sample.
  32.  * <p>
  33.  * The shifts take derivatives into account, up to user specified order.
  34.  * </p>
  35.  * @see GenericTimeStampedCache
  36.  * @see InterpolatingTransformProvider
  37.  * @since 7.1
  38.  * @author Luc Maisonobe
  39.  */
  40. public class ShiftingTransformProvider implements TransformProvider {

  41.     /** Serializable UID. */
  42.     private static final long serialVersionUID = 20150601L;

  43.     /** First level cache. */
  44.     private final InterpolatingTransformProvider interpolatingProvider;

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

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

  52.     /** Simple constructor.
  53.      * @param rawProvider provider for raw (non-interpolated) transforms
  54.      * @param cFilter filter for derivatives from the sample to use in interpolation
  55.      * @param aFilter filter for derivatives from the sample to use in interpolation
  56.      * @param gridPoints number of interpolation grid points
  57.      * @param step grid points time step
  58.      * @param maxSlots maximum number of independent cached time slots
  59.      * in the {@link GenericTimeStampedCache time-stamped cache}
  60.      * @param maxSpan maximum duration span in seconds of one slot
  61.      * in the {@link GenericTimeStampedCache time-stamped cache}
  62.      * @param newSlotInterval time interval above which a new slot is created
  63.      * in the {@link GenericTimeStampedCache time-stamped cache}
  64.      * @since 9.1
  65.      */
  66.     public ShiftingTransformProvider(final TransformProvider rawProvider,
  67.                                      final CartesianDerivativesFilter cFilter,
  68.                                      final AngularDerivativesFilter aFilter,
  69.                                      final int gridPoints, final double step,
  70.                                      final int maxSlots, final double maxSpan, final double newSlotInterval) {
  71.         this(new InterpolatingTransformProvider(rawProvider, cFilter, aFilter,
  72.                                                 gridPoints, step, maxSlots, maxSpan, newSlotInterval),
  73.              maxSlots, maxSpan, newSlotInterval);
  74.     }

  75.     /** Simple constructor.
  76.      * @param rawProvider provider for raw (non-interpolated) transforms
  77.      * @param cFilter filter for derivatives from the sample to use in interpolation
  78.      * @param aFilter filter for derivatives from the sample to use in interpolation
  79.      * @param earliest earliest supported date
  80.      * @param latest latest supported date
  81.      * @param gridPoints number of interpolation grid points
  82.      * @param step grid points time step
  83.      * @param maxSlots maximum number of independent cached time slots
  84.      * in the {@link GenericTimeStampedCache time-stamped cache}
  85.      * @param maxSpan maximum duration span in seconds of one slot
  86.      * in the {@link GenericTimeStampedCache time-stamped cache}
  87.      * @param newSlotInterval time interval above which a new slot is created
  88.      * in the {@link GenericTimeStampedCache time-stamped cache}
  89.      * @deprecated as of 9.1, replaced by {@link #ShiftingTransformProvider(TransformProvider,
  90.      * CartesianDerivativesFilter, AngularDerivativesFilter, int, double, int, double, double)}
  91.      */
  92.     @Deprecated
  93.     public ShiftingTransformProvider(final TransformProvider rawProvider,
  94.                                      final CartesianDerivativesFilter cFilter,
  95.                                      final AngularDerivativesFilter aFilter,
  96.                                      final AbsoluteDate earliest, final AbsoluteDate latest,
  97.                                      final int gridPoints, final double step,
  98.                                      final int maxSlots, final double maxSpan, final double newSlotInterval) {
  99.         this(new InterpolatingTransformProvider(rawProvider, cFilter, aFilter,
  100.                                                 earliest, latest, gridPoints, step,
  101.                                                 maxSlots, maxSpan, newSlotInterval),
  102.              maxSlots, maxSpan, newSlotInterval);
  103.     }

  104.     /** Simple constructor.
  105.      * @param interpolatingProvider first level cache provider
  106.      * @param maxSlots maximum number of independent cached time slots
  107.      * in the {@link GenericTimeStampedCache time-stamped cache}
  108.      * @param maxSpan maximum duration span in seconds of one slot
  109.      * in the {@link GenericTimeStampedCache time-stamped cache}
  110.      * @param newSlotInterval time interval above which a new slot is created
  111.      * in the {@link GenericTimeStampedCache time-stamped cache}
  112.      */
  113.     private ShiftingTransformProvider(final InterpolatingTransformProvider interpolatingProvider,
  114.                                      final int maxSlots, final double maxSpan, final double newSlotInterval) {
  115.         this.interpolatingProvider = interpolatingProvider;
  116.         this.cache = new GenericTimeStampedCache<Transform>(2, maxSlots, maxSpan, newSlotInterval,
  117.                                                             new TransformGenerator(2,
  118.                                                                                    interpolatingProvider,
  119.                                                                                    interpolatingProvider.getStep()));
  120.         this.fieldCaches = new HashMap<>();
  121.     }

  122.     /** Get the underlying provider for raw (non-interpolated) transforms.
  123.      * @return provider for raw (non-interpolated) transforms
  124.      */
  125.     public TransformProvider getRawProvider() {
  126.         return interpolatingProvider.getRawProvider();
  127.     }

  128.     /** Get the number of interpolation grid points.
  129.      * @return number of interpolation grid points
  130.      */
  131.     public int getGridPoints() {
  132.         return interpolatingProvider.getGridPoints();
  133.     }

  134.     /** Get the grid points time step.
  135.      * @return grid points time step
  136.      */
  137.     public double getStep() {
  138.         return interpolatingProvider.getStep();
  139.     }

  140.     /** {@inheritDoc} */
  141.     public Transform getTransform(final AbsoluteDate date) throws OrekitException {
  142.         try {

  143.             // retrieve a sample from the thread-safe cache
  144.             final Transform closest = cache.getNeighbors(date).reduce((t0, t1) ->
  145.                 FastMath.abs(date.durationFrom(t0.getDate())) < FastMath.abs(date.durationFrom(t1.getDate())) ? t0 : t1
  146.             ).get();
  147.             return closest.shiftedBy(date.durationFrom(closest.getDate()));

  148.         } catch (OrekitExceptionWrapper oew) {
  149.             // something went wrong while generating the sample,
  150.             // we just forward the exception up
  151.             throw oew.getException();
  152.         }
  153.     }

  154.     /** {@inheritDoc} */
  155.     public <T extends RealFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date)
  156.         throws OrekitException {
  157.         try {

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

  173.             // retrieve a sample from the thread-safe cache
  174.             final FieldTransform<T> closest = fieldCache.getNeighbors(date.toAbsoluteDate()).reduce((t0, t1) ->
  175.                 date.durationFrom(t0.getDate()).abs().getReal() < date.durationFrom(t1.getDate()).abs().getReal() ?
  176.                 t0 : t1
  177.             ).get();
  178.             return closest.shiftedBy(date.durationFrom(closest.getDate()));

  179.         } catch (OrekitExceptionWrapper oew) {
  180.             // something went wrong while generating the sample,
  181.             // we just forward the exception up
  182.             throw oew.getException();
  183.         }
  184.     }

  185.     /** Replace the instance with a data transfer object for serialization.
  186.      * <p>
  187.      * This intermediate class serializes only the data needed for generation,
  188.      * but does <em>not</em> serializes the cache itself (in fact the cache is
  189.      * not serializable).
  190.      * </p>
  191.      * @return data transfer object that will be serialized
  192.      */
  193.     private Object writeReplace() {
  194.         return new DTO(interpolatingProvider,
  195.                        cache.getMaxSlots(), cache.getMaxSpan(), cache.getNewSlotQuantumGap());
  196.     }

  197.     /** Internal class used only for serialization. */
  198.     private static class DTO implements Serializable {

  199.         /** Serializable UID. */
  200.         private static final long serialVersionUID = 20150601L;

  201.         /** Provider for raw (non-interpolated) transforms. */
  202.         private final InterpolatingTransformProvider interpolatingProvider;

  203.         /** Maximum number of independent cached time slots. */
  204.         private final int maxSlots;

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

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

  209.         /** Simple constructor.
  210.          * @param interpolatingProvider first level cache provider
  211.          * @param maxSlots maximum number of independent cached time slots
  212.          * in the {@link GenericTimeStampedCache time-stamped cache}
  213.          * @param maxSpan maximum duration span in seconds of one slot
  214.          * in the {@link GenericTimeStampedCache time-stamped cache}
  215.          * @param newSlotInterval time interval above which a new slot is created
  216.          * in the {@link GenericTimeStampedCache time-stamped cache}
  217.          */
  218.         private DTO(final InterpolatingTransformProvider interpolatingProvider,
  219.                     final int maxSlots, final double maxSpan, final double newSlotInterval) {
  220.             this.interpolatingProvider = interpolatingProvider;
  221.             this.maxSlots              = maxSlots;
  222.             this.maxSpan               = maxSpan;
  223.             this.newSlotInterval       = newSlotInterval;
  224.         }

  225.         /** Replace the deserialized data transfer object with a {@link ShiftingTransformProvider}.
  226.          * @return replacement {@link ShiftingTransformProvider}
  227.          */
  228.         private Object readResolve() {
  229.             // build a new provider, with an empty cache
  230.             return new ShiftingTransformProvider(interpolatingProvider,
  231.                                                  maxSlots, maxSpan, newSlotInterval);
  232.         }

  233.     }

  234. }