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.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.IdentityHashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.hipparchus.linear.Array2DRowRealMatrix;
28 import org.hipparchus.linear.ArrayRealVector;
29 import org.hipparchus.linear.MatrixUtils;
30 import org.hipparchus.linear.RealMatrix;
31 import org.hipparchus.linear.RealVector;
32 import org.hipparchus.optim.nonlinear.vector.leastsquares.MultivariateJacobianFunction;
33 import org.hipparchus.util.FastMath;
34 import org.hipparchus.util.Incrementor;
35 import org.hipparchus.util.Pair;
36 import org.orekit.estimation.measurements.EstimatedMeasurement;
37 import org.orekit.estimation.measurements.ObservedMeasurement;
38 import org.orekit.orbits.Orbit;
39 import org.orekit.propagation.Propagator;
40 import org.orekit.propagation.PropagatorsParallelizer;
41 import org.orekit.propagation.SpacecraftState;
42 import org.orekit.propagation.conversion.OrbitDeterminationPropagatorBuilder;
43 import org.orekit.propagation.integration.AbstractJacobiansMapper;
44 import org.orekit.propagation.sampling.MultiSatStepHandler;
45 import org.orekit.time.AbsoluteDate;
46 import org.orekit.time.ChronologicalComparator;
47 import org.orekit.utils.ParameterDriver;
48 import org.orekit.utils.ParameterDriversList;
49 import org.orekit.utils.ParameterDriversList.DelegatingDriver;
50
51
52
53
54
55
56
57
58
59 public abstract class AbstractBatchLSModel implements MultivariateJacobianFunction {
60
61
62 private final OrbitDeterminationPropagatorBuilder[] builders;
63
64
65 private final ParameterDriversList[] estimatedPropagationParameters;
66
67
68 private final ParameterDriversList estimatedMeasurementsParameters;
69
70
71 private final List<ObservedMeasurement<?>> measurements;
72
73
74 private final int[] orbitsStartColumns;
75
76
77 private final int[] orbitsEndColumns;
78
79
80 private final Map<String, Integer> propagationParameterColumns;
81
82
83 private final Map<String, Integer> measurementParameterColumns;
84
85
86 private final Map<ObservedMeasurement<?>, EstimatedMeasurement<?>> evaluations;
87
88
89 private final ModelObserver observer;
90
91
92 private Incrementor evaluationsCounter;
93
94
95 private Incrementor iterationsCounter;
96
97
98 private AbsoluteDate firstDate;
99
100
101 private AbsoluteDate lastDate;
102
103
104 private final boolean forwardPropagation;
105
106
107 private RealVector value;
108
109
110 private final AbstractJacobiansMapper[] mappers;
111
112
113 private RealMatrix jacobian;
114
115
116
117
118
119
120
121
122
123 public AbstractBatchLSModel(final OrbitDeterminationPropagatorBuilder[] propagatorBuilders,
124 final List<ObservedMeasurement<?>> measurements,
125 final ParameterDriversList estimatedMeasurementsParameters,
126 final AbstractJacobiansMapper[] mappers,
127 final ModelObserver observer) {
128
129 this.builders = propagatorBuilders.clone();
130 this.measurements = measurements;
131 this.estimatedMeasurementsParameters = estimatedMeasurementsParameters;
132 this.measurementParameterColumns = new HashMap<>(estimatedMeasurementsParameters.getDrivers().size());
133 this.estimatedPropagationParameters = new ParameterDriversList[builders.length];
134 this.evaluations = new IdentityHashMap<>(measurements.size());
135 this.observer = observer;
136 this.mappers = mappers.clone();
137
138
139 int rows = 0;
140 for (final ObservedMeasurement<?> measurement : measurements) {
141 rows += measurement.getDimension();
142 }
143
144 this.orbitsStartColumns = new int[builders.length];
145 this.orbitsEndColumns = new int[builders.length];
146 int columns = 0;
147 for (int i = 0; i < builders.length; ++i) {
148 this.orbitsStartColumns[i] = columns;
149 for (final ParameterDriver driver : builders[i].getOrbitalParametersDrivers().getDrivers()) {
150 if (driver.isSelected()) {
151 ++columns;
152 }
153 }
154 this.orbitsEndColumns[i] = columns;
155 }
156
157
158 final List<String> estimatedPropagationParametersNames = new ArrayList<>();
159 for (int i = 0; i < builders.length; ++i) {
160
161
162 for (final DelegatingDriver delegating : getSelectedPropagationDriversForBuilder(i).getDrivers()) {
163 final String driverName = delegating.getName();
164
165 if (!estimatedPropagationParametersNames.contains(driverName)) {
166 estimatedPropagationParametersNames.add(driverName);
167 }
168 }
169 }
170
171 propagationParameterColumns = new HashMap<>(estimatedPropagationParametersNames.size());
172 for (final String driverName : estimatedPropagationParametersNames) {
173 propagationParameterColumns.put(driverName, columns);
174 ++columns;
175 }
176
177
178 for (final ParameterDriver parameter : estimatedMeasurementsParameters.getDrivers()) {
179 measurementParameterColumns.put(parameter.getName(), columns);
180 ++columns;
181 }
182
183
184 value = new ArrayRealVector(rows);
185 jacobian = MatrixUtils.createRealMatrix(rows, columns);
186
187
188
189
190 final AbsoluteDate refDate = builders[0].getInitialOrbitDate();
191
192
193 measurements.sort(new ChronologicalComparator());
194 firstDate = measurements.get(0).getDate();
195 lastDate = measurements.get(measurements.size() - 1).getDate();
196
197
198 if (FastMath.abs(refDate.durationFrom(firstDate)) <= FastMath.abs(refDate.durationFrom(lastDate))) {
199
200 forwardPropagation = true;
201 } else {
202
203 forwardPropagation = false;
204 }
205 }
206
207
208
209
210 public void setEvaluationsCounter(final Incrementor evaluationsCounter) {
211 this.evaluationsCounter = evaluationsCounter;
212 }
213
214
215
216
217 public void setIterationsCounter(final Incrementor iterationsCounter) {
218 this.iterationsCounter = iterationsCounter;
219 }
220
221
222
223
224 public boolean isForwardPropagation() {
225 return forwardPropagation;
226 }
227
228
229
230
231
232 protected abstract AbstractJacobiansMapper configureDerivatives(Propagator propagators);
233
234
235
236
237
238
239
240
241
242 protected abstract Orbit configureOrbits(AbstractJacobiansMapper mapper, Propagator propagator);
243
244
245 @Override
246 public Pair<RealVector, RealMatrix> value(final RealVector point) {
247
248
249 final Propagator[] propagators = createPropagators(point);
250 final Orbit[] orbits = new Orbit[propagators.length];
251 for (int i = 0; i < propagators.length; ++i) {
252 mappers[i] = configureDerivatives(propagators[i]);
253 orbits[i] = configureOrbits(mappers[i], propagators[i]);
254 }
255 final PropagatorsParallelizer parallelizer =
256 new PropagatorsParallelizer(Arrays.asList(propagators), configureMeasurements(point));
257
258
259 evaluations.clear();
260 value.set(0.0);
261 for (int i = 0; i < jacobian.getRowDimension(); ++i) {
262 for (int j = 0; j < jacobian.getColumnDimension(); ++j) {
263 jacobian.setEntry(i, j, 0.0);
264 }
265 }
266
267
268 if (isForwardPropagation()) {
269
270 parallelizer.propagate(firstDate.shiftedBy(-1.0), lastDate.shiftedBy(+1.0));
271 } else {
272
273 parallelizer.propagate(lastDate.shiftedBy(+1.0), firstDate.shiftedBy(-1.0));
274 }
275
276 observer.modelCalled(orbits, evaluations);
277
278 return new Pair<RealVector, RealMatrix>(value, jacobian);
279
280 }
281
282
283
284
285
286 public ParameterDriversList getSelectedPropagationDriversForBuilder(final int iBuilder) {
287
288
289 if (estimatedPropagationParameters[iBuilder] == null) {
290
291
292 final ParameterDriversList selectedPropagationDrivers = new ParameterDriversList();
293 for (final DelegatingDriver delegating : builders[iBuilder].getPropagationParametersDrivers().getDrivers()) {
294 if (delegating.isSelected()) {
295 for (final ParameterDriver driver : delegating.getRawDrivers()) {
296 selectedPropagationDrivers.add(driver);
297 }
298 }
299 }
300
301
302
303 selectedPropagationDrivers.sort();
304
305
306 estimatedPropagationParameters[iBuilder] = selectedPropagationDrivers;
307 }
308 return estimatedPropagationParameters[iBuilder];
309 }
310
311
312
313
314
315 public Propagator[] createPropagators(final RealVector point) {
316
317 final Propagator[] propagators = new Propagator[builders.length];
318
319
320 for (int i = 0; i < builders.length; ++i) {
321
322
323 final int nbOrb = orbitsEndColumns[i] - orbitsStartColumns[i];
324
325
326 final ParameterDriversList selectedPropagationDrivers = getSelectedPropagationDriversForBuilder(i);
327 final int nbParams = selectedPropagationDrivers.getNbParams();
328
329
330 final double[] propagatorArray = new double[nbOrb + nbParams];
331
332
333 for (int j = 0; j < nbOrb; ++j) {
334 propagatorArray[j] = point.getEntry(orbitsStartColumns[i] + j);
335 }
336
337
338 for (int j = 0; j < nbParams; ++j) {
339 propagatorArray[nbOrb + j] =
340 point.getEntry(propagationParameterColumns.get(selectedPropagationDrivers.getDrivers().get(j).getName()));
341 }
342
343
344 propagators[i] = builders[i].buildPropagator(propagatorArray);
345 }
346
347 return propagators;
348
349 }
350
351
352
353
354
355 public void fetchEvaluatedMeasurement(final int index, final EstimatedMeasurement<?> evaluation) {
356
357
358 final SpacecraftState[] evaluationStates = evaluation.getStates();
359 final ObservedMeasurement<?> observedMeasurement = evaluation.getObservedMeasurement();
360
361
362 evaluations.put(observedMeasurement, evaluation);
363 if (evaluation.getStatus() == EstimatedMeasurement.Status.REJECTED) {
364 return;
365 }
366
367 final double[] evaluated = evaluation.getEstimatedValue();
368 final double[] observed = observedMeasurement.getObservedValue();
369 final double[] sigma = observedMeasurement.getTheoreticalStandardDeviation();
370 final double[] weight = evaluation.getObservedMeasurement().getBaseWeight();
371 for (int i = 0; i < evaluated.length; ++i) {
372 value.setEntry(index + i, weight[i] * (evaluated[i] - observed[i]) / sigma[i]);
373 }
374
375 for (int k = 0; k < evaluationStates.length; ++k) {
376
377 final int p = observedMeasurement.getSatellites().get(k).getPropagatorIndex();
378
379
380 final double[][] aCY = new double[6][6];
381 final Orbit currentOrbit = evaluationStates[k].getOrbit();
382 currentOrbit.getJacobianWrtParameters(builders[p].getPositionAngle(), aCY);
383 final RealMatrix dCdY = new Array2DRowRealMatrix(aCY, false);
384
385
386 final RealMatrix dMdC = new Array2DRowRealMatrix(evaluation.getStateDerivatives(k), false);
387 final RealMatrix dMdY = dMdC.multiply(dCdY);
388
389
390 mappers[p].analyticalDerivatives(evaluationStates[k]);
391
392
393 final double[][] aYY0 = new double[6][6];
394 mappers[p].getStateJacobian(evaluationStates[k], aYY0);
395 final RealMatrix dYdY0 = new Array2DRowRealMatrix(aYY0, false);
396 final RealMatrix dMdY0 = dMdY.multiply(dYdY0);
397 for (int i = 0; i < dMdY0.getRowDimension(); ++i) {
398 int jOrb = orbitsStartColumns[p];
399 for (int j = 0; j < dMdY0.getColumnDimension(); ++j) {
400 final ParameterDriver driver = builders[p].getOrbitalParametersDrivers().getDrivers().get(j);
401 if (driver.isSelected()) {
402 jacobian.setEntry(index + i, jOrb++,
403 weight[i] * dMdY0.getEntry(i, j) / sigma[i] * driver.getScale());
404 }
405 }
406 }
407
408
409 final ParameterDriversList selectedPropagationDrivers = getSelectedPropagationDriversForBuilder(p);
410 final int nbParams = selectedPropagationDrivers.getNbParams();
411 if ( nbParams > 0) {
412 final double[][] aYPp = new double[6][nbParams];
413 mappers[p].getParametersJacobian(evaluationStates[k], aYPp);
414 final RealMatrix dYdPp = new Array2DRowRealMatrix(aYPp, false);
415 final RealMatrix dMdPp = dMdY.multiply(dYdPp);
416 for (int i = 0; i < dMdPp.getRowDimension(); ++i) {
417 for (int j = 0; j < nbParams; ++j) {
418 final ParameterDriver delegating = selectedPropagationDrivers.getDrivers().get(j);
419 jacobian.addToEntry(index + i, propagationParameterColumns.get(delegating.getName()),
420 weight[i] * dMdPp.getEntry(i, j) / sigma[i] * delegating.getScale());
421 }
422 }
423 }
424 }
425
426 for (final ParameterDriver driver : observedMeasurement.getParametersDrivers()) {
427 if (driver.isSelected()) {
428 final double[] aMPm = evaluation.getParameterDerivatives(driver);
429 for (int i = 0; i < aMPm.length; ++i) {
430 jacobian.setEntry(index + i, measurementParameterColumns.get(driver.getName()),
431 weight[i] * aMPm[i] / sigma[i] * driver.getScale());
432 }
433 }
434 }
435
436 }
437
438
439
440
441
442 private MultiSatStepHandler configureMeasurements(final RealVector point) {
443
444
445 int index = orbitsEndColumns[builders.length - 1] + propagationParameterColumns.size();
446 for (final ParameterDriver parameter : estimatedMeasurementsParameters.getDrivers()) {
447 parameter.setNormalizedValue(point.getEntry(index++));
448 }
449
450
451 final List<PreCompensation> precompensated = new ArrayList<>();
452 for (final ObservedMeasurement<?> measurement : measurements) {
453 if (measurement.isEnabled()) {
454 precompensated.add(new PreCompensation(measurement, evaluations.get(measurement)));
455 }
456 }
457 precompensated.sort(new ChronologicalComparator());
458
459
460 firstDate = precompensated.get(0).getDate();
461 lastDate = precompensated.get(precompensated.size() - 1).getDate();
462
463
464 if (!forwardPropagation) {
465 Collections.reverse(precompensated);
466 }
467
468 return new MeasurementHandler(this, precompensated);
469
470 }
471
472
473
474
475 public int getIterationsCount() {
476 return iterationsCounter.getCount();
477 }
478
479
480
481
482 public int getEvaluationsCount() {
483 return evaluationsCounter.getCount();
484 }
485
486 }