1 /* Copyright 2002-2018 CS Systèmes d'Information
2 * Licensed to CS Systèmes d'Information (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.estimation.sequential;
18
19 import org.hipparchus.analysis.UnivariateFunction;
20 import org.hipparchus.exception.LocalizedCoreFormats;
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.hipparchus.linear.MatrixUtils;
23 import org.hipparchus.linear.RealMatrix;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.frames.LOFType;
26 import org.orekit.frames.Transform;
27 import org.orekit.orbits.PositionAngle;
28 import org.orekit.propagation.SpacecraftState;
29
30 /** Provider for a temporal evolution of the process noise matrix.
31 * All parameters (orbital or propagation) are time dependent and provided as {@link UnivariateFunction}.
32 * The argument of the functions is a duration in seconds (between current and previous spacecraft state).
33 * The output of the functions must be of the dimension of a standard deviation.
34 * The method {@link #getProcessNoiseMatrix} then square the values so that they are consistent with a covariance matrix.
35 * <p>
36 * The orbital parameters evolutions are provided in LOF frame and Cartesian (PV);
37 * then converted in inertial frame and current {@link OrbitType} and {@link PositionAngle}
38 * when method {@link #getProcessNoiseMatrix} is called.
39 * </p>
40 * <p>
41 * The time-dependent functions define a process noise matrix that is diagonal
42 * <em>in the Local Orbital Frame</em>, corresponds to Cartesian elements, abd represents
43 * the temporal evolution of (the standard deviation of) the process noise model. The
44 * first function is therefore the standard deviation along the LOF X axis, the second
45 * function represents the standard deviation along the LOF Y axis...
46 * This allows to set up simply a process noise representing an uncertainty that grows
47 * mainly along the track. The 6x6 upper left part of output matrix will however not be
48 * diagonal as it will be converted to the same inertial frame and orbit type as the
49 * {@link SpacecraftState state} used by the {@link KalmanEstimator Kalman estimator}.
50 * </p>
51 * <p>
52 * The propagation parameters are not associated to a specific frame and are appended as
53 * is in the lower right part diagonal of the output matrix. This implies this simplified
54 * model does not include correlation between the parameters and the orbit, but only
55 * evolution of the parameters themselves. If such correlations are needed, users must
56 * set up a custom {@link CovarianceMatrixProvider covariance matrix provider}. In most
57 * cases, the parameters are constant and their evolution noise is always 0, so the
58 * functions can be set to {@code x -> 0}.
59 * </p>
60 * <p>
61 * This class always provides one initial noise matrix or initial covariance matrix and one process noise matrix.
62 * </p>
63 * <p>
64 * WARNING: as of release 9.2, this feature is still considered experimental
65 * </p>
66 * @author Luc Maisonobe
67 * @author Maxime Journot
68 * @since 9.2
69 */
70 public class UnivariateProcessNoise extends AbstractCovarianceMatrixProvider {
71
72 /** Local Orbital Frame (LOF) type used. */
73 private final LOFType lofType;
74
75 /** Position angle for the orbital process noise matrix. */
76 private final PositionAngle positionAngle;
77
78 /** Array of univariate functions for the six orbital parameters process noise evolution in LOF frame and Cartesian formalism. */
79 private final UnivariateFunction[] lofCartesianOrbitalParametersEvolution;
80
81 /** Array of univariate functions for the propagation parameters process noise evolution. */
82 private final UnivariateFunction[] propagationParametersEvolution;
83
84 /** Simple constructor.
85 * @param initialCovarianceMatrix initial covariance matrix
86 * @param lofType the LOF type used
87 * @param positionAngle the position angle used for the computation of the process noise
88 * @param lofCartesianOrbitalParametersEvolution Array of univariate functions for the six orbital parameters process noise evolution in LOF frame and Cartesian orbit type
89 * @param propagationParametersEvolution Array of univariate functions for the propagation parameters process noise evolution
90 * @throws OrekitException if lofOrbitalParametersEvolution array size is different from 6
91 */
92 public UnivariateProcessNoise(final RealMatrix initialCovarianceMatrix,
93 final LOFType lofType,
94 final PositionAngle positionAngle,
95 final UnivariateFunction[] lofCartesianOrbitalParametersEvolution,
96 final UnivariateFunction[] propagationParametersEvolution)
97 throws OrekitException {
98 super(initialCovarianceMatrix);
99 this.lofType = lofType;
100 this.positionAngle = positionAngle;
101 this.lofCartesianOrbitalParametersEvolution = lofCartesianOrbitalParametersEvolution;
102 this.propagationParametersEvolution = propagationParametersEvolution;
103
104 // Ensure that the orbital evolution array size is 6
105 if (lofCartesianOrbitalParametersEvolution.length != 6) {
106 throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
107 lofCartesianOrbitalParametersEvolution, 6);
108 }
109 }
110
111 /** Getter for the lofType.
112 * @return the lofType
113 */
114 public LOFType getLofType() {
115 return lofType;
116 }
117
118 /** Getter for the positionAngle.
119 * @return the positionAngle
120 */
121 public PositionAngle getPositionAngle() {
122 return positionAngle;
123 }
124
125 /** Getter for the lofCartesianOrbitalParametersEvolution.
126 * @return the lofCartesianOrbitalParametersEvolution
127 */
128 public UnivariateFunction[] getLofCartesianOrbitalParametersEvolution() {
129 return lofCartesianOrbitalParametersEvolution;
130 }
131
132 /** Getter for the propagationParametersEvolution.
133 * @return the propagationParametersEvolution
134 */
135 public UnivariateFunction[] getPropagationParametersEvolution() {
136 return propagationParametersEvolution;
137 }
138
139 /** {@inheritDoc} */
140 @Override
141 public RealMatrix getProcessNoiseMatrix(final SpacecraftState previous,
142 final SpacecraftState current) {
143
144 // Orbital parameters process noise matrix in inertial frame and current orbit type
145 final RealMatrix inertialOrbitalProcessNoiseMatrix = getInertialOrbitalProcessNoiseMatrix(previous, current);
146
147 if (propagationParametersEvolution.length == 0) {
148
149 // no propagation parameters contribution, just return the orbital part
150 return inertialOrbitalProcessNoiseMatrix;
151
152 } else {
153
154 // Propagation parameters process noise matrix
155 final RealMatrix propagationProcessNoiseMatrix = getPropagationProcessNoiseMatrix(previous, current);
156
157 // Concatenate the matrices
158 final int orbitalMatrixSize = lofCartesianOrbitalParametersEvolution.length;
159 final int propagationMatrixSize = propagationParametersEvolution.length;
160 final RealMatrix processNoiseMatrix = MatrixUtils.createRealMatrix(orbitalMatrixSize + propagationMatrixSize,
161 orbitalMatrixSize + propagationMatrixSize);
162 processNoiseMatrix.setSubMatrix(inertialOrbitalProcessNoiseMatrix.getData(), 0, 0);
163 processNoiseMatrix.setSubMatrix(propagationProcessNoiseMatrix.getData(), orbitalMatrixSize, orbitalMatrixSize);
164 return processNoiseMatrix;
165
166 }
167 }
168
169 /** Get the process noise for the six orbital parameters in current spacecraft inertial frame and current orbit type.
170 * @param previous previous state
171 * @param current current state
172 * @return physical (i.e. non normalized) orbital process noise matrix in inertial frame
173 */
174 private RealMatrix getInertialOrbitalProcessNoiseMatrix(final SpacecraftState previous,
175 final SpacecraftState current) {
176
177 // ΔT = duration in seconds from previous to current spacecraft state
178 final double deltaT = current.getDate().durationFrom(previous.getDate());
179
180 // Evaluate the functions, using ΔT as argument
181 final int lofOrbitalprocessNoiseLength = lofCartesianOrbitalParametersEvolution.length;
182 final double[] lofOrbitalProcessNoiseValues = new double[lofOrbitalprocessNoiseLength];
183
184 // The function return a value which dimension is that of a standard deviation
185 // It needs to be squared before being put in the process noise covariance matrix
186 for (int i = 0; i < lofOrbitalprocessNoiseLength; i++) {
187 final double functionValue = lofCartesianOrbitalParametersEvolution[i].value(deltaT);
188 lofOrbitalProcessNoiseValues[i] = functionValue * functionValue;
189 }
190
191 // Form the diagonal matrix in LOF frame and Cartesian formalism
192 final RealMatrix lofCartesianProcessNoiseMatrix = MatrixUtils.createRealDiagonalMatrix(lofOrbitalProcessNoiseValues);
193
194 // Get the rotation matrix from LOF to inertial frame
195 final double[][] lofToInertialRotation = lofType.rotationFromInertial(current.getPVCoordinates()).
196 revert().getMatrix();
197
198 // Jacobian from LOF to inertial frame
199 final RealMatrix jacLofToInertial = MatrixUtils.createRealMatrix(6, 6);
200 jacLofToInertial.setSubMatrix(lofToInertialRotation, 0, 0);
201 jacLofToInertial.setSubMatrix(lofToInertialRotation, 3, 3);
202
203 // FIXME: Trying to fix the transform from LOF to inertial
204 final Transform lofToInertial = lofType.transformFromInertial(current.getDate(), current.getPVCoordinates()).getInverse();
205 final Vector3D OM = lofToInertial.getRotationRate().negate();
206 final double[][] MOM = new double[3][3];
207 MOM[0][1] = -OM.getZ();
208 MOM[0][2] = OM.getY();
209 MOM[1][0] = OM.getZ();
210 MOM[1][2] = -OM.getX();
211 MOM[2][0] = -OM.getY();
212 MOM[2][1] = OM.getX();
213 //jacLofToInertial.setSubMatrix(MOM, 3, 0);
214 //debug
215
216 // Jacobian of orbit parameters with respect to Cartesian parameters
217 final double[][] dYdC = new double[6][6];
218 current.getOrbit().getJacobianWrtCartesian(positionAngle, dYdC);
219 final RealMatrix jacParametersWrtCartesian = MatrixUtils.createRealMatrix(dYdC);
220
221 // Complete Jacobian of the transformation
222 final RealMatrix jacobian = jacParametersWrtCartesian.multiply(jacLofToInertial);
223
224 // Return the orbital process noise matrix in inertial frame and proper orbit type
225 final RealMatrix inertialOrbitalProcessNoiseMatrix = jacobian.
226 multiply(lofCartesianProcessNoiseMatrix).
227 multiply(jacobian.transpose());
228 return inertialOrbitalProcessNoiseMatrix;
229 }
230
231 /** Get the process noise for the propagation parameters.
232 * @param previous previous state
233 * @param current current state
234 * @return physical (i.e. non normalized) propagation process noise matrix
235 */
236 private RealMatrix getPropagationProcessNoiseMatrix(final SpacecraftState previous,
237 final SpacecraftState current) {
238
239 // ΔT = duration from previous to current spacecraft state (in seconds)
240 final double deltaT = current.getDate().durationFrom(previous.getDate());
241
242 // Evaluate the functions, using ΔT as argument
243 final int propagationProcessNoiseLength = propagationParametersEvolution.length;
244 final double[] propagationProcessNoiseValues = new double[propagationProcessNoiseLength];
245
246 // The function return a value which dimension is that of a standard deviation
247 // It needs to be squared before being put in the process noise covariance matrix
248 for (int i = 0; i < propagationProcessNoiseLength; i++) {
249 final double functionValue = propagationParametersEvolution[i].value(deltaT);
250 propagationProcessNoiseValues[i] = functionValue * functionValue;
251 }
252
253 // Form the diagonal matrix corresponding to propagation parameters process noise
254 return MatrixUtils.createRealDiagonalMatrix(propagationProcessNoiseValues);
255 }
256
257 }