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