1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.rugged.adjustment;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.LinkedHashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.hipparchus.analysis.differentiation.Gradient;
28 import org.hipparchus.linear.Array2DRowRealMatrix;
29 import org.hipparchus.linear.ArrayRealVector;
30 import org.hipparchus.linear.RealMatrix;
31 import org.hipparchus.linear.RealVector;
32 import org.hipparchus.optim.ConvergenceChecker;
33 import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresBuilder;
34 import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem;
35 import org.hipparchus.optim.nonlinear.vector.leastsquares.MultivariateJacobianFunction;
36 import org.hipparchus.optim.nonlinear.vector.leastsquares.ParameterValidator;
37 import org.hipparchus.util.Pair;
38 import org.orekit.rugged.adjustment.measurements.Observables;
39 import org.orekit.rugged.adjustment.measurements.SensorToSensorMapping;
40 import org.orekit.rugged.api.Rugged;
41 import org.orekit.rugged.errors.RuggedException;
42 import org.orekit.rugged.errors.RuggedMessages;
43 import org.orekit.rugged.linesensor.LineSensor;
44 import org.orekit.rugged.linesensor.SensorPixel;
45 import org.orekit.rugged.utils.SpacecraftToObservedBody;
46 import org.orekit.time.AbsoluteDate;
47 import org.orekit.utils.ParameterDriver;
48
49
50
51
52
53
54
55
56 public class InterSensorsOptimizationProblemBuilder extends OptimizationProblemBuilder {
57
58
59 private static final String TARGET = "Target";
60
61
62 private static final String WEIGHT = "Weight";
63
64
65 private Map<String, Rugged> ruggedMap;
66
67
68 private List<SensorToSensorMapping> sensorToSensorMappings;
69
70
71 private HashMap<String, double[] > targetAndWeight;
72
73
74
75
76
77
78 public InterSensorsOptimizationProblemBuilder(final List<LineSensor> sensors,
79 final Observables measurements, final Collection<Rugged> ruggedList) {
80
81 super(sensors, measurements);
82 this.ruggedMap = new LinkedHashMap<String, Rugged>();
83 for (final Rugged rugged : ruggedList) {
84 this.ruggedMap.put(rugged.getName(), rugged);
85 }
86 this.initMapping();
87 }
88
89
90 @Override
91 protected void initMapping() {
92
93 this.sensorToSensorMappings = new ArrayList<>();
94
95 for (final String ruggedNameA : this.ruggedMap.keySet()) {
96 for (final String ruggedNameB : this.ruggedMap.keySet()) {
97
98 for (final LineSensor sensorA : this.getSensors()) {
99 for (final LineSensor sensorB : this.getSensors()) {
100
101 final String sensorNameA = sensorA.getName();
102 final String sensorNameB = sensorB.getName();
103 final SensorToSensorMapping mapping = this.getMeasurements().getInterMapping(ruggedNameA, sensorNameA, ruggedNameB, sensorNameB);
104
105 if (mapping != null) {
106 this.sensorToSensorMappings.add(mapping);
107 }
108 }
109 }
110 }
111 }
112 }
113
114
115 @Override
116 protected void createTargetAndWeight() {
117
118 int n = 0;
119 for (final SensorToSensorMapping reference : this.sensorToSensorMappings) {
120 n += reference.getMapping().size();
121 }
122 if (n == 0) {
123 throw new RuggedException(RuggedMessages.NO_REFERENCE_MAPPINGS);
124 }
125
126 n = 2 * n;
127
128 final double[] target = new double[n];
129 final double[] weight = new double[n];
130
131 int k = 0;
132 for (final SensorToSensorMapping reference : this.sensorToSensorMappings) {
133
134
135 final double bodyConstraintWeight = reference.getBodyConstraintWeight();
136
137 int i = 0;
138 for (Iterator<Map.Entry<SensorPixel, SensorPixel>> gtIt = reference.getMapping().iterator(); gtIt.hasNext(); i++) {
139
140 if (i == reference.getMapping().size()) {
141 break;
142 }
143
144
145 final Double losDistance = reference.getLosDistance(i);
146
147 weight[k] = 1.0 - bodyConstraintWeight;
148 target[k++] = losDistance.doubleValue();
149
150
151 final Double bodyDistance = reference.getBodyDistance(i);
152 weight[k] = bodyConstraintWeight;
153 target[k++] = bodyDistance.doubleValue();
154 }
155 }
156
157 this.targetAndWeight = new HashMap<String, double[]>();
158 this.targetAndWeight.put(TARGET, target);
159 this.targetAndWeight.put(WEIGHT, weight);
160 }
161
162
163 @Override
164 protected MultivariateJacobianFunction createFunction() {
165
166
167 final MultivariateJacobianFunction model = point -> {
168
169
170 int i = 0;
171 for (final ParameterDriver driver : this.getDrivers()) {
172 driver.setNormalizedValue(point.getEntry(i++));
173 }
174
175 final double[] target = this.targetAndWeight.get(TARGET);
176
177
178 final RealVector value = new ArrayRealVector(target.length);
179 final RealMatrix jacobian = new Array2DRowRealMatrix(target.length, this.getNbParams());
180
181 int l = 0;
182 for (final SensorToSensorMapping reference : this.sensorToSensorMappings) {
183
184 final String ruggedNameA = reference.getRuggedNameA();
185 final String ruggedNameB = reference.getRuggedNameB();
186 final Rugged ruggedA = this.ruggedMap.get(ruggedNameA);
187 if (ruggedA == null) {
188 throw new RuggedException(RuggedMessages.INVALID_RUGGED_NAME);
189 }
190
191 final Rugged ruggedB = this.ruggedMap.get(ruggedNameB);
192 if (ruggedB == null) {
193 throw new RuggedException(RuggedMessages.INVALID_RUGGED_NAME);
194 }
195
196 for (final Map.Entry<SensorPixel, SensorPixel> mapping : reference.getMapping()) {
197
198 final SensorPixel spA = mapping.getKey();
199 final SensorPixel spB = mapping.getValue();
200
201 final LineSensor lineSensorB = ruggedB.getLineSensor(reference.getSensorNameB());
202 final LineSensor lineSensorA = ruggedA.getLineSensor(reference.getSensorNameA());
203
204 final AbsoluteDate dateA = lineSensorA.getDate(spA.getLineNumber());
205 final AbsoluteDate dateB = lineSensorB.getDate(spB.getLineNumber());
206
207 final double pixelA = spA.getPixelNumber();
208 final double pixelB = spB.getPixelNumber();
209
210 final SpacecraftToObservedBody scToBodyA = ruggedA.getScToBody();
211
212 final Gradient[] ilResult =
213 ruggedB.distanceBetweenLOSderivatives(lineSensorA, dateA, pixelA, scToBodyA,
214 lineSensorB, dateB, pixelB, this.getGenerator());
215
216
217 value.setEntry(l, ilResult[0].getValue());
218 value.setEntry(l + 1, ilResult[1].getValue());
219
220
221 final int[] orders = new int[this.getNbParams()];
222 int m = 0;
223
224 for (final ParameterDriver driver : this.getDrivers()) {
225 final double scale = driver.getScale();
226 orders[m] = 1;
227 jacobian.setEntry(l, m, ilResult[0].getPartialDerivative(orders) * scale);
228 jacobian.setEntry(l + 1, m, ilResult[1].getPartialDerivative(orders) * scale);
229 orders[m] = 0;
230 m++;
231 }
232
233 l += 2;
234 }
235 }
236
237
238 return new Pair<RealVector, RealMatrix>(value, jacobian);
239 };
240
241 return model;
242 }
243
244
245
246
247
248
249
250 @Override
251 public final LeastSquaresProblem build(final int maxEvaluations, final double convergenceThreshold) {
252
253 this.createTargetAndWeight();
254 final double[] target = this.targetAndWeight.get(TARGET);
255 final double[] start = this.createStartTab();
256 final ParameterValidator validator = this.createParameterValidator();
257 final ConvergenceChecker<LeastSquaresProblem.Evaluation> checker = this.createChecker(convergenceThreshold);
258 final MultivariateJacobianFunction model = this.createFunction();
259 return new LeastSquaresBuilder()
260 .lazyEvaluation(false).maxIterations(maxEvaluations)
261 .maxEvaluations(maxEvaluations).weight(null).start(start)
262 .target(target).parameterValidator(validator).checker(checker)
263 .model(model).build();
264 }
265 }