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