1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements.gnss;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.stream.Collectors;
23
24 import org.hipparchus.linear.MatrixUtils;
25 import org.hipparchus.linear.QRDecomposer;
26 import org.hipparchus.linear.RealMatrix;
27 import org.hipparchus.linear.RealVector;
28 import org.hipparchus.util.FastMath;
29 import org.orekit.errors.OrekitIllegalArgumentException;
30 import org.orekit.errors.OrekitMessages;
31 import org.orekit.utils.drivers.ParameterDriver;
32
33
34
35
36
37
38 public class AmbiguitySolver {
39
40
41 private final List<ParameterDriver> ambiguityDrivers;
42
43
44 private final IntegerLeastSquareSolver solver;
45
46
47 private final AmbiguityAcceptance acceptance;
48
49
50
51
52
53
54
55 public AmbiguitySolver(final List<ParameterDriver> ambiguityDrivers,
56 final IntegerLeastSquareSolver solver,
57 final AmbiguityAcceptance acceptance) {
58 this.ambiguityDrivers = ambiguityDrivers;
59 this.solver = solver;
60 this.acceptance = acceptance;
61 }
62
63
64
65
66 public List<ParameterDriver> getAllAmbiguityDrivers() {
67 return Collections.unmodifiableList(ambiguityDrivers);
68 }
69
70
71
72
73 protected List<ParameterDriver> getFreeAmbiguityDrivers() {
74 return ambiguityDrivers.
75 stream().
76 filter(d -> {
77 if (d.isSelected()) {
78
79
80
81 final double near = FastMath.rint(d.getValue());
82 final double gapMin = near - d.getMinValue();
83 final double gapMax = d.getMaxValue() - near;
84 return FastMath.max(FastMath.abs(gapMin), FastMath.abs(gapMax)) > 1.0e-15;
85 } else {
86 return false;
87 }
88 }).
89 collect(Collectors.toList());
90 }
91
92
93
94
95
96
97 protected int[] getFreeAmbiguityIndirection(final int startIndex,
98 final List<ParameterDriver> measurementsParametersDrivers) {
99
100
101 final List<ParameterDriver> freeDrivers = getFreeAmbiguityDrivers();
102 final List<String> measurementsPDriversNames = new ArrayList<>();
103 final int totalValuesToEstimate = freeDrivers.size();
104 for (ParameterDriver measDriver : measurementsParametersDrivers) {
105 measurementsPDriversNames.add(measDriver.getName());
106 }
107
108 final int[] indirection = new int[totalValuesToEstimate];
109 int nb = 0;
110 for (ParameterDriver freeDriver : freeDrivers) {
111
112 indirection[nb] = -1;
113
114 for (int k = 0; k < measurementsPDriversNames.size(); ++k) {
115 if (freeDriver.getName().equals(measurementsPDriversNames.get(k))) {
116 indirection[nb] = startIndex + k;
117 break;
118 }
119 }
120
121 if (indirection[nb] < 0) {
122
123 final StringBuilder builder = new StringBuilder();
124 for (final String driverName : measurementsPDriversNames) {
125 if (!builder.isEmpty()) {
126 builder.append(", ");
127 }
128 builder.append(driverName);
129 }
130 throw new OrekitIllegalArgumentException(OrekitMessages.UNSUPPORTED_PARAMETER_NAME,
131 freeDriver.getName(), builder.toString());
132 }
133 nb++;
134 }
135
136 return indirection;
137
138 }
139
140
141
142
143 public void unFixAmbiguity(final ParameterDriver ambiguityDriver) {
144 ambiguityDriver.setMinValue(Double.NEGATIVE_INFINITY);
145 ambiguityDriver.setMaxValue(Double.POSITIVE_INFINITY);
146 }
147
148
149
150
151
152
153
154 public List<ParameterDriver> fixIntegerAmbiguities(final int startIndex,
155 final List<ParameterDriver> measurementsParametersDrivers,
156 final RealMatrix covariance) {
157
158
159 final List<ParameterDriver> ambiguities = getAllAmbiguityDrivers();
160
161
162 final double[] floatAmbiguities = new double[ambiguities.size()];
163 int floatAmbRank = 0;
164 for (ParameterDriver pDriver : ambiguities) {
165 floatAmbiguities[floatAmbRank++] = pDriver.getValue();
166 }
167
168 final int[] indirection = getFreeAmbiguityIndirection(startIndex, measurementsParametersDrivers);
169
170 final IntegerLeastSquareSolution[] candidates =
171 solver.solveILS(acceptance.numberOfCandidates(), floatAmbiguities, indirection, covariance);
172
173
174
175
176 if (solver instanceof IntegerBootstrapping && candidates.length == 0) {
177 return Collections.emptyList();
178 }
179
180
181 if (candidates.length < acceptance.numberOfCandidates()) {
182 return Collections.emptyList();
183 }
184
185
186 final IntegerLeastSquareSolution bestCandidate = acceptance.accept(candidates);
187 if (bestCandidate == null) {
188 return Collections.emptyList();
189 }
190
191
192 final long[] fixedAmbiguities = bestCandidate.getSolution();
193 final List<ParameterDriver> fixedDrivers = new ArrayList<>(indirection.length);
194 final int nb = measurementsParametersDrivers.size();
195 for (int i = 0; i < nb; ++i) {
196 final ParameterDriver driver = measurementsParametersDrivers.get(indirection[i] - startIndex);
197 driver.setMinValue(fixedAmbiguities[i]);
198 driver.setMaxValue(fixedAmbiguities[i]);
199 fixedDrivers.add(driver);
200 }
201
202
203
204 final RealMatrix Qab = getCovMatrix(covariance, indirection);
205
206 final RealVector X = new QRDecomposer(1.0e-10).decompose(getAmbiguityMatrix(covariance, indirection)).solve(MatrixUtils.createRealVector(floatAmbiguities).
207 subtract(MatrixUtils.createRealVector(toDoubleArray(fixedAmbiguities.length, fixedAmbiguities))));
208 final RealVector Y = Qab.preMultiply(X);
209
210 int entry = 0;
211 for (int i = startIndex + 1; i < covariance.getColumnDimension(); i++) {
212 if (!belongTo(indirection, i)) {
213 final ParameterDriver driver = measurementsParametersDrivers.get(i - startIndex);
214 driver.setValue(driver.getValue() - Y.getEntry(entry++ - startIndex));
215 }
216 }
217
218 return fixedDrivers;
219
220 }
221
222
223
224
225
226
227 private RealMatrix getCovMatrix(final RealMatrix cov, final int[] indirection) {
228 final RealMatrix Qab = MatrixUtils.createRealMatrix(indirection.length, cov.getColumnDimension());
229 int index = 0;
230 int iter = 0;
231 while (iter < indirection.length) {
232
233 for (int j = 0; j < cov.getColumnDimension(); j++) {
234 if (!belongTo(indirection, j)) {
235 Qab.setEntry(index, 0, cov.getEntry(index, 0));
236 }
237 }
238 index++;
239 iter++;
240 }
241 return Qab;
242 }
243
244
245
246
247
248
249 private RealMatrix getAmbiguityMatrix(final RealMatrix cov, final int[] indirection) {
250 final RealMatrix Qa = MatrixUtils.createRealMatrix(indirection.length, indirection.length);
251 for (int i = 0; i < indirection.length; i++) {
252 Qa.setEntry(i, i, cov.getEntry(indirection[i], indirection[i]));
253 for (int j = 0; j < i; j++) {
254 Qa.setEntry(i, j, cov.getEntry(indirection[i], indirection[j]));
255 Qa.setEntry(j, i, cov.getEntry(indirection[i], indirection[j]));
256 }
257 }
258 return Qa;
259 }
260
261
262
263
264
265
266 private boolean belongTo(final int[] indirection, final int pos) {
267 for (int j : indirection) {
268 if (pos == j) {
269 return true;
270 }
271 }
272 return false;
273 }
274
275
276
277
278
279
280 private double[] toDoubleArray(final int size, final long[] longArray) {
281
282 final double[] doubleArray = new double[size];
283
284 for (int index = 0; index < size; index++) {
285 doubleArray[index] = longArray[index];
286 }
287 return doubleArray;
288 }
289
290 }