1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation;
18
19 import org.hipparchus.geometry.euclidean.threed.Vector3D;
20 import org.hipparchus.linear.MatrixUtils;
21 import org.hipparchus.linear.RealMatrix;
22 import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer.Optimum;
23 import org.hipparchus.util.FastMath;
24 import org.junit.jupiter.api.Assertions;
25 import org.orekit.Utils;
26 import org.orekit.bodies.CelestialBodyFactory;
27 import org.orekit.bodies.OneAxisEllipsoid;
28 import org.orekit.data.DataContext;
29 import org.orekit.estimation.leastsquares.BatchLSEstimator;
30 import org.orekit.estimation.measurements.EstimatedMeasurement;
31 import org.orekit.estimation.measurements.MeasurementCreator;
32 import org.orekit.estimation.measurements.ObservedMeasurement;
33 import org.orekit.estimation.sequential.KalmanEstimator;
34 import org.orekit.forces.gravity.potential.AstronomicalAmplitudeReader;
35 import org.orekit.forces.gravity.potential.FESCHatEpsilonReader;
36 import org.orekit.forces.gravity.potential.GRGSFormatReader;
37 import org.orekit.forces.gravity.potential.GravityFieldFactory;
38 import org.orekit.forces.gravity.potential.OceanLoadDeformationCoefficients;
39 import org.orekit.frames.EOPHistory;
40 import org.orekit.frames.FramesFactory;
41 import org.orekit.models.earth.displacement.StationDisplacement;
42 import org.orekit.models.earth.displacement.TidalDisplacement;
43 import org.orekit.orbits.KeplerianOrbit;
44 import org.orekit.orbits.Orbit;
45 import org.orekit.orbits.PositionAngleType;
46 import org.orekit.propagation.Propagator;
47 import org.orekit.propagation.conversion.PropagatorBuilder;
48 import org.orekit.time.AbsoluteDate;
49 import org.orekit.time.TimeScalesFactory;
50 import org.orekit.utils.Constants;
51 import org.orekit.utils.IERSConventions;
52 import org.orekit.utils.ParameterDriver;
53
54 import java.util.Arrays;
55 import java.util.List;
56 import java.util.Map;
57
58
59 public class KeplerianEstimationTestUtils {
60
61 public static KeplerianContext eccentricContext(final String dataRoot) {
62
63 Utils.setDataRoot(dataRoot);
64 KeplerianContext context = new KeplerianContext();
65 context.conventions = IERSConventions.IERS_2010;
66 context.earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
67 Constants.WGS84_EARTH_FLATTENING,
68 FramesFactory.getITRF(context.conventions, true));
69 context.sun = CelestialBodyFactory.getSun();
70 context.moon = CelestialBodyFactory.getMoon();
71 final EOPHistory eopHistory = FramesFactory.getEOPHistory(context.conventions, true);
72 context.utc = TimeScalesFactory.getUTC();
73 context.ut1 = TimeScalesFactory.getUT1(eopHistory);
74 context.displacements = new StationDisplacement[] {
75 new TidalDisplacement(Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS,
76 Constants.JPL_SSD_SUN_EARTH_PLUS_MOON_MASS_RATIO,
77 Constants.JPL_SSD_EARTH_MOON_MASS_RATIO,
78 context.sun, context.moon,
79 context.conventions, false)
80 };
81 GravityFieldFactory.addPotentialCoefficientsReader(new GRGSFormatReader("grim4s4_gr", true));
82 AstronomicalAmplitudeReader aaReader =
83 new AstronomicalAmplitudeReader("hf-fes2004.dat", 5, 2, 3, 1.0);
84 DataContext.getDefault().getDataProvidersManager().feed(aaReader.getSupportedNames(), aaReader);
85 Map<Integer, Double> map = aaReader.getAstronomicalAmplitudesMap();
86 GravityFieldFactory.addOceanTidesReader(new FESCHatEpsilonReader("fes2004-7x7.dat",
87 0.01, FastMath.toRadians(1.0),
88 OceanLoadDeformationCoefficients.IERS_2010,
89 map));
90 context.initialOrbit = new KeplerianOrbit(15000000.0, 0.125, 1.25,
91 0.250, 1.375, 0.0625, PositionAngleType.TRUE,
92 FramesFactory.getEME2000(),
93 new AbsoluteDate(2000, 2, 24, 11, 35, 47.0, context.utc),
94 Constants.WGS84_EARTH_MU);
95
96 context.stations = Arrays.asList(
97 context.createStation(-53.05388, -75.01551, 1750.0, "Isla Desolación"),
98 context.createStation( 62.29639, -7.01250, 880.0, "Slættaratindur")
99
100 );
101
102 return context;
103
104 }
105
106 public static Propagator createPropagator(final Orbit initialOrbit,
107 final PropagatorBuilder propagatorBuilder) {
108
109
110 double[] orbitArray = new double[6];
111 propagatorBuilder.getOrbitType().mapOrbitToArray(initialOrbit,
112 propagatorBuilder.getPositionAngleType(),
113 orbitArray, null);
114 for (int i = 0; i < orbitArray.length; ++i) {
115
116 propagatorBuilder.getOrbitalParametersDrivers().getDrivers().get(i).setValue(orbitArray[i], initialOrbit.getDate());
117 }
118
119 return propagatorBuilder.buildPropagator();
120
121 }
122
123 public static List<ObservedMeasurement<?>> createMeasurements(final Propagator propagator,
124 final MeasurementCreator creator,
125 final double startPeriod, final double endPeriod,
126 final double step) {
127
128 propagator.setStepHandler(step, creator);
129 final double period = propagator.getInitialState().getOrbit().getKeplerianPeriod();
130 final AbsoluteDate start = propagator.getInitialState().getDate().shiftedBy(startPeriod * period);
131 final AbsoluteDate end = propagator.getInitialState().getDate().shiftedBy(endPeriod * period);
132 propagator.propagate(start, end);
133
134 final List<ObservedMeasurement<?>> measurements = creator.getMeasurements();
135
136 for (final ObservedMeasurement<?> measurement : measurements) {
137 for (final ParameterDriver driver : measurement.getParametersDrivers()) {
138 if (driver.getReferenceDate() == null) {
139 driver.setReferenceDate(propagator.getInitialState().getDate());
140 }
141 }
142 }
143
144 return measurements;
145
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public static void checkFit(final KeplerianContext context, final BatchLSEstimator estimator,
164 final int iterations, final int evaluations,
165 final double expectedRMS, final double rmsEps,
166 final double expectedMax, final double maxEps,
167 final double expectedDeltaPos, final double posEps,
168 final double expectedDeltaVel, final double velEps) {
169
170 final Orbit estimatedOrbit = estimator.estimate()[0].getInitialState().getOrbit();
171 final Vector3D estimatedPosition = estimatedOrbit.getPosition();
172 final Vector3D estimatedVelocity = estimatedOrbit.getPVCoordinates().getVelocity();
173
174 Assertions.assertEquals(iterations, estimator.getIterationsCount());
175 Assertions.assertEquals(evaluations, estimator.getEvaluationsCount());
176 Optimum optimum = estimator.getOptimum();
177 Assertions.assertEquals(iterations, optimum.getIterations());
178 Assertions.assertEquals(evaluations, optimum.getEvaluations());
179
180 int k = 0;
181 double sum = 0;
182 double max = 0;
183 for (final Map.Entry<ObservedMeasurement<?>, EstimatedMeasurement<?>> entry :
184 estimator.getLastEstimations().entrySet()) {
185 final ObservedMeasurement<?> m = entry.getKey();
186 final EstimatedMeasurement<?> e = entry.getValue();
187 final double[] weight = m.getBaseWeight();
188 final double[] sigma = m.getTheoreticalStandardDeviation();
189 final double[] observed = m.getObservedValue();
190 final double[] theoretical = e.getEstimatedValue();
191 for (int i = 0; i < m.getDimension(); ++i) {
192 final double weightedResidual = weight[i] * (theoretical[i] - observed[i]) / sigma[i];
193 ++k;
194 sum += weightedResidual * weightedResidual;
195 max = FastMath.max(max, FastMath.abs(weightedResidual));
196 }
197 }
198
199 final double rms = FastMath.sqrt(sum / k);
200 final double deltaPos = Vector3D.distance(context.initialOrbit.getPosition(), estimatedPosition);
201 final double deltaVel = Vector3D.distance(context.initialOrbit.getPVCoordinates().getVelocity(), estimatedVelocity);
202 Assertions.assertEquals(expectedRMS,
203 rms,
204 rmsEps);
205 Assertions.assertEquals(expectedMax,
206 max,
207 maxEps);
208 Assertions.assertEquals(expectedDeltaPos,
209 deltaPos,
210 posEps);
211 Assertions.assertEquals(expectedDeltaVel,
212 deltaVel,
213 velEps);
214
215 }
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232 public static void checkKalmanFit(final KeplerianContext context, final KalmanEstimator kalman,
233 final List<ObservedMeasurement<?>> measurements,
234 final Orbit refOrbit, final PositionAngleType positionAngleType,
235 final double expectedDeltaPos, final double posEps,
236 final double expectedDeltaVel, final double velEps,
237 final double[] expectedSigmasPos,final double sigmaPosEps,
238 final double[] expectedSigmasVel,final double sigmaVelEps)
239 {
240 checkKalmanFit(context, kalman, measurements,
241 new Orbit[] { refOrbit },
242 new PositionAngleType[] {positionAngleType},
243 new double[] { expectedDeltaPos }, new double[] { posEps },
244 new double[] { expectedDeltaVel }, new double[] { velEps },
245 new double[][] { expectedSigmasPos }, new double[] { sigmaPosEps },
246 new double[][] { expectedSigmasVel }, new double[] { sigmaVelEps });
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264 public static void checkKalmanFit(final KeplerianContext context, final KalmanEstimator kalman,
265 final List<ObservedMeasurement<?>> measurements,
266 final Orbit[] refOrbit, final PositionAngleType[] positionAngleType,
267 final double[] expectedDeltaPos, final double[] posEps,
268 final double[] expectedDeltaVel, final double []velEps,
269 final double[][] expectedSigmasPos,final double[] sigmaPosEps,
270 final double[][] expectedSigmasVel,final double[] sigmaVelEps)
271 {
272
273
274 Propagator[] estimated = kalman.processMeasurements(measurements);
275
276
277 Assertions.assertEquals(measurements.size(), kalman.getCurrentMeasurementNumber());
278
279 for (int k = 0; k < refOrbit.length; ++k) {
280
281 final Orbit estimatedOrbit = estimated[k].getInitialState().getOrbit();
282 final Vector3D estimatedPosition = estimatedOrbit.getPosition();
283 final Vector3D estimatedVelocity = estimatedOrbit.getPVCoordinates().getVelocity();
284
285
286 final RealMatrix estimatedP = kalman.getPhysicalEstimatedCovarianceMatrix();
287
288
289
290 final double[][] dCdY = new double[6][6];
291 estimatedOrbit.getJacobianWrtParameters(positionAngleType[k], dCdY);
292 final RealMatrix Jacobian = MatrixUtils.createRealMatrix(dCdY);
293 final RealMatrix estimatedCartesianP =
294 Jacobian.
295 multiply(estimatedP.getSubMatrix(0, 5, 0, 5)).
296 multiply(Jacobian.transpose());
297
298
299 final double[] sigmas = new double[6];
300 for (int i = 0; i < 6; i++) {
301 sigmas[i] = FastMath.sqrt(estimatedCartesianP.getEntry(i, i));
302 }
303
304
305 final double deltaPosK = Vector3D.distance(refOrbit[k].getPosition(), estimatedPosition);
306 final double deltaVelK = Vector3D.distance(refOrbit[k].getPVCoordinates().getVelocity(), estimatedVelocity);
307 Assertions.assertEquals(expectedDeltaPos[k], deltaPosK, posEps[k]);
308 Assertions.assertEquals(expectedDeltaVel[k], deltaVelK, velEps[k]);
309
310 for (int i = 0; i < 3; i++) {
311 System.out.println(sigmas[i]);
312 System.out.println(sigmas[i+3]);
313 Assertions.assertEquals(expectedSigmasPos[k][i], sigmas[i], sigmaPosEps[k]);
314 Assertions.assertEquals(expectedSigmasVel[k][i], sigmas[i+3], sigmaVelEps[k]);
315 }
316 }
317 }
318
319 }
320