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