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.propagation;
18
19 import org.orekit.frames.Frame;
20 import org.orekit.frames.LOFType;
21 import org.orekit.orbits.Orbit;
22 import org.orekit.orbits.OrbitType;
23 import org.orekit.orbits.PositionAngleType;
24 import org.orekit.time.AbsoluteDate;
25 import org.orekit.time.AbstractTimeInterpolator;
26 import org.orekit.time.TimeInterpolator;
27 import org.orekit.time.TimeStampedPair;
28
29 import java.util.List;
30 import java.util.stream.Collectors;
31 import java.util.stream.Stream;
32
33 /**
34 * Abstract class for orbit and state covariance interpolator.
35 *
36 * @author Vincent Cucchietti
37 * @see Orbit
38 * @see StateCovariance
39 * @see TimeStampedPair
40 */
41 public abstract class AbstractStateCovarianceInterpolator
42 extends AbstractTimeInterpolator<TimeStampedPair<Orbit, StateCovariance>> {
43
44 /** Default position angle for covariance expressed in Cartesian elements. */
45 public static final PositionAngleType DEFAULT_POSITION_ANGLE = PositionAngleType.MEAN;
46
47 /** Default column dimension for position-velocity state covariance. */
48 public static final int COLUMN_DIM = 6;
49
50 /** Default row dimension for position-velocity state covariance. */
51 public static final int ROW_DIM = 6;
52
53 /** Output frame. */
54 private final Frame outFrame;
55
56 /** Output local orbital frame. */
57 private final LOFType outLOF;
58
59 /** Output orbit type. */
60 private final OrbitType outOrbitType;
61
62 /** Output position angle type. */
63 private final PositionAngleType outPositionAngleType;
64
65 /** Orbit interpolator. */
66 private final TimeInterpolator<Orbit> orbitInterpolator;
67
68 /**
69 * Constructor.
70 *
71 * @param interpolationPoints number of interpolation points
72 * @param extrapolationThreshold extrapolation threshold beyond which the propagation will fail
73 * @param orbitInterpolator orbit interpolator
74 * @param outLOF local orbital frame
75 *
76 * @see Frame
77 * @see OrbitType
78 * @see PositionAngleType
79 */
80 public AbstractStateCovarianceInterpolator(final int interpolationPoints, final double extrapolationThreshold,
81 final TimeInterpolator<Orbit> orbitInterpolator,
82 final LOFType outLOF) {
83 super(interpolationPoints, extrapolationThreshold);
84 this.orbitInterpolator = orbitInterpolator;
85 this.outLOF = outLOF;
86 this.outFrame = null;
87 this.outOrbitType = OrbitType.CARTESIAN;
88 this.outPositionAngleType = DEFAULT_POSITION_ANGLE;
89 }
90
91 /**
92 * Constructor.
93 *
94 * @param interpolationPoints number of interpolation points
95 * @param extrapolationThreshold extrapolation threshold beyond which the propagation will fail
96 * @param orbitInterpolator orbit interpolator
97 * @param outFrame desired output covariance frame
98 * @param outPositionAngleType desired output position angle
99 * @param outOrbitType desired output orbit type
100 *
101 * @see Frame
102 * @see OrbitType
103 * @see PositionAngleType
104 */
105 public AbstractStateCovarianceInterpolator(final int interpolationPoints, final double extrapolationThreshold,
106 final TimeInterpolator<Orbit> orbitInterpolator,
107 final Frame outFrame,
108 final OrbitType outOrbitType,
109 final PositionAngleType outPositionAngleType) {
110 super(interpolationPoints, extrapolationThreshold);
111 this.orbitInterpolator = orbitInterpolator;
112 this.outLOF = null;
113 this.outFrame = outFrame;
114 this.outOrbitType = outOrbitType;
115 this.outPositionAngleType = outPositionAngleType;
116 }
117
118 /**
119 * Interpolate orbit and associated covariance.
120 *
121 * @param interpolationData interpolation data
122 *
123 * @return interpolated orbit and associated covariance
124 */
125 @Override
126 public TimeStampedPair<Orbit, StateCovariance> interpolate(final InterpolationData interpolationData) {
127
128 // Interpolate orbit at interpolation date
129 final Orbit interpolatedOrbit = interpolateOrbit(interpolationData.getInterpolationDate(),
130 interpolationData.getNeighborList());
131
132 // Rebuild state covariance
133 final StateCovariance covarianceInOrbitFrame =
134 computeInterpolatedCovarianceInOrbitFrame(interpolationData.getNeighborList(), interpolatedOrbit);
135
136 // Output new blended StateCovariance instance in desired output
137 return expressCovarianceInDesiredOutput(interpolatedOrbit, covarianceInOrbitFrame);
138 }
139
140 /** Get output frame.
141 * @return output frame. Can be null.
142 */
143 public Frame getOutFrame() {
144 return outFrame;
145 }
146
147 /** Get output local orbital frame.
148 * @return output local orbital frame. Can be null.
149 */
150 public LOFType getOutLOF() {
151 return outLOF;
152 }
153
154 /** Get output orbit type.
155 * @return output orbit type.
156 */
157 public OrbitType getOutOrbitType() {
158 return outOrbitType;
159 }
160
161 /** Get output position angle type.
162 * @return output position angle.
163 */
164 public PositionAngleType getOutPositionAngleType() {
165 return outPositionAngleType;
166 }
167
168 /** Get orbit interpolator.
169 * @return orbit interpolator.
170 */
171 public TimeInterpolator<Orbit> getOrbitInterpolator() {
172 return orbitInterpolator;
173 }
174
175 /**
176 * Interpolate orbit at given interpolation date.
177 *
178 * @param interpolationDate interpolation date
179 * @param neighborList neighbor list
180 *
181 * @return interpolated orbit
182 */
183 protected Orbit interpolateOrbit(final AbsoluteDate interpolationDate,
184 final List<TimeStampedPair<Orbit, StateCovariance>> neighborList) {
185
186 // Build orbit list from uncertain orbits
187 final List<Orbit> orbits = buildOrbitList(neighborList);
188
189 return orbitInterpolator.interpolate(interpolationDate, orbits);
190 }
191
192 /**
193 * Compute the interpolated covariance expressed in the interpolated orbit frame.
194 *
195 * @param uncertainStates list of orbits and associated covariances
196 * @param interpolatedOrbit interpolated orbit
197 *
198 * @return interpolated covariance expressed in the interpolated orbit frame
199 */
200 protected abstract StateCovariance computeInterpolatedCovarianceInOrbitFrame(
201 List<TimeStampedPair<Orbit, StateCovariance>> uncertainStates,
202 Orbit interpolatedOrbit);
203
204 /**
205 * Express covariance in output configuration defined at this instance construction.
206 *
207 * @param interpolatedOrbit interpolated orbit
208 * @param covarianceInOrbitFrame covariance expressed in interpolated orbit frame
209 *
210 * @return covariance in desired output configuration
211 */
212 protected TimeStampedPair<Orbit, StateCovariance> expressCovarianceInDesiredOutput(final Orbit interpolatedOrbit,
213 final StateCovariance covarianceInOrbitFrame) {
214
215 final StateCovariance covarianceOutput;
216
217 // Output frame is defined
218 if (outLOF == null) {
219
220 // Output frame is pseudo inertial
221 if (outFrame.isPseudoInertial()) {
222 final StateCovariance covarianceInOutputFrame =
223 covarianceInOrbitFrame.changeCovarianceFrame(interpolatedOrbit, outFrame);
224
225 covarianceOutput =
226 covarianceInOutputFrame.changeCovarianceType(interpolatedOrbit, outOrbitType, outPositionAngleType);
227 }
228 // Output frame is not pseudo inertial
229 else {
230 covarianceOutput = covarianceInOrbitFrame.changeCovarianceFrame(interpolatedOrbit, outFrame);
231 }
232
233 }
234 // Output local orbital frame is defined
235 else {
236 covarianceOutput = covarianceInOrbitFrame.changeCovarianceFrame(interpolatedOrbit, outLOF);
237 }
238
239 return new TimeStampedPair<>(interpolatedOrbit, covarianceOutput);
240 }
241
242 /**
243 * Build an orbit list from cached samples.
244 *
245 * @param neighborList neighbor list
246 *
247 * @return orbit list
248 */
249 private List<Orbit> buildOrbitList(final List<TimeStampedPair<Orbit, StateCovariance>> neighborList) {
250
251 // Get samples stream
252 final Stream<TimeStampedPair<Orbit, StateCovariance>> uncertainStateStream = neighborList.stream();
253
254 // Map to orbit
255 final Stream<Orbit> orbitStream = uncertainStateStream.map(TimeStampedPair::getFirst);
256
257 // Convert to list
258 return orbitStream.collect(Collectors.toList());
259 }
260 }