ShiftingTransformProvider.java

  1. /* Copyright 2002-2025 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.util.HashMap;
  19. import java.util.Map;

  20. import org.hipparchus.Field;
  21. import org.hipparchus.CalculusFieldElement;
  22. import org.hipparchus.util.FastMath;
  23. import org.orekit.time.AbsoluteDate;
  24. import org.orekit.time.FieldAbsoluteDate;
  25. import org.orekit.utils.AngularDerivativesFilter;
  26. import org.orekit.utils.CartesianDerivativesFilter;
  27. import org.orekit.utils.GenericTimeStampedCache;

  28. /** Transform provider using thread-safe shifts on transforms sample.
  29.  * <p>
  30.  * The shifts take derivatives into account, up to user specified order.
  31.  * </p>
  32.  * @see GenericTimeStampedCache
  33.  * @see InterpolatingTransformProvider
  34.  * @since 7.1
  35.  * @author Luc Maisonobe
  36.  */
  37. public class ShiftingTransformProvider implements TransformProvider {

  38.     /** First level cache. */
  39.     private final InterpolatingTransformProvider interpolatingProvider;

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

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

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

  70.     /** Simple constructor.
  71.      * @param interpolatingProvider first level cache provider
  72.      * @param maxSlots maximum number of independent cached time slots
  73.      * in the {@link GenericTimeStampedCache time-stamped cache}
  74.      * @param maxSpan maximum duration span in seconds of one slot
  75.      * in the {@link GenericTimeStampedCache time-stamped cache}
  76.      * @param newSlotInterval time interval above which a new slot is created
  77.      * in the {@link GenericTimeStampedCache time-stamped cache}
  78.      */
  79.     private ShiftingTransformProvider(final InterpolatingTransformProvider interpolatingProvider,
  80.                                      final int maxSlots, final double maxSpan, final double newSlotInterval) {
  81.         this.interpolatingProvider = interpolatingProvider;
  82.         this.cache = new GenericTimeStampedCache<>(2, maxSlots, maxSpan, newSlotInterval,
  83.                 new TransformGenerator(2,
  84.                         interpolatingProvider,
  85.                         interpolatingProvider.getStep()));
  86.         this.fieldCaches = new HashMap<>();
  87.     }

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

  94.     /** Get the number of interpolation grid points.
  95.      * @return number of interpolation grid points
  96.      */
  97.     public int getGridPoints() {
  98.         return interpolatingProvider.getGridPoints();
  99.     }

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

  106.     /** {@inheritDoc} */
  107.     public Transform getTransform(final AbsoluteDate date) {
  108.         // retrieve a sample from the thread-safe cache
  109.         final Transform closest = cache.getNeighbors(date).reduce((t0, t1) ->
  110.             FastMath.abs(date.durationFrom(t0.getDate())) < FastMath.abs(date.durationFrom(t1.getDate())) ? t0 : t1
  111.         ).get();
  112.         return closest.shiftedBy(date.durationFrom(closest.getDate()));
  113.     }

  114.     /** {@inheritDoc} */
  115.     @Override
  116.     public StaticTransform getStaticTransform(final AbsoluteDate date) {
  117.         // retrieve a sample from the thread-safe cache
  118.         final Transform closest = cache.getNeighbors(date).reduce((t0, t1) ->
  119.                 FastMath.abs(date.durationFrom(t0.getDate())) < FastMath.abs(date.durationFrom(t1.getDate())) ? t0 : t1
  120.         ).get();
  121.         return closest.staticShiftedBy(date.durationFrom(closest.getDate()));
  122.     }

  123.     /** {@inheritDoc} */
  124.     public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
  125.         @SuppressWarnings("unchecked")
  126.         GenericTimeStampedCache<FieldTransform<T>> fieldCache =
  127.             (GenericTimeStampedCache<FieldTransform<T>>) fieldCaches.get(date.getField());
  128.         if (fieldCache == null) {
  129.             fieldCache =
  130.                     new GenericTimeStampedCache<>(cache.getMaxNeighborsSize(),
  131.                             cache.getMaxSlots(),
  132.                             cache.getMaxSpan(),
  133.                             cache.getNewSlotQuantumGap(),
  134.                             new FieldTransformGenerator<>(date.getField(),
  135.                                     cache.getMaxNeighborsSize(),
  136.                                     interpolatingProvider,
  137.                                     interpolatingProvider.getStep()));
  138.             fieldCaches.put(date.getField(), fieldCache);
  139.         }

  140.         // retrieve a sample from the thread-safe cache
  141.         final FieldTransform<T> closest = fieldCache.getNeighbors(date.toAbsoluteDate()).reduce((t0, t1) ->
  142.             date.durationFrom(t0.getDate()).abs().getReal() < date.durationFrom(t1.getDate()).abs().getReal() ?
  143.             t0 : t1
  144.         ).get();
  145.         return closest.shiftedBy(date.durationFrom(closest.getDate()));
  146.     }

  147.     /** {@inheritDoc} */
  148.     @Override
  149.     public <T extends CalculusFieldElement<T>> FieldStaticTransform<T> getStaticTransform(final FieldAbsoluteDate<T> date) {
  150.         @SuppressWarnings("unchecked")
  151.         GenericTimeStampedCache<FieldTransform<T>> fieldCache =
  152.             (GenericTimeStampedCache<FieldTransform<T>>) fieldCaches.get(date.getField());
  153.         if (fieldCache == null) {
  154.             fieldCache =
  155.                     new GenericTimeStampedCache<>(cache.getMaxNeighborsSize(),
  156.                             cache.getMaxSlots(),
  157.                             cache.getMaxSpan(),
  158.                             cache.getNewSlotQuantumGap(),
  159.                             new FieldTransformGenerator<>(date.getField(),
  160.                                     cache.getMaxNeighborsSize(),
  161.                                     interpolatingProvider,
  162.                                     interpolatingProvider.getStep()));
  163.             fieldCaches.put(date.getField(), fieldCache);
  164.         }

  165.         // retrieve a sample from the thread-safe cache
  166.         final FieldTransform<T> closest = fieldCache.getNeighbors(date.toAbsoluteDate()).reduce((t0, t1) ->
  167.             date.durationFrom(t0.getDate()).abs().getReal() < date.durationFrom(t1.getDate()).abs().getReal() ?
  168.             t0 : t1
  169.         ).get();
  170.         return closest.staticShiftedBy(date.durationFrom(closest.getDate()));
  171.     }

  172. }