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