1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.sequential;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.net.URISyntaxException;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Locale;
26 import java.util.NoSuchElementException;
27
28 import org.hipparchus.exception.LocalizedCoreFormats;
29 import org.hipparchus.geometry.euclidean.threed.Vector3D;
30 import org.hipparchus.linear.MatrixUtils;
31 import org.hipparchus.linear.RealMatrix;
32 import org.hipparchus.ode.nonstiff.AdaptiveStepsizeIntegrator;
33 import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
34 import org.junit.Assert;
35 import org.junit.Test;
36 import org.orekit.KeyValueFileParser;
37 import org.orekit.Utils;
38 import org.orekit.attitudes.AttitudeProvider;
39 import org.orekit.bodies.CelestialBody;
40 import org.orekit.bodies.CelestialBodyFactory;
41 import org.orekit.bodies.OneAxisEllipsoid;
42 import org.orekit.errors.OrekitException;
43 import org.orekit.estimation.common.AbstractOrbitDetermination;
44 import org.orekit.estimation.common.ParameterKey;
45 import org.orekit.estimation.common.ResultKalman;
46 import org.orekit.forces.ForceModel;
47 import org.orekit.forces.drag.DragForce;
48 import org.orekit.forces.drag.DragSensitive;
49 import org.orekit.forces.drag.IsotropicDrag;
50 import org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel;
51 import org.orekit.forces.gravity.ThirdBodyAttraction;
52 import org.orekit.forces.gravity.potential.GravityFieldFactory;
53 import org.orekit.forces.gravity.potential.ICGEMFormatReader;
54 import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
55 import org.orekit.forces.radiation.IsotropicRadiationSingleCoefficient;
56 import org.orekit.forces.radiation.RadiationSensitive;
57 import org.orekit.forces.radiation.SolarRadiationPressure;
58 import org.orekit.frames.FramesFactory;
59 import org.orekit.frames.Transform;
60 import org.orekit.models.earth.atmosphere.Atmosphere;
61 import org.orekit.models.earth.atmosphere.HarrisPriester;
62 import org.orekit.orbits.CartesianOrbit;
63 import org.orekit.orbits.Orbit;
64 import org.orekit.orbits.OrbitType;
65 import org.orekit.orbits.PositionAngle;
66 import org.orekit.propagation.SpacecraftState;
67 import org.orekit.propagation.analytical.tle.TLE;
68 import org.orekit.propagation.analytical.tle.TLEConstants;
69 import org.orekit.propagation.conversion.ODEIntegratorBuilder;
70 import org.orekit.propagation.conversion.TLEPropagatorBuilder;
71 import org.orekit.propagation.numerical.NumericalPropagator;
72 import org.orekit.time.AbsoluteDate;
73 import org.orekit.time.TimeScalesFactory;
74 import org.orekit.utils.Constants;
75 import org.orekit.utils.IERSConventions;
76 import org.orekit.utils.PVCoordinates;
77 import org.orekit.utils.ParameterDriver;
78 import org.orekit.utils.ParameterDriversList.DelegatingDriver;
79 import org.orekit.utils.TimeStampedPVCoordinates;
80
81 public class TLEKalmanOrbitDeterminationTest extends AbstractOrbitDetermination<TLEPropagatorBuilder> {
82
83
84 public TLE templateTLE;
85
86
87 @Override
88 protected void createGravityField(final KeyValueFileParser<ParameterKey> parser)
89 throws NoSuchElementException {
90
91
92 }
93
94
95 @Override
96 protected double getMu() {
97 return TLEConstants.MU;
98 }
99
100
101 @Override
102 protected TLEPropagatorBuilder createPropagatorBuilder(final Orbit referenceOrbit,
103 final ODEIntegratorBuilder builder,
104 final double positionScale) {
105 return new TLEPropagatorBuilder(templateTLE, PositionAngle.MEAN,
106 positionScale);
107 }
108
109
110 @Override
111 protected void setMass(final TLEPropagatorBuilder propagatorBuilder,
112 final double mass) {
113
114
115 }
116
117
118 @Override
119 protected List<ParameterDriver> setGravity(final TLEPropagatorBuilder propagatorBuilder,
120 final OneAxisEllipsoid body) {
121 return Collections.emptyList();
122
123 }
124
125
126 @Override
127 protected List<ParameterDriver> setOceanTides(final TLEPropagatorBuilder propagatorBuilder,
128 final IERSConventions conventions,
129 final OneAxisEllipsoid body,
130 final int degree, final int order) {
131 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
132 "Ocean tides not implemented in DSST");
133 }
134
135
136 @Override
137 protected List<ParameterDriver> setSolidTides(final TLEPropagatorBuilder propagatorBuilder,
138 final IERSConventions conventions,
139 final OneAxisEllipsoid body,
140 final CelestialBody[] solidTidesBodies) {
141 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
142 "Solid tides not implemented in DSST");
143 }
144
145
146 @Override
147 protected List<ParameterDriver> setThirdBody(final TLEPropagatorBuilder propagatorBuilder,
148 final CelestialBody thirdBody) {
149 return Collections.emptyList();
150 }
151
152
153 @Override
154 protected List<ParameterDriver> setDrag(final TLEPropagatorBuilder propagatorBuilder,
155 final Atmosphere atmosphere, final DragSensitive spacecraft) {
156 return Collections.emptyList();
157 }
158
159
160 @Override
161 protected List<ParameterDriver> setSolarRadiationPressure(final TLEPropagatorBuilder propagatorBuilder, final CelestialBody sun,
162 final double equatorialRadius, final RadiationSensitive spacecraft) {
163 return Collections.emptyList();
164 }
165
166
167 @Override
168 protected List<ParameterDriver> setAlbedoInfrared(final TLEPropagatorBuilder propagatorBuilder,
169 final CelestialBody sun, final double equatorialRadius,
170 final double angularResolution,
171 final RadiationSensitive spacecraft) {
172 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
173 "Albedo and infrared not implemented in TLE Propagator");
174 }
175
176
177 @Override
178 protected List<ParameterDriver> setRelativity(final TLEPropagatorBuilder propagatorBuilder) {
179 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
180 "Relativity not implemented in TLE Propagator");
181 }
182
183
184 @Override
185 protected List<ParameterDriver> setPolynomialAcceleration(final TLEPropagatorBuilder propagatorBuilder,
186 final String name, final Vector3D direction, final int degree) {
187 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
188 "Polynomial acceleration not implemented in TLE Propagator");
189 }
190
191
192 @Override
193 protected void setAttitudeProvider(final TLEPropagatorBuilder propagatorBuilder,
194 final AttitudeProvider attitudeProvider) {
195 propagatorBuilder.setAttitudeProvider(attitudeProvider);
196 }
197
198 @Test
199
200 public void testLageos2() throws URISyntaxException, IOException {
201
202
203 final boolean print = false;
204
205
206 final String inputPath = KalmanNumericalOrbitDeterminationTest.class.getClassLoader().getResource("orbit-determination/Lageos2/tle_od_test_Lageos2.in").toURI().getPath();
207 final File input = new File(inputPath);
208
209
210 Utils.setDataRoot("orbit-determination/february-2016:potential/icgem-format");
211 GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("eigen-6s-truncated", true));
212
213
214 final String line1 = "1 22195U 92070B 16045.51027931 -.00000009 00000-0 00000+0 0 9990";
215 final String line2 = "2 22195 52.6508 132.9147 0137738 336.2706 1.6348 6.47294052551192";
216 templateTLE = new TLE(line1, line2);
217 templateTLE.getParametersDrivers().get(0).setSelected(false);
218
219
220 final OrbitType orbitType = OrbitType.CARTESIAN;
221
222
223 final RealMatrix cartesianOrbitalP = MatrixUtils.createRealDiagonalMatrix(new double [] {
224 1e4, 4e3, 1, 5e-3, 6e-5, 1e-4
225 });
226
227
228 final RealMatrix cartesianOrbitalQ = MatrixUtils.createRealDiagonalMatrix(new double [] {
229 1.e-4, 1.e-4, 1.e-4, 1.e-10, 1.e-10, 1.e-10
230 });
231
232
233 final RealMatrix measurementP = MatrixUtils.createRealDiagonalMatrix(new double [] {
234 1., 1., 1., 1.
235 });
236 final RealMatrix measurementQ = MatrixUtils.createRealDiagonalMatrix(new double [] {
237 1e-6, 1e-6, 1e-6, 1e-6
238 });
239
240
241 ResultKalman kalmanLageos2 = runKalman(input, orbitType, print,
242 cartesianOrbitalP, cartesianOrbitalQ,
243 null, null,
244 measurementP, measurementQ);
245
246
247
248 final double distanceAccuracy = 300.38;
249 final double velocityAccuracy = 0.148;
250
251
252
253
254 final int numberOfMeas = 95;
255 Assert.assertEquals(numberOfMeas, kalmanLageos2.getNumberOfMeasurements());
256
257
258 final TimeStampedPVCoordinates odPV = kalmanLageos2.getEstimatedPV();
259 final Vector3D estimatedPos = odPV.getPosition();
260 final Vector3D estimatedVel = odPV.getVelocity();
261
262
263 final Vector3D refPos0 = new Vector3D(-5532131.956902, 10025696.592156, -3578940.040009);
264 final Vector3D refVel0 = new Vector3D(-3871.275109, -607.880985, 4280.972530);
265 final TimeStampedPVCoordinates refPV = createRef(odPV.getDate(), refPos0, refVel0);
266
267
268 final Vector3D refPos = refPV.getPosition();
269 final Vector3D refVel = refPV.getVelocity();
270
271
272 final double dP = Vector3D.distance(refPos, estimatedPos);
273 final double dV = Vector3D.distance(refVel, estimatedVel);
274 Assert.assertEquals(0.0, dP, distanceAccuracy);
275 Assert.assertEquals(0.0, dV, velocityAccuracy);
276
277
278 if (print) {
279 System.out.println("Test performances:");
280 System.out.format("\t%-30s\n",
281 "ΔEstimated / Reference");
282 System.out.format(Locale.US, "\t%-10s %20.6f\n",
283 "ΔP [m]", dP);
284 System.out.format(Locale.US, "\t%-10s %20.6f\n",
285 "ΔV [m/s]", dV);
286 }
287
288
289 final List<DelegatingDriver> list = new ArrayList<DelegatingDriver>();
290 list.addAll(kalmanLageos2.getMeasurementsParameters().getDrivers());
291 sortParametersChanges(list);
292 final double[] stationOffSet = { 0.214786, 1.057400, -0.54545 };
293 final double rangeBias = 0.12005;
294 Assert.assertEquals(stationOffSet[0], list.get(0).getValue(), distanceAccuracy);
295 Assert.assertEquals(stationOffSet[1], list.get(1).getValue(), distanceAccuracy);
296 Assert.assertEquals(stationOffSet[2], list.get(2).getValue(), distanceAccuracy);
297 Assert.assertEquals(rangeBias, list.get(3).getValue(), distanceAccuracy);
298
299
300 final long nbRange = 95;
301
302
303 final double[] RefStatRange = { -70.790, 55.667, 5.873, 36.540 };
304 Assert.assertEquals(nbRange, kalmanLageos2.getRangeStat().getN());
305 Assert.assertEquals(RefStatRange[0], kalmanLageos2.getRangeStat().getMin(), distanceAccuracy);
306 Assert.assertEquals(RefStatRange[1], kalmanLageos2.getRangeStat().getMax(), distanceAccuracy);
307 Assert.assertEquals(RefStatRange[2], kalmanLageos2.getRangeStat().getMean(), distanceAccuracy);
308 Assert.assertEquals(RefStatRange[3], kalmanLageos2.getRangeStat().getStandardDeviation(), distanceAccuracy);
309
310 }
311
312 @Test
313
314 public void testGNSS() throws URISyntaxException, IOException {
315
316
317 final boolean print = false;
318
319
320 final String inputPath = KalmanNumericalOrbitDeterminationTest.class.getClassLoader().getResource("orbit-determination/analytical/tle_od_test_GPS07.in").toURI().getPath();
321 final File input = new File(inputPath);
322
323
324 Utils.setDataRoot("orbit-determination/february-2016:potential/icgem-format");
325 GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("eigen-6s-truncated", true));
326
327
328 final String line1 = "1 32711U 08012A 16044.40566018 -.00000039 +00000-0 +00000-0 0 9993";
329 final String line2 = "2 32711 055.4362 301.3402 0091581 207.7162 151.8496 02.00563594058026";
330 templateTLE = new TLE(line1, line2);
331 templateTLE.getParametersDrivers().get(0).setSelected(false);
332
333
334 final OrbitType orbitType = OrbitType.CARTESIAN;
335
336
337 final RealMatrix cartesianOrbitalP = MatrixUtils.createRealDiagonalMatrix(new double [] {
338 1e4, 4e3, 1, 5e-3, 6e-5, 1e-4
339 });
340
341
342 final RealMatrix cartesianOrbitalQ = MatrixUtils.createRealDiagonalMatrix(new double [] {
343 1.e-4, 1.e-4, 1.e-4, 1.e-10, 1.e-10, 1.e-10
344 });
345
346
347 final RealMatrix measurementP = MatrixUtils.createRealDiagonalMatrix(new double [] {
348 1., 1., 1., 1., 1., 1.
349 });
350 final RealMatrix measurementQ = MatrixUtils.createRealDiagonalMatrix(new double [] {
351 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6
352 });
353
354
355 ResultKalman kalmanGNSS = runKalman(input, orbitType, print,
356 cartesianOrbitalP, cartesianOrbitalQ,
357 null, null,
358 measurementP, measurementQ);
359
360
361
362 final double distanceAccuracy = 67.33;
363
364
365
366
367 final int numberOfMeas = 661;
368 Assert.assertEquals(numberOfMeas, kalmanGNSS.getNumberOfMeasurements());
369
370
371 TimeStampedPVCoordinates odPV = kalmanGNSS.getEstimatedPV();
372 final Transform transform = FramesFactory.getTEME().getTransformTo(FramesFactory.getGCRF(), odPV.getDate());
373 odPV = transform.transformPVCoordinates(odPV);
374 final Vector3D estimatedPos = odPV.getPosition();
375
376
377 final Vector3D refPos = new Vector3D(2167703.453226041, 19788555.311260417, 17514805.616900872);
378
379
380 final double dP = Vector3D.distance(refPos, estimatedPos);
381 Assert.assertEquals(0.0, dP, distanceAccuracy);
382
383
384 if (print) {
385 System.out.println("Test performances:");
386 System.out.format("\t%-30s\n",
387 "ΔEstimated / Reference");
388 System.out.format(Locale.US, "\t%-10s %20.6f\n",
389 "ΔP [m]", dP);
390 }
391
392
393 final long nbRange = 8211;
394
395 final double[] RefStatRange = { -44.073, 51.349, 0.242, 8.602 };
396 Assert.assertEquals(nbRange, kalmanGNSS.getRangeStat().getN());
397 Assert.assertEquals(RefStatRange[0], kalmanGNSS.getRangeStat().getMin(), distanceAccuracy);
398 Assert.assertEquals(RefStatRange[1], kalmanGNSS.getRangeStat().getMax(), distanceAccuracy);
399 Assert.assertEquals(RefStatRange[2], kalmanGNSS.getRangeStat().getMean(), distanceAccuracy);
400 Assert.assertEquals(RefStatRange[3], kalmanGNSS.getRangeStat().getStandardDeviation(), distanceAccuracy);
401
402 }
403
404
405 public TimeStampedPVCoordinates createRef(final AbsoluteDate date, final Vector3D refPos0, final Vector3D refVel0) {
406
407
408 final AbsoluteDate initDate = new AbsoluteDate(2016, 02, 14, 12, 14, 48.132, TimeScalesFactory.getUTC());
409 final CartesianOrbit initOrbit= new CartesianOrbit(new PVCoordinates(refPos0, refVel0), FramesFactory.getEME2000(), initDate, TLEConstants.MU);
410 final SpacecraftState initState = new SpacecraftState(initOrbit);
411
412
413 double[][] tolerance = NumericalPropagator.tolerances(0.001, initOrbit, OrbitType.CARTESIAN);
414 AdaptiveStepsizeIntegrator integrator =
415 new DormandPrince853Integrator(0.001, 200, tolerance[0], tolerance[1]);
416 integrator.setInitialStepSize(60);
417 final NumericalPropagator propagator = new NumericalPropagator(integrator);
418 propagator.setInitialState(initState);
419
420
421 final int degree = 20;
422 final int order = 20;
423 final double spacecraftArea = 1.0;
424 final double spacecraftDragCoefficient = 2.0;
425 final double spacecraftReflectionCoefficient = 2.0;
426
427
428 final OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
429 Constants.WGS84_EARTH_FLATTENING,
430 FramesFactory.getITRF(IERSConventions.IERS_2010, true));
431 final NormalizedSphericalHarmonicsProvider harmonicsGravityProvider = GravityFieldFactory.getNormalizedProvider(degree, order);
432 propagator.addForceModel(new HolmesFeatherstoneAttractionModel(earth.getBodyFrame(), harmonicsGravityProvider));
433
434
435 propagator.addForceModel(new ThirdBodyAttraction(CelestialBodyFactory.getSun()));
436 propagator.addForceModel(new ThirdBodyAttraction(CelestialBodyFactory.getMoon()));
437
438
439 ForceModel drag = new DragForce(new HarrisPriester(CelestialBodyFactory.getSun(), earth),
440 new IsotropicDrag(spacecraftArea, spacecraftDragCoefficient));
441 propagator.addForceModel(drag);
442
443
444 propagator.addForceModel(new SolarRadiationPressure(CelestialBodyFactory.getSun(),
445 earth.getEquatorialRadius(),
446 new IsotropicRadiationSingleCoefficient(spacecraftArea, spacecraftReflectionCoefficient)));
447
448
449 TimeStampedPVCoordinates endPV = propagator.propagate(date).getPVCoordinates();
450 final Transform transform = FramesFactory.getEME2000().getTransformTo(FramesFactory.getTEME(), date);
451 endPV = transform.transformPVCoordinates(endPV);
452 return endPV;
453 }
454 }