CachedTransformProvider.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.orekit.time.AbsoluteDate;

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

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

  36.     /** Origin frame. */
  37.     private final Frame origin;

  38.     /** Destination frame. */
  39.     private final Frame destination;

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

  42.     /** Generator for full transforms. */
  43.     private final Function<AbsoluteDate, Transform> fullGenerator;

  44.     /** Generator for kinematic transforms. */
  45.     private final Function<AbsoluteDate, KinematicTransform> kinematicGenerator;

  46.     /** Generator for static transforms. */
  47.     private final Function<AbsoluteDate, StaticTransform> staticGenerator;

  48.     /** Lock for concurrent access. */
  49.     private final ReentrantLock lock;

  50.     /** Transforms LRU cache. */
  51.     private final Map<AbsoluteDate, Transform> fullCache;

  52.     /** Transforms LRU cache. */
  53.     private final Map<AbsoluteDate, KinematicTransform> kinematicCache;

  54.     /** Transforms LRU cache. */
  55.     private final Map<AbsoluteDate, StaticTransform> staticCache;

  56.     /** Simple constructor.
  57.      * @param origin             origin frame
  58.      * @param destination        destination frame
  59.      * @param fullGenerator      generator for full transforms
  60.      * @param kinematicGenerator generator for kinematic transforms
  61.      * @param staticGenerator    generator for static transforms
  62.      * @param cacheSize          number of transforms kept in the date-based cache
  63.      */
  64.     public CachedTransformProvider(final Frame origin, final Frame destination,
  65.                                    final Function<AbsoluteDate, Transform> fullGenerator,
  66.                                    final Function<AbsoluteDate, KinematicTransform> kinematicGenerator,
  67.                                    final Function<AbsoluteDate, StaticTransform> staticGenerator,
  68.                                    final int cacheSize) {

  69.         this.origin             = origin;
  70.         this.destination        = destination;
  71.         this.cacheSize          = cacheSize;
  72.         this.fullGenerator      = fullGenerator;
  73.         this.kinematicGenerator = kinematicGenerator;
  74.         this.staticGenerator    = staticGenerator;
  75.         this.lock               = new ReentrantLock();

  76.         // cache for full transforms
  77.         this.fullCache = new LinkedHashMap<AbsoluteDate, Transform>(cacheSize, 0.75f, true) {
  78.             /** {@inheritDoc} */
  79.             @Override
  80.             protected boolean removeEldestEntry(final Map.Entry<AbsoluteDate, Transform> eldest) {
  81.                 return size() > cacheSize;
  82.             }
  83.         };

  84.         // cache for kinematic transforms
  85.         this.kinematicCache = new LinkedHashMap<AbsoluteDate, KinematicTransform>(cacheSize, 0.75f, true) {
  86.             /** {@inheritDoc} */
  87.             @Override
  88.             protected boolean removeEldestEntry(final Map.Entry<AbsoluteDate, KinematicTransform> eldest) {
  89.                 return size() > cacheSize;
  90.             }
  91.         };

  92.         // cache for static transforms
  93.         this.staticCache = new LinkedHashMap<AbsoluteDate, StaticTransform>(cacheSize, 0.75f, true) {
  94.             /** {@inheritDoc} */
  95.             @Override
  96.             protected boolean removeEldestEntry(final Map.Entry<AbsoluteDate, StaticTransform> eldest) {
  97.                 return size() > cacheSize;
  98.             }
  99.         };

  100.     }

  101.     /** Get origin frame.
  102.      * @return origin frame
  103.      */
  104.     public Frame getOrigin() {
  105.         return origin;
  106.     }

  107.     /** Get destination frame.
  108.      * @return destination frame
  109.      */
  110.     public Frame getDestination() {
  111.         return destination;
  112.     }

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

  119.     /** Get the {@link Transform} corresponding to specified date.
  120.      * @param date current date
  121.      * @return transform at specified date
  122.      */
  123.     public Transform getTransform(final AbsoluteDate date) {
  124.         lock.lock();
  125.         try {
  126.             return fullCache.computeIfAbsent(date, fullGenerator);
  127.         } finally {
  128.             lock.unlock();
  129.         }
  130.     }

  131.     /** Get the {@link Transform} corresponding to specified date.
  132.      * @param date current date
  133.      * @return transform at specified date
  134.      */
  135.     public KinematicTransform getKinematicTransform(final AbsoluteDate date) {
  136.         lock.lock();
  137.         try {
  138.             return kinematicCache.computeIfAbsent(date, kinematicGenerator);
  139.         } finally {
  140.             lock.unlock();
  141.         }
  142.     }

  143.     /** Get the {@link Transform} corresponding to specified date.
  144.      * @param date current date
  145.      * @return transform at specified date
  146.      */
  147.     public StaticTransform getStaticTransform(final AbsoluteDate date) {
  148.         lock.lock();
  149.         try {
  150.             return staticCache.computeIfAbsent(date, staticGenerator);
  151.         } finally {
  152.             lock.unlock();
  153.         }
  154.     }

  155. }