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