1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.navigation.indoor.radiosource;
17
18 import com.irurueta.geometry.Point2D;
19 import com.irurueta.navigation.LockedException;
20 import com.irurueta.navigation.NavigationException;
21 import com.irurueta.navigation.indoor.Beacon;
22 import com.irurueta.navigation.indoor.BeaconLocated2D;
23 import com.irurueta.navigation.indoor.RadioSource;
24 import com.irurueta.navigation.indoor.RadioSourceLocated;
25 import com.irurueta.navigation.indoor.RangingReadingLocated;
26 import com.irurueta.navigation.indoor.WifiAccessPoint;
27 import com.irurueta.navigation.indoor.WifiAccessPointLocated2D;
28 import com.irurueta.numerical.robust.RobustEstimatorMethod;
29
30 import java.util.ArrayList;
31 import java.util.List;
32
33
34
35
36
37
38
39 @SuppressWarnings("DuplicatedCode")
40 public abstract class RobustRangingRadioSourceEstimator2D<S extends RadioSource> extends
41 RobustRangingRadioSourceEstimator<S, Point2D> {
42
43
44
45
46 protected final RangingRadioSourceEstimator2D<S> innerEstimator = new RangingRadioSourceEstimator2D<>();
47
48
49
50
51 private final List<RangingReadingLocated<S, Point2D>> innerReadings = new ArrayList<>();
52
53
54
55
56 protected RobustRangingRadioSourceEstimator2D() {
57 super();
58 preliminarySubsetSize = getMinReadings();
59 }
60
61
62
63
64
65
66
67
68
69 protected RobustRangingRadioSourceEstimator2D(final List<? extends RangingReadingLocated<S, Point2D>> readings) {
70 super(readings);
71 preliminarySubsetSize = getMinReadings();
72 }
73
74
75
76
77
78
79 protected RobustRangingRadioSourceEstimator2D(
80 final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener) {
81 super(listener);
82 preliminarySubsetSize = getMinReadings();
83 }
84
85
86
87
88
89
90
91
92
93 protected RobustRangingRadioSourceEstimator2D(
94 final List<? extends RangingReadingLocated<S, Point2D>> readings,
95 final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener) {
96 super(readings, listener);
97 preliminarySubsetSize = getMinReadings();
98 }
99
100
101
102
103
104
105
106 protected RobustRangingRadioSourceEstimator2D(final Point2D initialPosition) {
107 super(initialPosition);
108 preliminarySubsetSize = getMinReadings();
109 }
110
111
112
113
114
115
116
117
118
119
120 protected RobustRangingRadioSourceEstimator2D(
121 final List<? extends RangingReadingLocated<S, Point2D>> readings, final Point2D initialPosition) {
122 super(readings, initialPosition);
123 preliminarySubsetSize = getMinReadings();
124 }
125
126
127
128
129
130
131
132
133 protected RobustRangingRadioSourceEstimator2D(
134 final Point2D initialPosition, final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener) {
135 super(initialPosition, listener);
136 preliminarySubsetSize = getMinReadings();
137 }
138
139
140
141
142
143
144
145
146
147
148
149 protected RobustRangingRadioSourceEstimator2D(
150 final List<? extends RangingReadingLocated<S, Point2D>> readings, final Point2D initialPosition,
151 final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener) {
152 super(readings, initialPosition, listener);
153 preliminarySubsetSize = getMinReadings();
154 }
155
156
157
158
159
160
161
162
163 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
164 final RobustEstimatorMethod method) {
165 return switch (method) {
166 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>();
167 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>();
168 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>();
169 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>();
170 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>();
171 };
172 }
173
174
175
176
177
178
179
180
181
182 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
183 final List<? extends RangingReadingLocated<S, Point2D>> readings, final RobustEstimatorMethod method) {
184 return switch (method) {
185 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(readings);
186 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(readings);
187 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(readings);
188 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(readings);
189 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(readings);
190 };
191 }
192
193
194
195
196
197
198
199
200
201 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
202 final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener, final RobustEstimatorMethod method) {
203 return switch (method) {
204 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(listener);
205 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(listener);
206 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(listener);
207 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(listener);
208 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(listener);
209 };
210 }
211
212
213
214
215
216
217
218
219
220
221 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
222 final List<? extends RangingReadingLocated<S, Point2D>> readings,
223 final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener, final RobustEstimatorMethod method) {
224 return switch (method) {
225 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(readings, listener);
226 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(readings, listener);
227 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(readings, listener);
228 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(readings, listener);
229 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(readings, listener);
230 };
231 }
232
233
234
235
236
237
238
239
240
241
242 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
243 final Point2D initialPosition, final RobustEstimatorMethod method) {
244 return switch (method) {
245 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(initialPosition);
246 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(initialPosition);
247 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(initialPosition);
248 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(initialPosition);
249 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(initialPosition);
250 };
251 }
252
253
254
255
256
257
258
259
260
261
262
263 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
264 final List<? extends RangingReadingLocated<S, Point2D>> readings, final Point2D initialPosition,
265 final RobustEstimatorMethod method) {
266 return switch (method) {
267 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition);
268 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(readings, initialPosition);
269 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition);
270 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition);
271 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(readings, initialPosition);
272 };
273 }
274
275
276
277
278
279
280
281
282
283
284
285 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
286 final Point2D initialPosition, final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener,
287 final RobustEstimatorMethod method) {
288 return switch (method) {
289 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(initialPosition, listener);
290 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(initialPosition, listener);
291 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(initialPosition, listener);
292 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(initialPosition, listener);
293 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(initialPosition, listener);
294 };
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
309 final List<? extends RangingReadingLocated<S, Point2D>> readings, final Point2D initialPosition,
310 final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener, final RobustEstimatorMethod method) {
311 return switch (method) {
312 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition, listener);
313 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(readings, initialPosition, listener);
314 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition, listener);
315 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition, listener);
316 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(readings, initialPosition, listener);
317 };
318 }
319
320
321
322
323
324
325
326
327
328
329
330 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
331 final double[] qualityScores, final RobustEstimatorMethod method) {
332 return switch (method) {
333 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>();
334 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>();
335 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>();
336 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(qualityScores);
337 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(qualityScores);
338 };
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
353 final double[] qualityScores, final List<? extends RangingReadingLocated<S, Point2D>> readings,
354 final RobustEstimatorMethod method) {
355 return switch (method) {
356 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(readings);
357 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(readings);
358 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(readings);
359 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(qualityScores, readings);
360 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(qualityScores, readings);
361 };
362 }
363
364
365
366
367
368
369
370
371
372
373
374
375 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
376 final double[] qualityScores, final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener,
377 final RobustEstimatorMethod method) {
378 return switch (method) {
379 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(listener);
380 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(listener);
381 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(listener);
382 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(qualityScores, listener);
383 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(qualityScores, listener);
384 };
385 }
386
387
388
389
390
391
392
393
394
395
396
397
398
399 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
400 final double[] qualityScores, final List<? extends RangingReadingLocated<S, Point2D>> readings,
401 final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener, final RobustEstimatorMethod method) {
402 return switch (method) {
403 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(readings, listener);
404 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(readings, listener);
405 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(readings, listener);
406 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(qualityScores, readings, listener);
407 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(qualityScores, readings, listener);
408 };
409 }
410
411
412
413
414
415
416
417
418
419
420
421
422
423 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
424 final double[] qualityScores, final Point2D initialPosition, final RobustEstimatorMethod method) {
425 return switch (method) {
426 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(initialPosition);
427 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(initialPosition);
428 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(initialPosition);
429 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(qualityScores, initialPosition);
430 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(qualityScores, initialPosition);
431 };
432 }
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
448 final double[] qualityScores, final List<? extends RangingReadingLocated<S, Point2D>> readings,
449 final Point2D initialPosition, final RobustEstimatorMethod method) {
450 return switch (method) {
451 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition);
452 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(readings, initialPosition);
453 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition);
454 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(qualityScores, readings, initialPosition);
455 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(qualityScores, readings, initialPosition);
456 };
457 }
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
473 final double[] qualityScores, final Point2D initialPosition,
474 final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener, final RobustEstimatorMethod method) {
475 return switch (method) {
476 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(initialPosition, listener);
477 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(initialPosition, listener);
478 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(initialPosition, listener);
479 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(qualityScores, initialPosition, listener);
480 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(qualityScores, initialPosition, listener);
481 };
482 }
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498 public static <S extends RadioSource> RobustRangingRadioSourceEstimator2D<S> create(
499 final double[] qualityScores, final List<? extends RangingReadingLocated<S, Point2D>> readings,
500 final Point2D initialPosition, final RobustRangingRadioSourceEstimatorListener<S, Point2D> listener,
501 final RobustEstimatorMethod method) {
502 return switch (method) {
503 case RANSAC -> new RANSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition, listener);
504 case LMEDS -> new LMedSRobustRangingRadioSourceEstimator2D<>(readings, initialPosition, listener);
505 case MSAC -> new MSACRobustRangingRadioSourceEstimator2D<>(readings, initialPosition, listener);
506 case PROSAC -> new PROSACRobustRangingRadioSourceEstimator2D<>(qualityScores, readings, initialPosition,
507 listener);
508 default -> new PROMedSRobustRangingRadioSourceEstimator2D<>(qualityScores, readings, initialPosition,
509 listener);
510 };
511 }
512
513
514
515
516
517
518
519 @Override
520 public int getMinReadings() {
521 return Point2D.POINT2D_INHOMOGENEOUS_COORDINATES_LENGTH + 1;
522 }
523
524
525
526
527
528
529
530 @Override
531 public int getNumberOfDimensions() {
532 return Point2D.POINT2D_INHOMOGENEOUS_COORDINATES_LENGTH;
533 }
534
535
536
537
538
539
540 @SuppressWarnings("unchecked")
541 @Override
542 public RadioSourceLocated<Point2D> getEstimatedRadioSource() {
543 final var readings = getReadings();
544 if (readings == null || readings.isEmpty()) {
545 return null;
546 }
547 final var source = readings.get(0).getSource();
548
549 final var estimatedPosition = getEstimatedPosition();
550 if (estimatedPosition == null) {
551 return null;
552 }
553
554 final var estimatedPositionCovariance = getEstimatedPositionCovariance();
555
556 if (source instanceof WifiAccessPoint accessPoint) {
557 return new WifiAccessPointLocated2D(accessPoint.getBssid(), accessPoint.getFrequency(),
558 accessPoint.getSsid(), estimatedPosition, estimatedPositionCovariance);
559 } else if (source instanceof Beacon beacon) {
560 return new BeaconLocated2D(beacon.getIdentifiers(), beacon.getTransmittedPower(), beacon.getFrequency(),
561 beacon.getBluetoothAddress(), beacon.getBeaconTypeCode(), beacon.getManufacturer(),
562 beacon.getServiceUuid(), beacon.getBluetoothName(), estimatedPosition, estimatedPositionCovariance);
563 } else {
564 return null;
565 }
566 }
567
568
569
570
571
572
573
574
575 @Override
576 public boolean isHomogeneousLinearSolverUsed() {
577 return innerEstimator.isHomogeneousLinearSolverUsed();
578 }
579
580
581
582
583
584
585
586
587
588 @Override
589 public void setHomogeneousLinearSolverUsed(final boolean useHomogeneousLinearSolver) throws LockedException {
590 if (isLocked()) {
591 throw new LockedException();
592 }
593 innerEstimator.setHomogeneousLinearSolverUsed(useHomogeneousLinearSolver);
594 }
595
596
597
598
599
600
601
602 @Override
603 protected void solvePreliminarySolutions(final int[] samplesIndices, final List<Solution<Point2D>> solutions) {
604 try {
605 innerReadings.clear();
606 for (final var samplesIndex : samplesIndices) {
607 innerReadings.add(readings.get(samplesIndex));
608 }
609
610
611 innerEstimator.setInitialPosition(initialPosition);
612
613 innerEstimator.setReadings(innerReadings);
614
615
616
617
618
619 innerEstimator.setNonLinearSolverEnabled(initialPosition != null);
620
621
622 innerEstimator.setUseReadingPositionCovariances(useReadingPositionCovariances);
623
624 innerEstimator.estimate();
625
626 final var estimatedPosition = innerEstimator.getEstimatedPosition();
627 solutions.add(new Solution<>(estimatedPosition));
628 } catch (final NavigationException ignore) {
629
630 }
631 }
632
633
634
635
636
637
638
639
640
641
642
643
644 protected void attemptRefine(final Solution<Point2D> result) {
645 final var initialPosition = result.getEstimatedPosition();
646
647 if (refineResult && inliersData != null) {
648 final var inliers = inliersData.getInliers();
649 final var nSamples = readings.size();
650
651 innerReadings.clear();
652
653 for (var i = 0; i < nSamples; i++) {
654 if (inliers.get(i)) {
655
656 innerReadings.add(readings.get(i));
657 }
658 }
659
660 try {
661 innerEstimator.setInitialPosition(initialPosition);
662 innerEstimator.setReadings(innerReadings);
663
664 innerEstimator.setNonLinearSolverEnabled(true);
665 innerEstimator.setUseReadingPositionCovariances(useReadingPositionCovariances);
666 innerEstimator.estimate();
667
668 final var cov = innerEstimator.getEstimatedCovariance();
669 if (keepCovariance && cov != null) {
670
671 estimatedPositionCovariance = covariance = cov;
672
673 } else {
674 covariance = null;
675 estimatedPositionCovariance = null;
676 }
677
678 estimatedPosition = innerEstimator.getEstimatedPosition();
679 } catch (final Exception e) {
680
681
682 covariance = null;
683 estimatedPositionCovariance = null;
684
685 estimatedPosition = initialPosition;
686 }
687 } else {
688 covariance = null;
689 estimatedPositionCovariance = null;
690
691 estimatedPosition = initialPosition;
692 }
693 }
694 }