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.DerivativeStructure;
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<SensorToSensorMapping>();
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()) break;
141
142
143 final Double losDistance = reference.getLosDistance(i);
144
145 weight[k] = 1.0 - bodyConstraintWeight;
146 target[k++] = losDistance.doubleValue();
147
148
149 final Double bodyDistance = reference.getBodyDistance(i);
150 weight[k] = bodyConstraintWeight;
151 target[k++] = bodyDistance.doubleValue();
152 }
153 }
154
155 this.targetAndWeight = new HashMap<String, double[]>();
156 this.targetAndWeight.put(TARGET, target);
157 this.targetAndWeight.put(WEIGHT, weight);
158 }
159
160
161 @Override
162 protected MultivariateJacobianFunction createFunction() {
163
164
165 final MultivariateJacobianFunction model = point -> {
166
167
168 int i = 0;
169 for (final ParameterDriver driver : this.getDrivers()) {
170 driver.setNormalizedValue(point.getEntry(i++));
171 }
172
173 final double[] target = this.targetAndWeight.get(TARGET);
174
175
176 final RealVector value = new ArrayRealVector(target.length);
177 final RealMatrix jacobian = new Array2DRowRealMatrix(target.length, this.getNbParams());
178
179 int l = 0;
180 for (final SensorToSensorMapping reference : this.sensorToSensorMappings) {
181
182 final String ruggedNameA = reference.getRuggedNameA();
183 final String ruggedNameB = reference.getRuggedNameB();
184 final Rugged ruggedA = this.ruggedMap.get(ruggedNameA);
185 if (ruggedA == null) {
186 throw new RuggedException(RuggedMessages.INVALID_RUGGED_NAME);
187 }
188
189 final Rugged ruggedB = this.ruggedMap.get(ruggedNameB);
190 if (ruggedB == null) {
191 throw new RuggedException(RuggedMessages.INVALID_RUGGED_NAME);
192 }
193
194 for (final Map.Entry<SensorPixel, SensorPixel> mapping : reference.getMapping()) {
195
196 final SensorPixel spA = mapping.getKey();
197 final SensorPixel spB = mapping.getValue();
198
199 final LineSensor lineSensorB = ruggedB.getLineSensor(reference.getSensorNameB());
200 final LineSensor lineSensorA = ruggedA.getLineSensor(reference.getSensorNameA());
201
202 final AbsoluteDate dateA = lineSensorA.getDate(spA.getLineNumber());
203 final AbsoluteDate dateB = lineSensorB.getDate(spB.getLineNumber());
204
205 final double pixelA = spA.getPixelNumber();
206 final double pixelB = spB.getPixelNumber();
207
208 final SpacecraftToObservedBody scToBodyA = ruggedA.getScToBody();
209
210 final DerivativeStructure[] ilResult =
211 ruggedB.distanceBetweenLOSderivatives(lineSensorA, dateA, pixelA, scToBodyA,
212 lineSensorB, dateB, pixelB, this.getGenerator());
213
214
215 value.setEntry(l, ilResult[0].getValue());
216 value.setEntry(l + 1, ilResult[1].getValue());
217
218
219 final int[] orders = new int[this.getNbParams()];
220 int m = 0;
221
222 for (final ParameterDriver driver : this.getDrivers()) {
223 final double scale = driver.getScale();
224 orders[m] = 1;
225 jacobian.setEntry(l, m, ilResult[0].getPartialDerivative(orders) * scale);
226 jacobian.setEntry(l + 1, m, ilResult[1].getPartialDerivative(orders) * scale);
227 orders[m] = 0;
228 m++;
229 }
230
231 l += 2;
232 }
233 }
234
235
236 return new Pair<RealVector, RealMatrix>(value, jacobian);
237 };
238
239 return model;
240 }
241
242
243
244
245
246
247
248 @Override
249 public final LeastSquaresProblem build(final int maxEvaluations, final double convergenceThreshold) {
250
251 this.createTargetAndWeight();
252 final double[] target = this.targetAndWeight.get(TARGET);
253 final double[] start = this.createStartTab();
254 final ParameterValidator validator = this.createParameterValidator();
255 final ConvergenceChecker<LeastSquaresProblem.Evaluation> checker = this.createChecker(convergenceThreshold);
256 final MultivariateJacobianFunction model = this.createFunction();
257 return new LeastSquaresBuilder()
258 .lazyEvaluation(false).maxIterations(maxEvaluations)
259 .maxEvaluations(maxEvaluations).weight(null).start(start)
260 .target(target).parameterValidator(validator).checker(checker)
261 .model(model).build();
262 }
263 }