View Javadoc
1   /*
2    * Copyright (C) 2019 Alberto Irurueta Carro (alberto@irurueta.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.irurueta.navigation.indoor.position;
17  
18  import com.irurueta.geometry.InhomogeneousPoint2D;
19  import com.irurueta.geometry.Point2D;
20  import com.irurueta.navigation.LockedException;
21  import com.irurueta.navigation.indoor.RadioSource;
22  import com.irurueta.navigation.indoor.RadioSourceLocated;
23  import com.irurueta.navigation.indoor.RangingAndRssiFingerprint;
24  import com.irurueta.navigation.indoor.RangingAndRssiReading;
25  import com.irurueta.numerical.robust.RobustEstimatorMethod;
26  
27  import java.util.List;
28  
29  /**
30   * Base class for robust ranging+RSSI 2D position estimators using located radio sources
31   * and their ranging+RSSI readings at unknown locations.
32   * These kind of estimators can be used to robustly determine the 2D position of a given
33   * device by getting ranging+RSSI readings at an unknown location of different radio
34   * sources whose locations are known.
35   * Implementations of this class should be able to detect and discard outliers in order
36   * to find the best solution.
37   */
38  @SuppressWarnings("DuplicatedCode")
39  public abstract class RobustRangingAndRssiPositionEstimator2D extends RobustRangingAndRssiPositionEstimator<Point2D> {
40  
41      /**
42       * Constructor.
43       */
44      protected RobustRangingAndRssiPositionEstimator2D() {
45          super();
46          preliminarySubsetSize = getMinRequiredSources();
47      }
48  
49      /**
50       * Constructor.
51       *
52       * @param listener listener in charge of handling events.
53       */
54      protected RobustRangingAndRssiPositionEstimator2D(
55              final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener) {
56          super(listener);
57          preliminarySubsetSize = getMinRequiredSources();
58      }
59  
60      /**
61       * Gets minimum required number of located radio sources to perform lateration.
62       *
63       * @return minimum required number of located radio sources to perform lateration.
64       */
65      @Override
66      public int getMinRequiredSources() {
67          return Point2D.POINT2D_HOMOGENEOUS_COORDINATES_LENGTH;
68      }
69  
70  
71      /**
72       * Creates a robust 2D position estimator.
73       *
74       * @param method robust estimator method.
75       * @return a robust 2D position estimator.
76       */
77      public static RobustRangingAndRssiPositionEstimator2D create(final RobustEstimatorMethod method) {
78          return switch (method) {
79              case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D();
80              case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D();
81              case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D();
82              case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D();
83              default -> new PROMedSRobustRangingAndRssiPositionEstimator2D();
84          };
85      }
86  
87      /**
88       * Creates a robust 2D position estimator.
89       *
90       * @param sources located radio sources used for lateration.
91       * @param method  robust estimator method.
92       * @return a robust 2D position estimator.
93       * @throws IllegalArgumentException if provided sources is null or the number of
94       *                                  provided sources is less than the required minimum.
95       */
96      public static RobustRangingAndRssiPositionEstimator2D create(
97              final List<? extends RadioSourceLocated<Point2D>> sources, final RobustEstimatorMethod method) {
98          return switch (method) {
99              case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(sources);
100             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(sources);
101             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(sources);
102             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sources);
103             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sources);
104         };
105     }
106 
107     /**
108      * Creates a robust 2D position estimator.
109      *
110      * @param fingerprint fingerprint containing ranging+RSSI readings at an unknown
111      *                    location for provided located radio sources.
112      * @param method      robust estimator method.
113      * @return a robust 2D position estimator.
114      * @throws IllegalArgumentException if provided fingerprint is null.
115      */
116     public static RobustRangingAndRssiPositionEstimator2D create(
117             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
118                     extends RadioSource>> fingerprint,
119             final RobustEstimatorMethod method) {
120         return switch (method) {
121             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(fingerprint);
122             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(fingerprint);
123             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(fingerprint);
124             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(fingerprint);
125             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(fingerprint);
126         };
127     }
128 
129     /**
130      * Creates a robust 2D position estimator.
131      *
132      * @param sources     located radio sources used for lateration.
133      * @param fingerprint fingerprint containing ranging+RSSI readings at an unknown
134      *                    location for provided located radio sources.
135      * @param method      robust estimator method.
136      * @return a robust 2D position estimator.
137      * @throws IllegalArgumentException if either provided sources or fingerprint is null
138      *                                  or the number of provided sources is less than the required minimum.
139      */
140     public static RobustRangingAndRssiPositionEstimator2D create(
141             final List<? extends RadioSourceLocated<Point2D>> sources,
142             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
143                     extends RadioSource>> fingerprint,
144             final RobustEstimatorMethod method) {
145         return switch (method) {
146             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint);
147             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(sources, fingerprint);
148             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint);
149             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint);
150             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sources, fingerprint);
151         };
152     }
153 
154     /**
155      * Creates a robust 2D position estimator.
156      *
157      * @param listener listener in charge of handling events.
158      * @param method   robust estimator method.
159      * @return a robust 2D position estimator.
160      */
161     public static RobustRangingAndRssiPositionEstimator2D create(
162             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener, final RobustEstimatorMethod method) {
163         return switch (method) {
164             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(listener);
165             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(listener);
166             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(listener);
167             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(listener);
168             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(listener);
169         };
170     }
171 
172     /**
173      * Creates a robust 2D position estimator.
174      *
175      * @param sources  located radio sources used for lateration.
176      * @param listener listener in charge of handling events.
177      * @param method   robust estimator method.
178      * @return a robust 2D position estimator.
179      * @throws IllegalArgumentException if provided sources is null or the number of
180      *                                  provided sources is less than the required minimum.
181      */
182     public static RobustRangingAndRssiPositionEstimator2D create(
183             final List<? extends RadioSourceLocated<Point2D>> sources,
184             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener, final RobustEstimatorMethod method) {
185         return switch (method) {
186             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(sources, listener);
187             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(sources, listener);
188             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(sources, listener);
189             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sources, listener);
190             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sources, listener);
191         };
192     }
193 
194     /**
195      * Creates a robust 2D position estimator.
196      *
197      * @param fingerprint fingerprint containing ranging+RSSI readings at an unknown
198      *                    location for provided located radio sources.
199      * @param listener    listener in charge of handling events.
200      * @param method      robust estimator method.
201      * @return a robust 2D position estimator.
202      * @throws IllegalArgumentException if provided fingerprint is null.
203      */
204     public static RobustRangingAndRssiPositionEstimator2D create(
205             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
206                     extends RadioSource>> fingerprint,
207             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener,
208             final RobustEstimatorMethod method) {
209         return switch (method) {
210             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(fingerprint, listener);
211             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(fingerprint, listener);
212             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(fingerprint, listener);
213             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(fingerprint, listener);
214             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(fingerprint, listener);
215         };
216     }
217 
218     /**
219      * Creates a robust 2D position estimator.
220      *
221      * @param sources     located radio sources used for lateration.
222      * @param fingerprint fingerprint containing ranging+RSSI readings at an unknown
223      *                    location for provided located radio sources.
224      * @param listener    listener in charge of handling events.
225      * @param method      robust estimator method.
226      * @return a robust 2D position estimator.
227      * @throws IllegalArgumentException if either provided sources or fingerprint is null
228      *                                  or the number of provided sources is less than the required minimum.
229      */
230     public static RobustRangingAndRssiPositionEstimator2D create(
231             final List<? extends RadioSourceLocated<Point2D>> sources,
232             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
233                     extends RadioSource>> fingerprint,
234             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener,
235             final RobustEstimatorMethod method) {
236         return switch (method) {
237             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint, listener);
238             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(sources, fingerprint, listener);
239             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint, listener);
240             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint, listener);
241             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sources, fingerprint, listener);
242         };
243     }
244 
245     /**
246      * Creates a robust 2D position estimator.
247      *
248      * @param sourceQualityScores             quality scores corresponding to
249      *                                        each provided located radio source.
250      *                                        The larger the score value the better
251      *                                        the quality of the radio source.
252      * @param fingerprintReadingQualityScores quality scores corresponding to readings
253      *                                        within provided fingerprint. The larger
254      *                                        the score the better the quality of the
255      *                                        reading.
256      * @param method                          robust estimator method.
257      * @return a robust 2D position estimator.
258      */
259     public static RobustRangingAndRssiPositionEstimator2D create(
260             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
261             final RobustEstimatorMethod method) {
262         return switch (method) {
263             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D();
264             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D();
265             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D();
266             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
267                     fingerprintReadingQualityScores);
268             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
269                     fingerprintReadingQualityScores);
270         };
271     }
272 
273     /**
274      * Creates a robust 2D position estimator.
275      *
276      * @param sourceQualityScores             quality scores corresponding to
277      *                                        each provided located radio source.
278      *                                        The larger the score value the better
279      *                                        the quality of the radio source.
280      * @param fingerprintReadingQualityScores quality scores corresponding to readings
281      *                                        within provided fingerprint. The larger
282      *                                        the score the better the quality of the
283      *                                        reading.
284      * @param sources                         located radio sources used for
285      *                                        lateration.
286      * @param method                          robust estimator method.
287      * @return a robust 2D position estimator.
288      * @throws IllegalArgumentException if provided sources is null or the number of
289      *                                  provided sources is less than the required minimum.
290      */
291     public static RobustRangingAndRssiPositionEstimator2D create(
292             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
293             final List<? extends RadioSourceLocated<Point2D>> sources,
294             final RobustEstimatorMethod method) {
295         return switch (method) {
296             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(sources);
297             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(sources);
298             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(sources);
299             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
300                     fingerprintReadingQualityScores, sources);
301             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
302                     fingerprintReadingQualityScores, sources);
303         };
304     }
305 
306     /**
307      * Creates a robust 2D position estimator.
308      *
309      * @param sourceQualityScores             quality scores corresponding to
310      *                                        each provided located radio source.
311      *                                        The larger the score value the better
312      *                                        the quality of the radio source.
313      * @param fingerprintReadingQualityScores quality scores corresponding to readings
314      *                                        within provided fingerprint. The larger
315      *                                        the score the better the quality of the
316      *                                        reading.
317      * @param fingerprint                     fingerprint containing ranging+RSSI
318      *                                        readings at an unknown location for
319      *                                        provided located radio sources.
320      * @param method                          robust estimator method.
321      * @return a robust 2D position estimator.
322      * @throws IllegalArgumentException if provided fingerprint is null.
323      */
324     public static RobustRangingAndRssiPositionEstimator2D create(
325             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
326             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
327                     extends RadioSource>> fingerprint,
328             final RobustEstimatorMethod method) {
329         return switch (method) {
330             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(fingerprint);
331             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(fingerprint);
332             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(fingerprint);
333             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
334                     fingerprintReadingQualityScores, fingerprint);
335             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
336                     fingerprintReadingQualityScores, fingerprint);
337         };
338     }
339 
340     /**
341      * Creates a robust 2D position estimator.
342      *
343      * @param sourceQualityScores             quality scores corresponding to
344      *                                        each provided located radio source.
345      *                                        The larger the score value the better
346      *                                        the quality of the radio source.
347      * @param fingerprintReadingQualityScores quality scores corresponding to readings
348      *                                        within provided fingerprint. The larger
349      *                                        the score the better the quality of the
350      *                                        reading.
351      * @param sources                         located radio sources used for
352      *                                        lateration.
353      * @param fingerprint                     fingerprint containing ranging+RSSI
354      *                                        readings at an unknown location for
355      *                                        provided located radio sources.
356      * @param method                          robust estimator method.
357      * @return a robust 2D position estimator.
358      * @throws IllegalArgumentException if either provided sources or fingerprint is null
359      *                                  or the number of provided sources is less than the required minimum.
360      */
361     public static RobustRangingAndRssiPositionEstimator2D create(
362             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
363             final List<? extends RadioSourceLocated<Point2D>> sources,
364             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
365                     extends RadioSource>> fingerprint,
366             final RobustEstimatorMethod method) {
367         return switch (method) {
368             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint);
369             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(sources, fingerprint);
370             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint);
371             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
372                     fingerprintReadingQualityScores, sources, fingerprint);
373             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
374                     fingerprintReadingQualityScores, sources, fingerprint);
375         };
376     }
377 
378     /**
379      * Creates a robust 2D position estimator.
380      *
381      * @param sourceQualityScores             quality scores corresponding to
382      *                                        each provided located radio source.
383      *                                        The larger the score value the better
384      *                                        the quality of the radio source.
385      * @param fingerprintReadingQualityScores quality scores corresponding to readings
386      *                                        within provided fingerprint. The larger
387      *                                        the score the better the quality of the
388      *                                        reading.
389      * @param listener                        listener in charge of handling events.
390      * @param method                          robust estimator method.
391      * @return a robust 2D position estimator.
392      */
393     public static RobustRangingAndRssiPositionEstimator2D create(
394             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
395             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener, final RobustEstimatorMethod method) {
396         return switch (method) {
397             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(listener);
398             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(listener);
399             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(listener);
400             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
401                     fingerprintReadingQualityScores, listener);
402             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
403                     fingerprintReadingQualityScores, listener);
404         };
405     }
406 
407     /**
408      * Creates a robust 2D position estimator.
409      *
410      * @param sourceQualityScores             quality scores corresponding to
411      *                                        each provided located radio source.
412      *                                        The larger the score value the better
413      *                                        the quality of the radio source.
414      * @param fingerprintReadingQualityScores quality scores corresponding to readings
415      *                                        within provided fingerprint. The larger
416      *                                        the score the better the quality of the
417      *                                        reading.
418      * @param sources                         located radio sources used for
419      *                                        lateration.
420      * @param listener                        listener in charge of handling events.
421      * @param method                          robust estimator method.
422      * @return a robust 2D position estimator.
423      * @throws IllegalArgumentException if provided sources is null or the number of
424      *                                  provided sources is less than the required minimum.
425      */
426     public static RobustRangingAndRssiPositionEstimator2D create(
427             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
428             final List<? extends RadioSourceLocated<Point2D>> sources,
429             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener, final RobustEstimatorMethod method) {
430         return switch (method) {
431             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(sources, listener);
432             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(sources, listener);
433             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(sources, listener);
434             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
435                     fingerprintReadingQualityScores, sources, listener);
436             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
437                     fingerprintReadingQualityScores, sources, listener);
438         };
439     }
440 
441     /**
442      * Creates a robust 2D position estimator.
443      *
444      * @param sourceQualityScores             quality scores corresponding to
445      *                                        each provided located radio source.
446      *                                        The larger the score value the better
447      *                                        the quality of the radio source.
448      * @param fingerprintReadingQualityScores quality scores corresponding to readings
449      *                                        within provided fingerprint. The larger
450      *                                        the score the better the quality of the
451      *                                        reading.
452      * @param fingerprint                     fingerprint containing ranging+RSSI
453      *                                        readings at an unknown location for
454      *                                        provided located radio sources.
455      * @param listener                        listener in charge of handling events.
456      * @param method                          robust estimator method.
457      * @return a robust 2D position estimator.
458      * @throws IllegalArgumentException if provided fingerprint is null.
459      */
460     public static RobustRangingAndRssiPositionEstimator2D create(
461             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
462             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
463                     extends RadioSource>> fingerprint,
464             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener,
465             final RobustEstimatorMethod method) {
466         return switch (method) {
467             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(fingerprint, listener);
468             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(fingerprint, listener);
469             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(fingerprint, listener);
470             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
471                     fingerprintReadingQualityScores, fingerprint, listener);
472             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
473                     fingerprintReadingQualityScores, fingerprint, listener);
474         };
475     }
476 
477     /**
478      * Creates a robust 2D position estimator.
479      *
480      * @param sourceQualityScores             quality scores corresponding to
481      *                                        each provided located radio source.
482      *                                        The larger the score value the better
483      *                                        the quality of the radio source.
484      * @param fingerprintReadingQualityScores quality scores corresponding to readings
485      *                                        within provided fingerprint. The larger
486      *                                        the score the better the quality of the
487      *                                        reading.
488      * @param sources                         located radio sources used for
489      *                                        lateration.
490      * @param fingerprint                     fingerprint containing ranging+RSSI
491      *                                        readings at an unknown location for
492      *                                        provided located radio sources.
493      * @param listener                        listener in charge of handling events.
494      * @param method                          robust estimator method.
495      * @return a robust 2D position estimator.
496      * @throws IllegalArgumentException if either provided sources or fingerprint is null
497      *                                  or the number of provided sources is less than the required minimum.
498      */
499     public static RobustRangingAndRssiPositionEstimator2D create(
500             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
501             final List<? extends RadioSourceLocated<Point2D>> sources,
502             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
503                     extends RadioSource>> fingerprint,
504             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener, final RobustEstimatorMethod method) {
505         return switch (method) {
506             case RANSAC -> new RANSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint, listener);
507             case LMEDS -> new LMedSRobustRangingAndRssiPositionEstimator2D(sources, fingerprint, listener);
508             case MSAC -> new MSACRobustRangingAndRssiPositionEstimator2D(sources, fingerprint, listener);
509             case PROSAC -> new PROSACRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
510                     fingerprintReadingQualityScores, sources, fingerprint, listener);
511             default -> new PROMedSRobustRangingAndRssiPositionEstimator2D(sourceQualityScores,
512                     fingerprintReadingQualityScores, sources, fingerprint, listener);
513         };
514     }
515 
516     /**
517      * Creates a robust 2D position estimator.
518      *
519      * @return a robust 2D position estimator.
520      */
521     public static RobustRangingAndRssiPositionEstimator2D create() {
522         return create(DEFAULT_ROBUST_METHOD);
523     }
524 
525     /**
526      * Creates a robust 2D position estimator.
527      *
528      * @param sources located radio sources used for lateration.
529      * @return a robust 2D position estimator.
530      * @throws IllegalArgumentException if provided sources is null or the number of
531      *                                  provided sources is less than the required minimum.
532      */
533     public static RobustRangingAndRssiPositionEstimator2D create(
534             final List<? extends RadioSourceLocated<Point2D>> sources) {
535         return create(sources, DEFAULT_ROBUST_METHOD);
536     }
537 
538     /**
539      * Creates a robust 2D position estimator.
540      *
541      * @param fingerprint fingerprint containing ranging+RSSI readings at an unknown
542      *                    location for provided located radio sources.
543      * @return a robust 2D position estimator.
544      * @throws IllegalArgumentException if provided fingerprint is null.
545      */
546     public static RobustRangingAndRssiPositionEstimator2D create(
547             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
548                     extends RadioSource>> fingerprint) {
549         return create(fingerprint, DEFAULT_ROBUST_METHOD);
550     }
551 
552     /**
553      * Creates a robust 2D position estimator.
554      *
555      * @param sources     located radio sources used for lateration.
556      * @param fingerprint fingerprint containing ranging+RSSI readings at an unknown
557      *                    location for provided located radio sources.
558      * @return a robust 2D position estimator.
559      * @throws IllegalArgumentException if either provided sources or fingerprint is null
560      *                                  or the number of provided sources is less than the required minimum.
561      */
562     public static RobustRangingAndRssiPositionEstimator2D create(
563             final List<? extends RadioSourceLocated<Point2D>> sources,
564             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
565                     extends RadioSource>> fingerprint) {
566         return create(sources, fingerprint, DEFAULT_ROBUST_METHOD);
567     }
568 
569     /**
570      * Creates a robust 2D position estimator.
571      *
572      * @param listener listener in charge of handling events.
573      * @return a robust 2D position estimator.
574      */
575     public static RobustRangingAndRssiPositionEstimator2D create(
576             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener) {
577         return create(listener, DEFAULT_ROBUST_METHOD);
578     }
579 
580     /**
581      * Creates a robust 2D position estimator.
582      *
583      * @param sources  located radio sources used for lateration.
584      * @param listener listener in charge of handling events.
585      * @return a robust 2D position estimator.
586      * @throws IllegalArgumentException if provided sources is null or the number of
587      *                                  provided sources is less than the required minimum.
588      */
589     public static RobustRangingAndRssiPositionEstimator2D create(
590             final List<? extends RadioSourceLocated<Point2D>> sources,
591             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener) {
592         return create(sources, listener, DEFAULT_ROBUST_METHOD);
593     }
594 
595     /**
596      * Creates a robust 2D position estimator.
597      *
598      * @param fingerprint fingerprint containing ranging+RSSI readings at an unknown
599      *                    location for provided located radio sources.
600      * @param listener    listener in charge of handling events.
601      * @return a robust 2D position estimator.
602      * @throws IllegalArgumentException if provided fingerprint is null.
603      */
604     public static RobustRangingAndRssiPositionEstimator2D create(
605             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
606                     extends RadioSource>> fingerprint,
607             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener) {
608         return create(fingerprint, listener, DEFAULT_ROBUST_METHOD);
609     }
610 
611     /**
612      * Creates a robust 2D position estimator.
613      *
614      * @param sources     located radio sources used for lateration.
615      * @param fingerprint fingerprint containing ranging+RSSI readings at an unknown
616      *                    location for provided located radio sources.
617      * @param listener    listener in charge of handling events.
618      * @return a robust 2D position estimator.
619      * @throws IllegalArgumentException if either provided sources or fingerprint is null
620      *                                  or the number of provided sources is less than the required minimum.
621      */
622     public static RobustRangingAndRssiPositionEstimator2D create(
623             final List<? extends RadioSourceLocated<Point2D>> sources,
624             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
625                     extends RadioSource>> fingerprint,
626             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener) {
627         return create(sources, fingerprint, listener, DEFAULT_ROBUST_METHOD);
628     }
629 
630     /**
631      * Creates a robust 2D position estimator.
632      *
633      * @param sourceQualityScores             quality scores corresponding to
634      *                                        each provided located radio source.
635      *                                        The larger the score value the better
636      *                                        the quality of the radio source.
637      * @param fingerprintReadingQualityScores quality scores corresponding to readings
638      *                                        within provided fingerprint. The larger
639      *                                        the score the better the quality of the
640      *                                        reading.
641      * @return a robust 2D position estimator.
642      */
643     public static RobustRangingAndRssiPositionEstimator2D create(
644             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores) {
645         return create(sourceQualityScores, fingerprintReadingQualityScores, DEFAULT_ROBUST_METHOD);
646     }
647 
648     /**
649      * Creates a robust 2D position estimator.
650      *
651      * @param sourceQualityScores             quality scores corresponding to
652      *                                        each provided located radio source.
653      *                                        The larger the score value the better
654      *                                        the quality of the radio source.
655      * @param fingerprintReadingQualityScores quality scores corresponding to readings
656      *                                        within provided fingerprint. The larger
657      *                                        the score the better the quality of the
658      *                                        reading.
659      * @param sources                         located radio sources used for
660      *                                        lateration.
661      * @return a robust 2D position estimator.
662      * @throws IllegalArgumentException if provided sources is null or the number of
663      *                                  provided sources is less than the required minimum.
664      */
665     public static RobustRangingAndRssiPositionEstimator2D create(
666             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
667             final List<? extends RadioSourceLocated<Point2D>> sources) {
668         return create(sourceQualityScores, fingerprintReadingQualityScores, sources, DEFAULT_ROBUST_METHOD);
669     }
670 
671     /**
672      * Creates a robust 2D position estimator.
673      *
674      * @param sourceQualityScores             quality scores corresponding to
675      *                                        each provided located radio source.
676      *                                        The larger the score value the better
677      *                                        the quality of the radio source.
678      * @param fingerprintReadingQualityScores quality scores corresponding to readings
679      *                                        within provided fingerprint. The larger
680      *                                        the score the better the quality of the
681      *                                        reading.
682      * @param fingerprint                     fingerprint containing ranging+RSSI
683      *                                        readings at an unknown location for
684      *                                        provided located radio sources.
685      * @return a robust 2D position estimator.
686      * @throws IllegalArgumentException if provided fingerprint is null.
687      */
688     public static RobustRangingAndRssiPositionEstimator2D create(
689             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
690             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
691                     extends RadioSource>> fingerprint) {
692         return create(sourceQualityScores, fingerprintReadingQualityScores, fingerprint, DEFAULT_ROBUST_METHOD);
693     }
694 
695     /**
696      * Creates a robust 2D position estimator.
697      *
698      * @param sourceQualityScores             quality scores corresponding to
699      *                                        each provided located radio source.
700      *                                        The larger the score value the better
701      *                                        the quality of the radio source.
702      * @param fingerprintReadingQualityScores quality scores corresponding to readings
703      *                                        within provided fingerprint. The larger
704      *                                        the score the better the quality of the
705      *                                        reading.
706      * @param sources                         located radio sources used for
707      *                                        lateration.
708      * @param fingerprint                     fingerprint containing ranging+RSSI
709      *                                        readings at an unknown location for
710      *                                        provided located radio sources.
711      * @return a robust 2D position estimator.
712      * @throws IllegalArgumentException if either provided sources or fingerprint is null
713      *                                  or the number of provided sources is less than the required minimum.
714      */
715     public static RobustRangingAndRssiPositionEstimator2D create(
716             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
717             final List<? extends RadioSourceLocated<Point2D>> sources,
718             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
719                     extends RadioSource>> fingerprint) {
720         return create(sourceQualityScores, fingerprintReadingQualityScores, sources, fingerprint,
721                 DEFAULT_ROBUST_METHOD);
722     }
723 
724     /**
725      * Creates a robust 2D position estimator.
726      *
727      * @param sourceQualityScores             quality scores corresponding to
728      *                                        each provided located radio source.
729      *                                        The larger the score value the better
730      *                                        the quality of the radio source.
731      * @param fingerprintReadingQualityScores quality scores corresponding to readings
732      *                                        within provided fingerprint. The larger
733      *                                        the score the better the quality of the
734      *                                        reading.
735      * @param listener                        listener in charge of handling events.
736      * @return a robust 2D position estimator.
737      */
738     public static RobustRangingAndRssiPositionEstimator2D create(
739             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
740             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener) {
741         return create(sourceQualityScores, fingerprintReadingQualityScores, listener, DEFAULT_ROBUST_METHOD);
742     }
743 
744     /**
745      * Creates a robust 2D position estimator.
746      *
747      * @param sourceQualityScores             quality scores corresponding to
748      *                                        each provided located radio source.
749      *                                        The larger the score value the better
750      *                                        the quality of the radio source.
751      * @param fingerprintReadingQualityScores quality scores corresponding to readings
752      *                                        within provided fingerprint. The larger
753      *                                        the score the better the quality of the
754      *                                        reading.
755      * @param sources                         located radio sources used for
756      *                                        lateration.
757      * @param listener                        listener in charge of handling events.
758      * @return a robust 2D position estimator.
759      * @throws IllegalArgumentException if provided sources is null or the number of
760      *                                  provided sources is less than the required minimum.
761      */
762     public static RobustRangingAndRssiPositionEstimator2D create(
763             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
764             final List<? extends RadioSourceLocated<Point2D>> sources,
765             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener) {
766         return create(sourceQualityScores, fingerprintReadingQualityScores, sources, listener, DEFAULT_ROBUST_METHOD);
767     }
768 
769     /**
770      * Creates a robust 2D position estimator.
771      *
772      * @param sourceQualityScores             quality scores corresponding to
773      *                                        each provided located radio source.
774      *                                        The larger the score value the better
775      *                                        the quality of the radio source.
776      * @param fingerprintReadingQualityScores quality scores corresponding to readings
777      *                                        within provided fingerprint. The larger
778      *                                        the score the better the quality of the
779      *                                        reading.
780      * @param fingerprint                     fingerprint containing ranging+RSSI
781      *                                        readings at an unknown location for
782      *                                        provided located radio sources.
783      * @param listener                        listener in charge of handling events.
784      * @return a robust 2D position estimator.
785      * @throws IllegalArgumentException if provided fingerprint is null.
786      */
787     public static RobustRangingAndRssiPositionEstimator2D create(
788             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
789             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
790                     extends RadioSource>> fingerprint,
791             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener) {
792         return create(sourceQualityScores, fingerprintReadingQualityScores, fingerprint, listener,
793                 DEFAULT_ROBUST_METHOD);
794     }
795 
796     /**
797      * Creates a robust 2D position estimator.
798      *
799      * @param sourceQualityScores             quality scores corresponding to
800      *                                        each provided located radio source.
801      *                                        The larger the score value the better
802      *                                        the quality of the radio source.
803      * @param fingerprintReadingQualityScores quality scores corresponding to readings
804      *                                        within provided fingerprint. The larger
805      *                                        the score the better the quality of the
806      *                                        reading.
807      * @param sources                         located radio sources used for
808      *                                        lateration.
809      * @param fingerprint                     fingerprint containing ranging+RSSI
810      *                                        readings at an unknown location for
811      *                                        provided located radio sources.
812      * @param listener                        listener in charge of handling events.
813      * @return a robust 2D position estimator.
814      * @throws IllegalArgumentException if either provided sources or fingerprint is null
815      *                                  or the number of provided sources is less than the required minimum.
816      */
817     public static RobustRangingAndRssiPositionEstimator2D create(
818             final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
819             final List<? extends RadioSourceLocated<Point2D>> sources,
820             final RangingAndRssiFingerprint<? extends RadioSource, ? extends RangingAndRssiReading<?
821                     extends RadioSource>> fingerprint,
822             final RobustRangingAndRssiPositionEstimatorListener<Point2D> listener) {
823         return create(sourceQualityScores, fingerprintReadingQualityScores, sources, fingerprint, listener,
824                 DEFAULT_ROBUST_METHOD);
825     }
826 
827     /**
828      * Sets positions, distances and standard deviations of distances on internal
829      * lateration solver.
830      *
831      * @param positions                  positions to be set.
832      * @param distances                  distances to be set.
833      * @param distanceStandardDeviations standard deviations of distances to be set.
834      * @param distanceQualityScores      distance quality scores or null if not
835      *                                   required.
836      */
837     @Override
838     protected void setPositionsDistancesDistanceStandardDeviationsAndQualityScores(
839             final List<Point2D> positions, List<Double> distances, final List<Double> distanceStandardDeviations,
840             final List<Double> distanceQualityScores) {
841         final var size = positions.size();
842         Point2D[] positionsArray = new InhomogeneousPoint2D[size];
843         positionsArray = positions.toArray(positionsArray);
844 
845         final var distancesArray = new double[size];
846         final var distanceStandardDeviationsArray = new double[size];
847 
848         double[] qualityScoresArray = null;
849         if (distanceQualityScores != null) {
850             qualityScoresArray = new double[size];
851         }
852 
853         for (var i = 0; i < size; i++) {
854             distancesArray[i] = distances.get(i);
855             distanceStandardDeviationsArray[i] = distanceStandardDeviations.get(i);
856 
857             if (qualityScoresArray != null) {
858                 qualityScoresArray[i] = distanceQualityScores.get(i);
859             }
860         }
861 
862         try {
863             laterationSolver.setPositionsDistancesAndStandardDeviations(positionsArray, distancesArray,
864                     distanceStandardDeviationsArray);
865 
866             if (qualityScoresArray != null) {
867                 laterationSolver.setQualityScores(qualityScoresArray);
868             }
869         } catch (final LockedException e) {
870             throw new IllegalArgumentException(e);
871         }
872     }
873 }