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.attitudes;
18  
19  import java.util.List;
20  import java.util.stream.Collectors;
21  
22  import org.hipparchus.CalculusFieldElement;
23  import org.orekit.frames.Frame;
24  import org.orekit.time.AbsoluteDate;
25  import org.orekit.time.FieldAbsoluteDate;
26  import org.orekit.time.FieldTimeInterpolator;
27  import org.orekit.time.TimeInterpolator;
28  import org.orekit.utils.AngularDerivativesFilter;
29  import org.orekit.utils.FieldPVCoordinatesProvider;
30  import org.orekit.utils.ImmutableTimeStampedCache;
31  import org.orekit.utils.PVCoordinatesProvider;
32  import org.orekit.utils.TimeStampedAngularCoordinates;
33  import org.orekit.utils.TimeStampedAngularCoordinatesHermiteInterpolator;
34  import org.orekit.utils.TimeStampedFieldAngularCoordinates;
35  import org.orekit.utils.TimeStampedFieldAngularCoordinatesHermiteInterpolator;
36  
37  /**
38   * This class handles an attitude provider interpolating from a predefined table.
39   * <p>Instances of this class are guaranteed to be immutable.</p>
40   * @author Luc Maisonobe
41   * @see TabulatedLofOffset
42   * @since 6.1
43   */
44  public class TabulatedProvider implements BoundedAttitudeProvider {
45  
46      /** Cached attitude table. */
47      private final transient ImmutableTimeStampedCache<? extends TimeStampedAngularCoordinates> table;
48  
49      /** Filter for derivatives from the sample to use in interpolation. */
50      private final AngularDerivativesFilter filter;
51  
52      /** First date of the range. */
53      private final AbsoluteDate minDate;
54  
55      /** Last date of the range. */
56      private final AbsoluteDate maxDate;
57  
58      /** Builder for filtered attitudes. */
59      private final AttitudeBuilder builder;
60  
61      /** Creates new instance.
62       * <p>
63       * This constructor uses the first and last point samples as the min and max dates.
64       * </p>
65       * @param referenceFrame reference frame for tabulated attitudes
66       * @param table tabulated attitudes
67       * @param n number of attitude to use for interpolation
68       * @param filter filter for derivatives from the sample to use in interpolation
69       * @see #TabulatedProvider(List, int, AngularDerivativesFilter, AbsoluteDate, AbsoluteDate, AttitudeBuilder)
70       */
71      public TabulatedProvider(final Frame referenceFrame, final List<? extends TimeStampedAngularCoordinates> table,
72                               final int n, final AngularDerivativesFilter filter) {
73          this(table, n, filter, table.get(0).getDate(), table.get(table.size() - 1).getDate(),
74               new FixedFrameBuilder(referenceFrame));
75      }
76  
77      /** Creates new instance.
78       * @param table tabulated attitudes
79       * @param n number of attitude to use for interpolation
80       * @param filter filter for derivatives from the sample to use in interpolation
81       * @param minDate min date to use
82       * @param maxDate max date to use
83       * @param builder builder to use
84       * @since 11.0
85       */
86      public TabulatedProvider(final List<? extends TimeStampedAngularCoordinates> table,
87                               final int n, final AngularDerivativesFilter filter,
88                               final AbsoluteDate minDate, final AbsoluteDate maxDate,
89                               final AttitudeBuilder builder) {
90          this.table          = new ImmutableTimeStampedCache<TimeStampedAngularCoordinates>(n, table);
91          this.filter         = filter;
92          this.minDate        = minDate;
93          this.maxDate        = maxDate;
94          this.builder        = builder;
95      }
96  
97      /** {@inheritDoc} */
98      public Attitude getAttitude(final PVCoordinatesProvider pvProv,
99                                  final AbsoluteDate date, final Frame frame) {
100 
101         // get attitudes sample on which interpolation will be performed
102         final List<TimeStampedAngularCoordinates> sample = table.getNeighbors(date).collect(Collectors.toList());
103 
104         // create interpolator
105         final TimeInterpolator<TimeStampedAngularCoordinates> interpolator =
106                 new TimeStampedAngularCoordinatesHermiteInterpolator(sample.size(), filter);
107 
108         // interpolate
109         final TimeStampedAngularCoordinates interpolated = interpolator.interpolate(date, sample);
110 
111         // build the attitude
112         return builder.build(frame, pvProv, interpolated);
113 
114     }
115 
116     /** {@inheritDoc} */
117     public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
118                                                                         final FieldAbsoluteDate<T> date,
119                                                                         final Frame frame) {
120 
121         // get attitudes sample on which interpolation will be performed
122         final List<TimeStampedFieldAngularCoordinates<T>> sample =
123                         table.
124                         getNeighbors(date.toAbsoluteDate()).
125                         map(ac -> new TimeStampedFieldAngularCoordinates<>(date.getField(), ac)).
126                         collect(Collectors.toList());
127 
128         // create interpolator
129         final FieldTimeInterpolator<TimeStampedFieldAngularCoordinates<T>, T> interpolator =
130                 new TimeStampedFieldAngularCoordinatesHermiteInterpolator<>(sample.size(), filter);
131 
132         // interpolate
133         final TimeStampedFieldAngularCoordinates<T> interpolated = interpolator.interpolate(date, sample);
134 
135         // build the attitude
136         return builder.build(frame, pvProv, interpolated);
137 
138     }
139 
140     /** {@inheritDoc} */
141     public AbsoluteDate getMinDate() {
142         return minDate;
143     }
144 
145     /** {@inheritDoc} */
146     public AbsoluteDate getMaxDate() {
147         return maxDate;
148     }
149 
150 }