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