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