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.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.hipparchus.analysis.differentiation.DerivativeStructure;
25 import org.hipparchus.linear.Array2DRowRealMatrix;
26 import org.hipparchus.linear.ArrayRealVector;
27 import org.hipparchus.linear.RealMatrix;
28 import org.hipparchus.linear.RealVector;
29 import org.hipparchus.optim.ConvergenceChecker;
30 import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresBuilder;
31 import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem;
32 import org.hipparchus.optim.nonlinear.vector.leastsquares.MultivariateJacobianFunction;
33 import org.hipparchus.optim.nonlinear.vector.leastsquares.ParameterValidator;
34 import org.hipparchus.util.FastMath;
35 import org.hipparchus.util.Pair;
36 import org.orekit.bodies.GeodeticPoint;
37 import org.orekit.rugged.adjustment.measurements.Observables;
38 import org.orekit.rugged.adjustment.measurements.SensorToGroundMapping;
39 import org.orekit.rugged.api.Rugged;
40 import org.orekit.rugged.errors.RuggedException;
41 import org.orekit.rugged.errors.RuggedMessages;
42 import org.orekit.rugged.linesensor.LineSensor;
43 import org.orekit.rugged.linesensor.SensorPixel;
44 import org.orekit.utils.ParameterDriver;
45
46
47
48
49
50
51
52
53
54 public class GroundOptimizationProblemBuilder extends OptimizationProblemBuilder {
55
56
57 private static final String TARGET = "Target";
58
59
60 private static final String WEIGHT = "Weight";
61
62
63 private final Rugged rugged;
64
65
66 private List<SensorToGroundMapping> sensorToGroundMappings;
67
68
69 private int minLine;
70
71
72 private int maxLine;
73
74
75 private HashMap<String, double[] > targetAndWeight;
76
77
78
79
80
81
82
83 public GroundOptimizationProblemBuilder(final List<LineSensor> sensors,
84 final Observables measurements, final Rugged rugged) {
85
86 super(sensors, measurements);
87 this.rugged = rugged;
88 this.initMapping();
89 }
90
91
92 @Override
93 protected void initMapping() {
94
95 final String ruggedName = rugged.getName();
96 this.sensorToGroundMappings = new ArrayList<SensorToGroundMapping>();
97 for (final LineSensor lineSensor : this.getSensors()) {
98 final SensorToGroundMapping mapping = this.getMeasurements().getGroundMapping(ruggedName, lineSensor.getName());
99 if (mapping != null) {
100 this.sensorToGroundMappings.add(mapping);
101 }
102 }
103 }
104
105
106 @Override
107 protected void createTargetAndWeight() {
108
109 int n = 0;
110 for (final SensorToGroundMapping reference : this.sensorToGroundMappings) {
111 n += reference.getMapping().size();
112 }
113
114 if (n == 0) {
115 throw new RuggedException(RuggedMessages.NO_REFERENCE_MAPPINGS);
116 }
117 final double[] target = new double[2 * n];
118 final double[] weight = new double[2 * n];
119
120 double min = Double.POSITIVE_INFINITY;
121 double max = Double.NEGATIVE_INFINITY;
122 int k = 0;
123
124 for (final SensorToGroundMapping reference : this.sensorToGroundMappings) {
125 for (final Map.Entry<SensorPixel, GeodeticPoint> mapping : reference.getMapping()) {
126 final SensorPixel sp = mapping.getKey();
127 weight[k] = 1.0;
128 target[k++] = sp.getLineNumber();
129 weight[k] = 1.0;
130 target[k++] = sp.getPixelNumber();
131 min = FastMath.min(min, sp.getLineNumber());
132 max = FastMath.max(max, sp.getLineNumber());
133 }
134 }
135
136 this.minLine = (int) FastMath.floor(min - ESTIMATION_LINE_RANGE_MARGIN);
137 this.maxLine = (int) FastMath.ceil(max - ESTIMATION_LINE_RANGE_MARGIN);
138 this.targetAndWeight = new HashMap<String, double[]>();
139 this.targetAndWeight.put(TARGET, target);
140 this.targetAndWeight.put(WEIGHT, weight);
141 }
142
143
144 @Override
145 protected MultivariateJacobianFunction createFunction() {
146
147
148 final MultivariateJacobianFunction model = point -> {
149
150
151 int i = 0;
152 for (final ParameterDriver driver : this.getDrivers()) {
153 driver.setNormalizedValue(point.getEntry(i++));
154 }
155
156 final double[] target = this.targetAndWeight.get(TARGET);
157
158
159 final RealVector value = new ArrayRealVector(target.length);
160 final RealMatrix jacobian = new Array2DRowRealMatrix(target.length, this.getNbParams());
161 int l = 0;
162 for (final SensorToGroundMapping reference : this.sensorToGroundMappings) {
163 for (final Map.Entry<SensorPixel, GeodeticPoint> mapping : reference.getMapping()) {
164 final GeodeticPoint gp = mapping.getValue();
165 final DerivativeStructure[] ilResult = this.rugged.inverseLocationDerivatives(reference.getSensorName(), gp, minLine, maxLine, this.getGenerator());
166
167 if (ilResult == null) {
168 value.setEntry(l, minLine - 100.0);
169
170
171 value.setEntry(l + 1, -100.0);
172
173 } else {
174
175 value.setEntry(l, ilResult[0].getValue());
176 value.setEntry(l + 1, ilResult[1].getValue());
177
178
179 final int[] orders = new int[this.getNbParams()];
180 int m = 0;
181 for (final ParameterDriver driver : this.getDrivers()) {
182 final double scale = driver.getScale();
183 orders[m] = 1;
184 jacobian.setEntry(l, m,
185 ilResult[0]
186 .getPartialDerivative(orders) *
187 scale);
188 jacobian.setEntry(l + 1, m,
189 ilResult[1]
190 .getPartialDerivative(orders) *
191 scale);
192 orders[m] = 0;
193 m++;
194 }
195 }
196
197 l += 2;
198 }
199 }
200
201
202 return new Pair<RealVector, RealMatrix>(value, jacobian);
203 };
204
205 return model;
206 }
207
208
209
210
211
212
213
214 @Override
215 public final LeastSquaresProblem build(final int maxEvaluations, final double convergenceThreshold) {
216
217 this.createTargetAndWeight();
218 final double[] target = this.targetAndWeight.get(TARGET);
219 final double[] start = this.createStartTab();
220 final ParameterValidator validator = this.createParameterValidator();
221 final ConvergenceChecker<LeastSquaresProblem.Evaluation> checker = this.createChecker(convergenceThreshold);
222 final MultivariateJacobianFunction model = this.createFunction();
223 return new LeastSquaresBuilder()
224 .lazyEvaluation(false).maxIterations(maxEvaluations)
225 .maxEvaluations(maxEvaluations).weight(null).start(start)
226 .target(target).parameterValidator(validator).checker(checker)
227 .model(model).build();
228 }
229 }