1   /* Copyright 2002-2021 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.errors.OrekitException;
24  import org.orekit.errors.OrekitMessages;
25  import org.orekit.frames.FieldTransform;
26  import org.orekit.frames.Frame;
27  import org.orekit.frames.LOFType;
28  import org.orekit.frames.Transform;
29  import org.orekit.time.AbsoluteDate;
30  import org.orekit.time.FieldAbsoluteDate;
31  import org.orekit.utils.AngularDerivativesFilter;
32  import org.orekit.utils.FieldPVCoordinates;
33  import org.orekit.utils.FieldPVCoordinatesProvider;
34  import org.orekit.utils.ImmutableTimeStampedCache;
35  import org.orekit.utils.PVCoordinates;
36  import org.orekit.utils.PVCoordinatesProvider;
37  import org.orekit.utils.TimeStampedAngularCoordinates;
38  import org.orekit.utils.TimeStampedFieldAngularCoordinates;
39  
40  /**
41   * This class handles an attitude provider interpolating from a predefined table
42   * containing offsets from a Local Orbital Frame.
43   * <p>Instances of this class are guaranteed to be immutable.</p>
44   * @see LofOffset
45   * @see TabulatedProvider
46   * @author Luc Maisonobe
47   * @since 7.1
48   */
49  public class TabulatedLofOffset implements BoundedAttitudeProvider {
50  
51      /** Inertial frame with respect to which orbit should be computed. */
52      private final Frame inertialFrame;
53  
54      /** Type of Local Orbital Frame. */
55      private LOFType type;
56  
57      /** Cached attitude table. */
58      private final transient ImmutableTimeStampedCache<? extends TimeStampedAngularCoordinates> table;
59  
60      /** Filter for derivatives from the sample to use in interpolation. */
61      private final AngularDerivativesFilter filter;
62  
63      /** First date of the range. */
64      private final AbsoluteDate minDate;
65  
66      /** Last date of the range. */
67      private final AbsoluteDate maxDate;
68  
69      /** Creates new instance.
70       * <p>
71       * This constructor uses the first and last point samples as the min and max dates.
72       * </p>
73       * @param inertialFrame inertial frame with respect to which orbit should be computed
74       * @param type type of Local Orbital Frame
75       * @param table tabulated attitudes
76       * @param n number of attitude to use for interpolation
77       * @param filter filter for derivatives from the sample to use in interpolation
78       */
79      public TabulatedLofOffset(final Frame inertialFrame, final LOFType type,
80                                final List<? extends TimeStampedAngularCoordinates> table,
81                                final int n, final AngularDerivativesFilter filter) {
82          this(inertialFrame, type, table, n, filter, table.get(0).getDate(), table.get(table.size() - 1).getDate());
83      }
84  
85      /** Creates new instance.
86       * @param inertialFrame inertial frame with respect to which orbit should be computed
87       * @param type type of Local Orbital Frame
88       * @param table tabulated attitudes
89       * @param n number of attitude to use for interpolation
90       * @param minDate min date to use
91       * @param maxDate max date to use
92       * @param filter filter for derivatives from the sample to use in interpolation
93       * @since 11.0
94       */
95      public TabulatedLofOffset(final Frame inertialFrame, final LOFType type,
96                                final List<? extends TimeStampedAngularCoordinates> table,
97                                final int n, final AngularDerivativesFilter filter,
98                                final AbsoluteDate minDate, final AbsoluteDate maxDate) {
99          if (!inertialFrame.isPseudoInertial()) {
100             throw new OrekitException(OrekitMessages.NON_PSEUDO_INERTIAL_FRAME,
101                                       inertialFrame.getName());
102         }
103         this.inertialFrame = inertialFrame;
104         this.type          = type;
105         this.table         = new ImmutableTimeStampedCache<TimeStampedAngularCoordinates>(n, table);
106         this.filter        = filter;
107         this.minDate       = minDate;
108         this.maxDate       = maxDate;
109     }
110 
111     /** Get an unmodifiable view of the tabulated attitudes.
112      * @return unmodifiable view of the tabulated attitudes
113      */
114     public List<? extends TimeStampedAngularCoordinates> getTable() {
115         return table.getAll();
116     }
117 
118     /** {@inheritDoc} */
119     public Attitude getAttitude(final PVCoordinatesProvider pvProv,
120                                 final AbsoluteDate date, final Frame frame) {
121 
122         // get attitudes sample on which interpolation will be performed
123         final List<TimeStampedAngularCoordinates> sample = table.getNeighbors(date).collect(Collectors.toList());
124 
125         // interpolate
126         final TimeStampedAngularCoordinates interpolated =
127                 TimeStampedAngularCoordinates.interpolate(date, filter, sample);
128 
129         // construction of the local orbital frame, using PV from inertial frame
130         final PVCoordinates pv = pvProv.getPVCoordinates(date, inertialFrame);
131         final Transform inertialToLof = type.transformFromInertial(date, pv);
132 
133         // take into account the specified start frame (which may not be an inertial one)
134         final Transform frameToInertial = frame.getTransformTo(inertialFrame, date);
135         final Transform frameToLof      = new Transform(date, frameToInertial, inertialToLof);
136 
137         // compose with interpolated rotation
138         return new Attitude(date, frame,
139                             interpolated.addOffset(frameToLof.getAngular()));
140     }
141 
142     /** {@inheritDoc} */
143     public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
144                                                                         final FieldAbsoluteDate<T> date,
145                                                                         final Frame frame) {
146 
147         // get attitudes sample on which interpolation will be performed
148         final List<TimeStampedFieldAngularCoordinates<T>> sample =
149                         table.
150                         getNeighbors(date.toAbsoluteDate()).
151                         map(ac -> new TimeStampedFieldAngularCoordinates<>(date.getField(), ac)).
152                         collect(Collectors.toList());
153 
154         // interpolate
155         final TimeStampedFieldAngularCoordinates<T> interpolated =
156                 TimeStampedFieldAngularCoordinates.interpolate(date, filter, sample);
157 
158         // construction of the local orbital frame, using PV from inertial frame
159         final FieldPVCoordinates<T> pv = pvProv.getPVCoordinates(date, inertialFrame);
160         final FieldTransform<T> inertialToLof = type.transformFromInertial(date, pv);
161 
162         // take into account the specified start frame (which may not be an inertial one)
163         final FieldTransform<T> frameToInertial = frame.getTransformTo(inertialFrame, date);
164         final FieldTransform<T> frameToLof      = new FieldTransform<>(date, frameToInertial, inertialToLof);
165 
166         // compose with interpolated rotation
167         return new FieldAttitude<>(date, frame,
168                                    interpolated.addOffset(frameToLof.getAngular()));
169     }
170 
171     /** {@inheritDoc} */
172     public AbsoluteDate getMinDate() {
173         return minDate;
174     }
175 
176     /** {@inheritDoc} */
177     public AbsoluteDate getMaxDate() {
178         return maxDate;
179     }
180 
181 }