FieldCachedTransformProvider.java

  1. /* Copyright 2022-2025 Thales Alenia Space
  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 org.hipparchus.CalculusFieldElement;
  19. import org.orekit.time.FieldAbsoluteDate;

  20. import java.util.LinkedHashMap;
  21. import java.util.Map;
  22. import java.util.concurrent.locks.ReentrantLock;
  23. import java.util.function.Function;

  24. /** Thread-safe cached provider for frame transforms.
  25.  * <p>
  26.  * This provider is based on a thread-safe Least Recently Used cache
  27.  * using date as it access key, hence saving computation time on
  28.  * transform building.
  29.  * </p>
  30.  * <p>
  31.  * This class is thread-safe.
  32.  * </p>
  33.  * @param <T> type of the field elements
  34.  * @author Luc Maisonobe
  35.  * @since 13.0.3
  36.  */
  37. public class FieldCachedTransformProvider<T extends CalculusFieldElement<T>> {

  38.     /** Origin frame. */
  39.     private final Frame origin;

  40.     /** Destination frame. */
  41.     private final Frame destination;

  42.     /** Number of transforms kept in the date-based cache. */
  43.     private final int cacheSize;

  44.     /** Generator for full transforms. */
  45.     private final Function<FieldAbsoluteDate<T>, FieldTransform<T>> fullGenerator;

  46.     /** Generator for kinematic transforms. */
  47.     private final Function<FieldAbsoluteDate<T>, FieldKinematicTransform<T>> kinematicGenerator;

  48.     /** Generator for static transforms. */
  49.     private final Function<FieldAbsoluteDate<T>, FieldStaticTransform<T>> staticGenerator;

  50.     /** Lock for concurrent access. */
  51.     private final ReentrantLock lock;

  52.     /** Transforms LRU cache. */
  53.     private final Map<FieldAbsoluteDate<T>, FieldTransform<T>> fullCache;

  54.     /** Transforms LRU cache. */
  55.     private final Map<FieldAbsoluteDate<T>, FieldKinematicTransform<T>> kinematicCache;

  56.     /** Transforms LRU cache. */
  57.     private final Map<FieldAbsoluteDate<T>, FieldStaticTransform<T>> staticCache;

  58.     /**
  59.      * Simple constructor.
  60.      * @param origin             origin frame
  61.      * @param destination        destination frame
  62.      * @param fullGenerator      generator for full transforms
  63.      * @param kinematicGenerator generator for kinematic transforms
  64.      * @param staticGenerator    generator for static transforms
  65.      * @param cacheSize          number of transforms kept in the date-based cache
  66.      */
  67.     public FieldCachedTransformProvider(final Frame origin, final Frame destination,
  68.                                         final Function<FieldAbsoluteDate<T>, FieldTransform<T>> fullGenerator,
  69.                                         final Function<FieldAbsoluteDate<T>, FieldKinematicTransform<T>> kinematicGenerator,
  70.                                         final Function<FieldAbsoluteDate<T>, FieldStaticTransform<T>> staticGenerator,
  71.                                         final int cacheSize) {

  72.         this.origin             = origin;
  73.         this.destination        = destination;
  74.         this.cacheSize          = cacheSize;
  75.         this.fullGenerator      = fullGenerator;
  76.         this.kinematicGenerator = kinematicGenerator;
  77.         this.staticGenerator    = staticGenerator;
  78.         this.lock               = new ReentrantLock();

  79.         // cache for full transforms
  80.         this.fullCache = new LinkedHashMap<FieldAbsoluteDate<T>, FieldTransform<T>>(cacheSize, 0.75f, true) {
  81.             /** {@inheritDoc} */
  82.             @Override
  83.             protected boolean removeEldestEntry(final Map.Entry<FieldAbsoluteDate<T>, FieldTransform<T>> eldest) {
  84.                 return size() > cacheSize;
  85.             }
  86.         };

  87.         // cache for kinematic transforms
  88.         this.kinematicCache = new LinkedHashMap<FieldAbsoluteDate<T>, FieldKinematicTransform<T>>(cacheSize, 0.75f, true) {
  89.             /** {@inheritDoc} */
  90.             @Override
  91.             protected boolean removeEldestEntry(final Map.Entry<FieldAbsoluteDate<T>, FieldKinematicTransform<T>> eldest) {
  92.                 return size() > cacheSize;
  93.             }
  94.         };

  95.         // cache for static transforms
  96.         this.staticCache = new LinkedHashMap<FieldAbsoluteDate<T>, FieldStaticTransform<T>>(cacheSize, 0.75f, true) {
  97.             /** {@inheritDoc} */
  98.             @Override
  99.             protected boolean removeEldestEntry(final Map.Entry<FieldAbsoluteDate<T>, FieldStaticTransform<T>> eldest) {
  100.                 return size() > cacheSize;
  101.             }
  102.         };

  103.     }

  104.     /** Get origin frame.
  105.      * @return origin frame
  106.      */
  107.     public Frame getOrigin() {
  108.         return origin;
  109.     }

  110.     /** Get destination frame.
  111.      * @return destination frame
  112.      */
  113.     public Frame getDestination() {
  114.         return destination;
  115.     }

  116.     /** Get the nmber of transforms kept in the date-based cache.
  117.      * @return nmber of transforms kept in the date-based cache
  118.      */
  119.     public int getCacheSize() {
  120.         return cacheSize;
  121.     }

  122.     /** Get the {@link Transform} corresponding to specified date.
  123.      * @param date current date
  124.      * @return transform at specified date
  125.      */
  126.     public FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
  127.         lock.lock();
  128.         try {
  129.             return fullCache.computeIfAbsent(date, fullGenerator);
  130.         } finally {
  131.             lock.unlock();
  132.         }
  133.     }

  134.     /** Get the {@link Transform} corresponding to specified date.
  135.      * @param date current date
  136.      * @return transform at specified date
  137.      */
  138.     public FieldKinematicTransform<T> getKinematicTransform(final FieldAbsoluteDate<T> date) {
  139.         lock.lock();
  140.         try {
  141.             return kinematicCache.computeIfAbsent(date, kinematicGenerator);
  142.         } finally {
  143.             lock.unlock();
  144.         }
  145.     }

  146.     /** Get the {@link Transform} corresponding to specified date.
  147.      * @param date current date
  148.      * @return transform at specified date
  149.      */
  150.     public FieldStaticTransform<T> getStaticTransform(final FieldAbsoluteDate<T> date) {
  151.         lock.lock();
  152.         try {
  153.             return staticCache.computeIfAbsent(date, staticGenerator);
  154.         } finally {
  155.             lock.unlock();
  156.         }
  157.     }

  158. }