1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.leastsquares;
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.List;
24 import java.util.NoSuchElementException;
25
26 import org.hamcrest.MatcherAssert;
27 import org.hamcrest.Matchers;
28 import org.hipparchus.exception.LocalizedCoreFormats;
29 import org.hipparchus.geometry.euclidean.threed.Vector3D;
30 import org.hipparchus.util.FastMath;
31 import org.junit.jupiter.api.Assertions;
32 import org.junit.jupiter.api.Test;
33 import org.orekit.KeyValueFileParser;
34 import org.orekit.Utils;
35 import org.orekit.attitudes.AttitudeProvider;
36 import org.orekit.bodies.CelestialBody;
37 import org.orekit.bodies.OneAxisEllipsoid;
38 import org.orekit.errors.OrekitException;
39 import org.orekit.estimation.common.AbstractOrbitDetermination;
40 import org.orekit.estimation.common.ParameterKey;
41 import org.orekit.estimation.common.ResultBatchLeastSquares;
42 import org.orekit.forces.drag.DragSensitive;
43 import org.orekit.forces.gravity.potential.GravityFieldFactory;
44 import org.orekit.forces.gravity.potential.ICGEMFormatReader;
45 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
46 import org.orekit.forces.radiation.RadiationSensitive;
47 import org.orekit.models.earth.atmosphere.Atmosphere;
48 import org.orekit.orbits.EquinoctialOrbit;
49 import org.orekit.orbits.Orbit;
50 import org.orekit.orbits.OrbitType;
51 import org.orekit.propagation.PropagationType;
52 import org.orekit.propagation.conversion.DSSTPropagatorBuilder;
53 import org.orekit.propagation.conversion.ODEIntegratorBuilder;
54 import org.orekit.propagation.semianalytical.dsst.forces.DSSTAtmosphericDrag;
55 import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
56 import org.orekit.propagation.semianalytical.dsst.forces.DSSTSolarRadiationPressure;
57 import org.orekit.propagation.semianalytical.dsst.forces.DSSTTesseral;
58 import org.orekit.propagation.semianalytical.dsst.forces.DSSTThirdBody;
59 import org.orekit.propagation.semianalytical.dsst.forces.DSSTZonal;
60 import org.orekit.utils.Constants;
61 import org.orekit.utils.IERSConventions;
62 import org.orekit.utils.ParameterDriver;
63
64 public class DSSTOrbitDeterminationTest extends AbstractOrbitDetermination<DSSTPropagatorBuilder> {
65
66
67 private UnnormalizedSphericalHarmonicsProvider gravityField;
68
69
70 private PropagationType propagationType;
71
72
73 private PropagationType stateType;
74
75
76 @Override
77 protected void createGravityField(final KeyValueFileParser<ParameterKey> parser)
78 throws NoSuchElementException {
79
80 final int degree = parser.getInt(ParameterKey.CENTRAL_BODY_DEGREE);
81 final int order = FastMath.min(degree, parser.getInt(ParameterKey.CENTRAL_BODY_ORDER));
82 gravityField = GravityFieldFactory.getUnnormalizedProvider(degree, order);
83 }
84
85
86 @Override
87 protected double getMu() {
88 return gravityField.getMu();
89 }
90
91
92 @Override
93 protected DSSTPropagatorBuilder createPropagatorBuilder(final Orbit referenceOrbit,
94 final ODEIntegratorBuilder builder,
95 final double positionScale) {
96 final EquinoctialOrbit equiOrbit = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(referenceOrbit);
97 return new DSSTPropagatorBuilder(equiOrbit, builder, positionScale, propagationType, stateType);
98 }
99
100
101 @Override
102 protected void setMass(final DSSTPropagatorBuilder propagatorBuilder,
103 final double mass) {
104 propagatorBuilder.setMass(mass);
105 }
106
107
108 @Override
109 protected List<ParameterDriver> setGravity(final DSSTPropagatorBuilder propagatorBuilder,
110 final OneAxisEllipsoid body) {
111
112
113 final DSSTForceModel tesseral = new DSSTTesseral(body.getBodyFrame(),
114 Constants.WGS84_EARTH_ANGULAR_VELOCITY, gravityField,
115 gravityField.getMaxDegree(), gravityField.getMaxOrder(), 4, 12,
116 gravityField.getMaxDegree(), gravityField.getMaxOrder(), 4);
117 propagatorBuilder.addForceModel(tesseral);
118
119
120 final DSSTForceModel zonal = new DSSTZonal(gravityField, gravityField.getMaxDegree(), 4,
121 2 * gravityField.getMaxDegree() + 1);
122 propagatorBuilder.addForceModel(zonal);
123
124
125 final List<ParameterDriver> drivers = new ArrayList<>();
126 drivers.addAll(tesseral.getParametersDrivers());
127 drivers.addAll(zonal.getParametersDrivers());
128 return drivers;
129
130 }
131
132
133 @Override
134 protected List<ParameterDriver> setOceanTides(final DSSTPropagatorBuilder propagatorBuilder,
135 final IERSConventions conventions,
136 final OneAxisEllipsoid body,
137 final int degree, final int order) {
138 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
139 "Ocean tides not implemented in DSST");
140 }
141
142
143 @Override
144 protected List<ParameterDriver> setSolidTides(final DSSTPropagatorBuilder propagatorBuilder,
145 final IERSConventions conventions,
146 final OneAxisEllipsoid body,
147 final CelestialBody[] solidTidesBodies) {
148 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
149 "Solid tides not implemented in DSST");
150 }
151
152
153 @Override
154 protected List<ParameterDriver> setThirdBody(final DSSTPropagatorBuilder propagatorBuilder,
155 final CelestialBody thirdBody) {
156 final DSSTForceModel thirdBodyModel = new DSSTThirdBody(thirdBody, gravityField.getMu());
157 propagatorBuilder.addForceModel(thirdBodyModel);
158 return thirdBodyModel.getParametersDrivers();
159 }
160
161
162 @Override
163 protected List<ParameterDriver> setDrag(final DSSTPropagatorBuilder propagatorBuilder,
164 final Atmosphere atmosphere, final DragSensitive spacecraft) {
165 final DSSTForceModel dragModel = new DSSTAtmosphericDrag(atmosphere, spacecraft, gravityField.getMu());
166 propagatorBuilder.addForceModel(dragModel);
167 return dragModel.getParametersDrivers();
168 }
169
170
171 @Override
172 protected List<ParameterDriver> setSolarRadiationPressure(final DSSTPropagatorBuilder propagatorBuilder, final CelestialBody sun,
173 final OneAxisEllipsoid body, final RadiationSensitive spacecraft) {
174 final DSSTForceModel srpModel = new DSSTSolarRadiationPressure(sun, body, spacecraft, gravityField.getMu());
175 propagatorBuilder.addForceModel(srpModel);
176 return srpModel.getParametersDrivers();
177 }
178
179
180 @Override
181 protected List<ParameterDriver> setAlbedoInfrared(final DSSTPropagatorBuilder propagatorBuilder,
182 final CelestialBody sun, final double equatorialRadius,
183 final double angularResolution,
184 final RadiationSensitive spacecraft) {
185 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
186 "Albedo and infrared not implemented in DSST");
187 }
188
189
190 @Override
191 protected List<ParameterDriver> setRelativity(final DSSTPropagatorBuilder propagatorBuilder) {
192 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
193 "Albedo and infrared not implemented in DSST");
194 }
195
196
197 @Override
198 protected List<ParameterDriver> setPolynomialAcceleration(final DSSTPropagatorBuilder propagatorBuilder,
199 final String name, final Vector3D direction, final int degree) {
200 throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
201 "Polynomial acceleration not implemented in DSST");
202 }
203
204
205 @Override
206 protected void setAttitudeProvider(final DSSTPropagatorBuilder propagatorBuilder,
207 final AttitudeProvider attitudeProvider) {
208 propagatorBuilder.setAttitudeProvider(attitudeProvider);
209 }
210
211
212
213
214
215
216
217
218 @Test
219 public void testLageos2()
220 throws URISyntaxException, IllegalArgumentException, IOException,
221 OrekitException {
222
223
224 final String inputPath = DSSTOrbitDeterminationTest.class.getClassLoader().getResource("orbit-determination/Lageos2/dsst_od_test_Lageos2.in").toURI().getPath();
225 final File input = new File(inputPath);
226
227
228 Utils.setDataRoot("orbit-determination/february-2016:potential/icgem-format");
229 GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("eigen-6s-truncated", true));
230
231
232 propagationType = PropagationType.OSCULATING;
233 stateType = PropagationType.OSCULATING;
234
235
236 ResultBatchLeastSquares odLageos2 = runBLS(input, false);
237
238
239
240 final double distanceAccuracy = 46.51;
241 final double velocityAccuracy = 1.126e-1;
242
243
244 final int numberOfIte = 5;
245 final int numberOfEval = 5;
246
247 Assertions.assertEquals(numberOfIte, odLageos2.getNumberOfIteration());
248 Assertions.assertEquals(numberOfEval, odLageos2.getNumberOfEvaluation());
249
250
251 final Vector3D estimatedPos = odLageos2.getEstimatedPV().getPosition();
252 final Vector3D estimatedVel = odLageos2.getEstimatedPV().getVelocity();
253
254
255 final Vector3D refPos = new Vector3D(7526994.072, -9646309.832, 1464110.239);
256 final Vector3D refVel = new Vector3D(3033.794, 1715.265, -4447.659);
257 final double dP = Vector3D.distance(refPos, estimatedPos);
258 final double dV = Vector3D.distance(refVel, estimatedVel);
259 Assertions.assertEquals(0.0, dP, distanceAccuracy);
260 Assertions.assertEquals(0.0, dV, velocityAccuracy);
261
262
263 final long nbRange = 95;
264 final double[] RefStatRange = { -28.3161, 58.490, 0.0, 14.857 };
265 Assertions.assertEquals(nbRange, odLageos2.getRangeStat().getN());
266 MatcherAssert.assertThat(odLageos2.getRangeStat().getMin(),
267 Matchers.greaterThan(RefStatRange[0]));
268 Assertions.assertEquals(RefStatRange[0], odLageos2.getRangeStat().getMin(), 1.0e-3);
269 Assertions.assertEquals(RefStatRange[1], odLageos2.getRangeStat().getMax(), 1.0e-3);
270 Assertions.assertEquals(RefStatRange[2], odLageos2.getRangeStat().getMean(), 1.0e-3);
271 Assertions.assertEquals(RefStatRange[3], odLageos2.getRangeStat().getStandardDeviation(), 1.0e-3);
272 }
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 @Test
290 public void testGNSS()
291 throws URISyntaxException, IllegalArgumentException, IOException, OrekitException {
292
293
294 final String inputPath = DSSTOrbitDeterminationTest.class.getClassLoader().getResource("orbit-determination/GNSS/dsst_od_test_GPS07.in").toURI().getPath();
295 final File input = new File(inputPath);
296
297
298 Utils.setDataRoot("orbit-determination/february-2016:potential/icgem-format");
299 GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("eigen-6s-truncated", true));
300
301
302 propagationType = PropagationType.OSCULATING;
303 stateType = PropagationType.OSCULATING;
304
305
306 ResultBatchLeastSquares odGNSS = runBLS(input, false);
307
308
309
310 final double distanceAccuracy = 6.052;
311 final double velocityAccuracy = 2.48e-3;
312
313
314 final int numberOfIte = 3;
315 final int numberOfEval = 4;
316
317 Assertions.assertEquals(numberOfIte, odGNSS.getNumberOfIteration());
318 Assertions.assertEquals(numberOfEval, odGNSS.getNumberOfEvaluation());
319
320
321 final Vector3D estimatedPos = odGNSS.getEstimatedPV().getPosition();
322 final Vector3D estimatedVel = odGNSS.getEstimatedPV().getVelocity();
323 final Vector3D refPos = new Vector3D(-2747606.680868164, 22572091.30648564, 13522761.402325712);
324 final Vector3D refVel = new Vector3D(-2729.5151218788005, 1142.6629459030657, -2523.9055974487947);
325 Assertions.assertEquals(0.0, Vector3D.distance(refPos, estimatedPos), distanceAccuracy);
326 Assertions.assertEquals(0.0, Vector3D.distance(refVel, estimatedVel), velocityAccuracy);
327
328
329 final long nbRange = 4009;
330 final double[] RefStatRange = { -3.480, 2.608, 0.0, 0.836 };
331 Assertions.assertEquals(nbRange, odGNSS.getRangeStat().getN());
332 Assertions.assertEquals(RefStatRange[0], odGNSS.getRangeStat().getMin(), 1.0e-3);
333 Assertions.assertEquals(RefStatRange[1], odGNSS.getRangeStat().getMax(), 1.0e-3);
334 Assertions.assertEquals(RefStatRange[2], odGNSS.getRangeStat().getMean(), 1.0e-3);
335 Assertions.assertEquals(RefStatRange[3], odGNSS.getRangeStat().getStandardDeviation(), 1.0e-3);
336 }
337 }