View Javadoc
1   /*
2    * Copyright (C) 2018 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.radiosource;
17  
18  import com.irurueta.geometry.Point2D;
19  import com.irurueta.navigation.LockedException;
20  import com.irurueta.navigation.indoor.*;
21  
22  import java.util.List;
23  
24  /**
25   * Robustly estimate 2D position, transmitted power and path-loss exponent of a radio
26   * source (e.g. Wi-Fi access point or bluetooth beacon), by discarding
27   * outliers and assuming that the ranging data is available to obtain position with
28   * greater accuracy and that the radio source emits isotropically following the
29   * expression below:
30   * Pr = Pt*Gt*Gr*lambda^2 / (4*pi*d)^2,
31   * where Pr is the received power (expressed in mW),
32   * Gt is the Gain of the transmission antenna
33   * Gr is the Gain of the receiver antenna
34   * d is the distance between emitter and receiver
35   * and lambda is the wavelength and is equal to: lambda = c / f,
36   * where c is the speed of light
37   * and f is the carrier frequency of the radio signal.
38   * <p>
39   * Implementations of this class sequentially estimate position and then remaining
40   * parameters. First ranging data is used to robustly estimate position and then
41   * remaining parameters are robustly estimated using former estimated position as
42   * an initial guess.
43   * <p>
44   * Because usually information about the antenna of the radio source cannot be
45   * retrieved (because many measurements are made on unknown devices where
46   * physical access is not possible), this implementation will estimate the
47   * equivalent transmitted power as: Pte = Pt * Gt * Gr.
48   * If Readings contain RSSI standard deviations, those values will be used,
49   * otherwise it will be assumed an RSSI standard deviation of 1 dB.
50   * <p>
51   * This implementation is like SequentialRobustRangingAndRssiRadioSourceEstimator but
52   * allows mixing different kinds of located radio source readings (ranging, RSSI
53   * and ranging+RSSI).
54   *
55   * @param <S> a {@link RadioSource} type.
56   */
57  @SuppressWarnings("Duplicates")
58  public class SequentialRobustMixedRadioSourceEstimator2D<S extends RadioSource> extends
59          SequentialRobustMixedRadioSourceEstimator<S, Point2D> {
60  
61      /**
62       * Constructor.
63       */
64      public SequentialRobustMixedRadioSourceEstimator2D() {
65          rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
66      }
67  
68      /**
69       * Constructor.
70       * Sets signal readings belonging to the same radio source.
71       *
72       * @param readings signal readings belonging to the same radio source.
73       * @throws IllegalArgumentException if readings are not valid.
74       */
75      public SequentialRobustMixedRadioSourceEstimator2D(final List<? extends ReadingLocated<Point2D>> readings) {
76          super(readings);
77          rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
78      }
79  
80      /**
81       * Constructor.
82       *
83       * @param listener listener in charge of attending events raised by this instance.
84       */
85      public SequentialRobustMixedRadioSourceEstimator2D(
86              final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
87          super(listener);
88          rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
89      }
90  
91      /**
92       * Constructor.
93       * Sets signal readings belonging to the same radio source.
94       *
95       * @param readings signal readings belonging to the same radio source.
96       * @param listener listener in charge of attending events raised by this instance.
97       * @throws IllegalArgumentException if readings are not valid.
98       */
99      public SequentialRobustMixedRadioSourceEstimator2D(
100             final List<? extends ReadingLocated<Point2D>> readings,
101             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
102         super(readings, listener);
103         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
104     }
105 
106     /**
107      * Constructor.
108      * Sets signal readings belonging to the same radio source.
109      *
110      * @param readings        signal readings belonging to the same radio source.
111      * @param initialPosition initial position to start the estimation of radio
112      *                        source position.
113      * @throws IllegalArgumentException if readings are not valid.
114      */
115     public SequentialRobustMixedRadioSourceEstimator2D(
116             final List<? extends ReadingLocated<Point2D>> readings, final Point2D initialPosition) {
117         super(readings, initialPosition);
118         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
119     }
120 
121     /**
122      * Constructor.
123      *
124      * @param initialPosition initial position to start the estimation of radio
125      *                        source position.
126      */
127     public SequentialRobustMixedRadioSourceEstimator2D(final Point2D initialPosition) {
128         super(initialPosition);
129         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
130     }
131 
132     /**
133      * Constructor.
134      *
135      * @param initialPosition initial position to start the estimation of radio
136      *                        source position.
137      * @param listener        listener in charge of attending events raised by this instance.
138      */
139     public SequentialRobustMixedRadioSourceEstimator2D(
140             final Point2D initialPosition,
141             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
142         super(initialPosition, listener);
143         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
144     }
145 
146     /**
147      * Constructor.
148      * Sets signal readings belonging to the same radio source.
149      *
150      * @param readings        signal readings belonging to the same radio source.
151      * @param initialPosition initial position to start the estimation of radio
152      *                        source position.
153      * @param listener        listener in charge of attending events raised by this instance.
154      * @throws IllegalArgumentException if readings are not valid.
155      */
156     public SequentialRobustMixedRadioSourceEstimator2D(
157             final List<? extends ReadingLocated<Point2D>> readings, final Point2D initialPosition,
158             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
159         super(readings, initialPosition, listener);
160         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
161     }
162 
163     /**
164      * Constructor.
165      *
166      * @param initialTransmittedPowerdBm initial transmitted power to start the
167      *                                   estimation of radio source transmitted power
168      *                                   (expressed in dBm's).
169      */
170     public SequentialRobustMixedRadioSourceEstimator2D(final Double initialTransmittedPowerdBm) {
171         super(initialTransmittedPowerdBm);
172         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
173     }
174 
175     /**
176      * Constructor.
177      * Sets signal readings belonging to the same radio source.
178      *
179      * @param readings                   signal readings belonging to the same radio source.
180      * @param initialTransmittedPowerdBm initial transmitted power to start the
181      *                                   estimation of radio source transmitted power
182      *                                   (expressed in dBm's).
183      * @throws IllegalArgumentException if readings are not valid.
184      */
185     public SequentialRobustMixedRadioSourceEstimator2D(
186             final List<? extends ReadingLocated<Point2D>> readings, final Double initialTransmittedPowerdBm) {
187         super(readings, initialTransmittedPowerdBm);
188         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
189     }
190 
191     /**
192      * Constructor.
193      *
194      * @param initialTransmittedPowerdBm initial transmitted power to start the
195      *                                   estimation of radio source transmitted power
196      *                                   (expressed in dBm's).
197      * @param listener                   listener in charge of attending events raised by this instance.
198      */
199     public SequentialRobustMixedRadioSourceEstimator2D(
200             final Double initialTransmittedPowerdBm,
201             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
202         super(initialTransmittedPowerdBm, listener);
203         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
204     }
205 
206     /**
207      * Constructor.
208      * Sets signal readings belonging to the same radio source.
209      *
210      * @param readings                   signal readings belonging to the same radio source.
211      * @param initialTransmittedPowerdBm initial transmitted power to start the
212      *                                   estimation of radio source transmitted power
213      *                                   (expressed in dBm's).
214      * @param listener                   listener in charge of attending events raised by this instance.
215      * @throws IllegalArgumentException if readings are not valid.
216      */
217     public SequentialRobustMixedRadioSourceEstimator2D(
218             final List<? extends ReadingLocated<Point2D>> readings, final Double initialTransmittedPowerdBm,
219             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
220         super(readings, initialTransmittedPowerdBm, listener);
221         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
222     }
223 
224     /**
225      * Constructor.
226      * Sets signal readings belonging to the same radio source.
227      *
228      * @param readings                   signal readings belonging to the same radio source.
229      * @param initialPosition            initial position to start the estimation of radio
230      *                                   source position.
231      * @param initialTransmittedPowerdBm initial transmitted power to start the
232      *                                   estimation of radio source transmitted power
233      *                                   (expressed in dBm's).
234      * @throws IllegalArgumentException if readings are not valid.
235      */
236     public SequentialRobustMixedRadioSourceEstimator2D(
237             final List<? extends ReadingLocated<Point2D>> readings, final Point2D initialPosition,
238             final Double initialTransmittedPowerdBm) {
239         super(readings, initialPosition, initialTransmittedPowerdBm);
240         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
241     }
242 
243     /**
244      * Constructor.
245      *
246      * @param initialPosition            initial position to start the estimation of radio
247      *                                   source position.
248      * @param initialTransmittedPowerdBm initial transmitted power to start the
249      *                                   estimation of radio source transmitted power
250      *                                   (expressed in dBm's).
251      */
252     public SequentialRobustMixedRadioSourceEstimator2D(
253             final Point2D initialPosition, final Double initialTransmittedPowerdBm) {
254         super(initialPosition, initialTransmittedPowerdBm);
255         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
256     }
257 
258     /**
259      * Constructor.
260      *
261      * @param initialPosition            initial position to start the estimation of radio
262      *                                   source position.
263      * @param initialTransmittedPowerdBm initial transmitted power to start the
264      *                                   estimation of radio source transmitted power
265      *                                   (expressed in dBm's).
266      * @param listener                   in charge of attending events raised by this instance.
267      */
268     public SequentialRobustMixedRadioSourceEstimator2D(
269             final Point2D initialPosition, final Double initialTransmittedPowerdBm,
270             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
271         super(initialPosition, initialTransmittedPowerdBm, listener);
272         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
273     }
274 
275     /**
276      * Constructor.
277      * Sets signal readings belonging to the same radio source.
278      *
279      * @param readings                   signal readings belonging to the same radio source.
280      * @param initialPosition            initial position to start the estimation of radio
281      *                                   source position.
282      * @param initialTransmittedPowerdBm initial transmitted power to start the
283      *                                   estimation of radio source transmitted power
284      *                                   (expressed in dBm's).
285      * @param listener                   listener in charge of attending events raised by this instance.
286      * @throws IllegalArgumentException if readings are not valid.
287      */
288     public SequentialRobustMixedRadioSourceEstimator2D(
289             final List<? extends ReadingLocated<Point2D>> readings, final Point2D initialPosition,
290             final Double initialTransmittedPowerdBm,
291             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
292         super(readings, initialPosition, initialTransmittedPowerdBm, listener);
293         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
294     }
295 
296     /**
297      * Constructor.
298      * Sets signal readings belonging to the same radio source.
299      *
300      * @param readings                   signal readings belonging to the same radio source.
301      * @param initialPosition            initial position to start the estimation of radio
302      *                                   source position.
303      * @param initialTransmittedPowerdBm initial transmitted power to start the
304      *                                   estimation of radio source transmitted power
305      *                                   (expressed in dBm's).
306      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
307      * @throws IllegalArgumentException if readings are not valid.
308      */
309     public SequentialRobustMixedRadioSourceEstimator2D(
310             final List<? extends ReadingLocated<Point2D>> readings, final Point2D initialPosition,
311             final Double initialTransmittedPowerdBm, final double initialPathLossExponent) {
312         super(readings, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent);
313         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
314     }
315 
316     /**
317      * Constructor.
318      *
319      * @param initialPosition            initial position to start the estimation of radio
320      *                                   source position.
321      * @param initialTransmittedPowerdBm initial transmitted power to start the
322      *                                   estimation of radio source transmitted power
323      *                                   (expressed in dBm's).
324      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
325      */
326     public SequentialRobustMixedRadioSourceEstimator2D(
327             final Point2D initialPosition, final Double initialTransmittedPowerdBm,
328             final double initialPathLossExponent) {
329         super(initialPosition, initialTransmittedPowerdBm, initialPathLossExponent);
330         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
331     }
332 
333     /**
334      * Constructor.
335      *
336      * @param initialPosition            initial position to start the estimation of radio
337      *                                   source position.
338      * @param initialTransmittedPowerdBm initial transmitted power to start the
339      *                                   estimation of radio source transmitted power
340      *                                   (expressed in dBm's).
341      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
342      * @param listener                   listener in charge of attending events raised by this instance.
343      */
344     public SequentialRobustMixedRadioSourceEstimator2D(
345             final Point2D initialPosition, final Double initialTransmittedPowerdBm,
346             final double initialPathLossExponent,
347             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
348         super(initialPosition, initialTransmittedPowerdBm, initialPathLossExponent, listener);
349         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
350     }
351 
352     /**
353      * Constructors.
354      * Sets signal readings belonging to the same radio source.
355      *
356      * @param readings                   signal readings belonging to the same radio source.
357      * @param initialPosition            initial position to start the estimation of radio
358      *                                   source position.
359      * @param initialTransmittedPowerdBm initial transmitted power to start the
360      *                                   estimation of radio source transmitted power
361      *                                   (expressed in dBm's).
362      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
363      * @param listener                   listener in charge of attending events raised by this instance.
364      * @throws IllegalArgumentException if readings are not valid.
365      */
366     public SequentialRobustMixedRadioSourceEstimator2D(
367             final List<? extends ReadingLocated<Point2D>> readings, final Point2D initialPosition,
368             final Double initialTransmittedPowerdBm, final double initialPathLossExponent,
369             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
370         super(readings, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent, listener);
371         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
372     }
373 
374     /**
375      * Constructor.
376      *
377      * @param qualityScores quality scores corresponding to each provided sample.
378      *                      The larger the score value the better the quality of
379      *                      the sample.
380      * @throws IllegalArgumentException if quality scores is null, or length of
381      *                                  quality scores is less than required minimum.
382      */
383     public SequentialRobustMixedRadioSourceEstimator2D(final double[] qualityScores) {
384         super(qualityScores);
385         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
386     }
387 
388     /**
389      * Constructor.
390      * Sets signal readings belonging to the same radio source.
391      *
392      * @param qualityScores quality scores corresponding to each provided sample.
393      *                      The larger the score value the better the quality of
394      *                      the sample.
395      * @param readings      signal readings belonging to the same radio source.
396      * @throws IllegalArgumentException if readings are not valid, quality scores is
397      *                                  null, or length of quality scores is less than required minimum.
398      */
399     public SequentialRobustMixedRadioSourceEstimator2D(
400             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings) {
401         super(qualityScores, readings);
402         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
403     }
404 
405     /**
406      * Constructor.
407      *
408      * @param qualityScores quality scores corresponding to each provided sample.
409      *                      The larger the score value the better the quality of
410      *                      the sample.
411      * @param listener      listener in charge of attending events raised by this instance.
412      * @throws IllegalArgumentException if quality scores is null, or length
413      *                                  of quality scores is less than required minimum.
414      */
415     public SequentialRobustMixedRadioSourceEstimator2D(
416             final double[] qualityScores,
417             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
418         super(qualityScores, listener);
419         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
420     }
421 
422     /**
423      * Constructor.
424      * Sets signal readings belonging to the same radio source.
425      *
426      * @param qualityScores quality scores corresponding to each provided sample.
427      *                      The larger the score value the better the quality of
428      *                      the sample.
429      * @param readings      signal readings belonging to the same radio source.
430      * @param listener      listener in charge of attending events raised by this instance.
431      * @throws IllegalArgumentException if readings are not valid, quality scores is
432      *                                  null, or length of quality scores is less than required minimum.
433      */
434     public SequentialRobustMixedRadioSourceEstimator2D(
435             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings,
436             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
437         super(qualityScores, readings, listener);
438         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
439     }
440 
441     /**
442      * Constructor.
443      * Sets signal readings belonging to the same radio source.
444      *
445      * @param qualityScores   quality scores corresponding to each provided sample.
446      *                        The larger the score value the better the quality of
447      *                        the sample.
448      * @param readings        signal readings belonging to the same radio source.
449      * @param initialPosition initial position to start the estimation of radio
450      *                        source position.
451      * @throws IllegalArgumentException if readings are not valid, quality scores is
452      *                                  null, or length of quality scores is less than required minimum.
453      */
454     public SequentialRobustMixedRadioSourceEstimator2D(
455             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings,
456             final Point2D initialPosition) {
457         super(qualityScores, readings, initialPosition);
458         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
459     }
460 
461     /**
462      * Constructor.
463      *
464      * @param qualityScores   quality scores corresponding to each provided sample.
465      *                        The larger the score value the better the quality of
466      *                        the sample.
467      * @param initialPosition initial position to start the estimation of radio
468      *                        source position.
469      * @throws IllegalArgumentException if quality scores is null, or length
470      *                                  of quality scores is less than required minimum.
471      */
472     public SequentialRobustMixedRadioSourceEstimator2D(final double[] qualityScores, final Point2D initialPosition) {
473         super(qualityScores, initialPosition);
474         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
475     }
476 
477     /**
478      * Constructor.
479      *
480      * @param qualityScores   quality scores corresponding to each provided sample.
481      *                        The larger the score value the better the quality of
482      *                        the sample.
483      * @param initialPosition initial position to start the estimation of radio
484      *                        source position.
485      * @param listener        listener in charge of attending events raised by this instance.
486      * @throws IllegalArgumentException if quality scores is null, or length
487      *                                  of quality scores is less than required minimum.
488      */
489     public SequentialRobustMixedRadioSourceEstimator2D(
490             final double[] qualityScores, final Point2D initialPosition,
491             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
492         super(qualityScores, initialPosition, listener);
493         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
494     }
495 
496     /**
497      * Constructor.
498      * Sets signal readings belonging to the same radio source.
499      *
500      * @param qualityScores   quality scores corresponding to each provided sample.
501      *                        The larger the score value the better the quality of
502      *                        the sample.
503      * @param readings        signal readings belonging to the same radio source.
504      * @param initialPosition initial position to start the estimation of radio
505      *                        source position.
506      * @param listener        listener in charge of attending events raised by this instance.
507      * @throws IllegalArgumentException if readings are not valid, quality scores
508      *                                  is null, or length of quality scores is less than required minimum.
509      */
510     public SequentialRobustMixedRadioSourceEstimator2D(
511             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings,
512             final Point2D initialPosition,
513             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
514         super(qualityScores, readings, initialPosition, listener);
515         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
516     }
517 
518     /**
519      * Constructor.
520      *
521      * @param qualityScores              quality scores corresponding to each provided sample.
522      *                                   The larger the score value the better the quality of
523      *                                   the sample.
524      * @param initialTransmittedPowerdBm initial transmitted power to start the
525      *                                   estimation of radio source transmitted power
526      *                                   (expressed in dBm's).
527      * @throws IllegalArgumentException if quality scores is null, or length
528      *                                  of quality scores is less than required minimum.
529      */
530     public SequentialRobustMixedRadioSourceEstimator2D(
531             final double[] qualityScores, final Double initialTransmittedPowerdBm) {
532         super(qualityScores, initialTransmittedPowerdBm);
533         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
534     }
535 
536     /**
537      * Constructor.
538      * Sets signal readings belonging to the same radio source.
539      *
540      * @param qualityScores              quality scores corresponding to each provided sample.
541      *                                   The larger the score value the better the quality of
542      *                                   the sample.
543      * @param readings                   signal readings belonging to the same radio source.
544      * @param initialTransmittedPowerdBm initial transmitted power to start the
545      *                                   estimation of radio source transmitted power
546      *                                   (expressed in dBm's).
547      * @throws IllegalArgumentException if readings are not valid, quality scores
548      *                                  is null, or length of quality scores is less than required minimum.
549      */
550     public SequentialRobustMixedRadioSourceEstimator2D(
551             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings,
552             final Double initialTransmittedPowerdBm) {
553         super(qualityScores, readings, initialTransmittedPowerdBm);
554         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
555     }
556 
557     /**
558      * Constructor.
559      *
560      * @param qualityScores              quality scores corresponding to each provided sample.
561      *                                   The larger the score value the better the quality of
562      *                                   the sample.
563      * @param initialTransmittedPowerdBm initial transmitted power to start the
564      *                                   estimation of radio source transmitted power
565      *                                   (expressed in dBm's).
566      * @param listener                   listener in charge of attending events raised by this instance.
567      * @throws IllegalArgumentException if quality scores is null, or length
568      *                                  of quality scores is less than required minimum.
569      */
570     public SequentialRobustMixedRadioSourceEstimator2D(
571             final double[] qualityScores, final Double initialTransmittedPowerdBm,
572             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
573         super(qualityScores, initialTransmittedPowerdBm, listener);
574         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
575     }
576 
577     /**
578      * Constructor.
579      * Sets signal readings belonging to the same radio source.
580      *
581      * @param qualityScores              quality scores corresponding to each provided
582      *                                   sample. The larger the score value the better
583      *                                   the quality of the sample.
584      * @param readings                   signal readings belonging to the same radio source.
585      * @param initialTransmittedPowerdBm initial transmitted power to start the
586      *                                   estimation of radio source transmitted power
587      *                                   (expressed in dBm's).
588      * @param listener                   listener in charge of attending events raised by this instance.
589      * @throws IllegalArgumentException if readings are not valid, quality scores
590      *                                  is null, or length of quality scores is less than required minimum.
591      */
592     public SequentialRobustMixedRadioSourceEstimator2D(
593             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings,
594             final Double initialTransmittedPowerdBm,
595             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
596         super(qualityScores, readings, initialTransmittedPowerdBm, listener);
597         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
598     }
599 
600     /**
601      * Constructor.
602      * Sets signal readings belonging to the same radio source.
603      *
604      * @param qualityScores              quality scores corresponding to each provided
605      *                                   sample. The larger the score value the better
606      *                                   the quality of the sample.
607      * @param readings                   signal readings belonging to the same radio source.
608      * @param initialPosition            initial position to start the estimation of radio
609      *                                   source position.
610      * @param initialTransmittedPowerdBm initial transmitted power to start the
611      *                                   estimation of radio source transmitted power
612      *                                   (expressed in dBm's).
613      * @throws IllegalArgumentException if readings are not valid, quality scores
614      *                                  is null, or length of quality scores is less than required minimum.
615      */
616     public SequentialRobustMixedRadioSourceEstimator2D(
617             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings,
618             final Point2D initialPosition, final Double initialTransmittedPowerdBm) {
619         super(qualityScores, readings, initialPosition, initialTransmittedPowerdBm);
620         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
621     }
622 
623     /**
624      * Constructor.
625      *
626      * @param qualityScores              quality scores corresponding to each provided
627      *                                   sample. The larger the score value the better
628      *                                   the quality of the sample.
629      * @param initialPosition            initial position to start the estimation of radio
630      *                                   source position.
631      * @param initialTransmittedPowerdBm initial transmitted power to start the
632      *                                   estimation of radio source transmitted power
633      *                                   (expressed in dBm's).
634      * @throws IllegalArgumentException if quality scores is null, or length
635      *                                  of quality scores is less than required minimum.
636      */
637     public SequentialRobustMixedRadioSourceEstimator2D(
638             final double[] qualityScores, final Point2D initialPosition, final Double initialTransmittedPowerdBm) {
639         super(qualityScores, initialPosition, initialTransmittedPowerdBm);
640         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
641     }
642 
643     /**
644      * Constructor.
645      *
646      * @param qualityScores              quality scores corresponding to each provided
647      *                                   sample. The larger the score value the better
648      *                                   the quality of the sample.
649      * @param initialPosition            initial position to start the estimation of radio
650      *                                   source position.
651      * @param initialTransmittedPowerdBm initial transmitted power to start the
652      *                                   estimation of radio source transmitted power
653      *                                   (expressed in dBm's).
654      * @param listener                   in charge of attending events raised by this instance.
655      * @throws IllegalArgumentException if quality scores is null, or length
656      *                                  of quality scores is less than required minimum.
657      */
658     public SequentialRobustMixedRadioSourceEstimator2D(
659             final double[] qualityScores, final Point2D initialPosition, final Double initialTransmittedPowerdBm,
660             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
661         super(qualityScores, initialPosition, initialTransmittedPowerdBm, listener);
662         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
663     }
664 
665     /**
666      * Constructor.
667      * Sets signal readings belonging to the same radio source.
668      *
669      * @param qualityScores              quality scores corresponding to each provided
670      *                                   sample. The larger the score value the better
671      *                                   the quality of the sample.
672      * @param readings                   signal readings belonging to the same radio source.
673      * @param initialPosition            initial position to start the estimation of radio
674      *                                   source position.
675      * @param initialTransmittedPowerdBm initial transmitted power to start the
676      *                                   estimation of radio source transmitted power
677      *                                   (expressed in dBm's).
678      * @param listener                   listener in charge of attending events raised by this instance.
679      * @throws IllegalArgumentException if readings are not valid, quality scores
680      *                                  is null, or length of quality scores is less than required minimum.
681      */
682     public SequentialRobustMixedRadioSourceEstimator2D(
683             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings,
684             final Point2D initialPosition, final Double initialTransmittedPowerdBm,
685             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
686         super(qualityScores, readings, initialPosition, initialTransmittedPowerdBm, listener);
687         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
688     }
689 
690     /**
691      * Constructor.
692      * Sets signal readings belonging to the same radio source.
693      *
694      * @param qualityScores              quality scores corresponding to each provided
695      *                                   sample. The larger the score value the better
696      *                                   the quality of the sample.
697      * @param readings                   signal readings belonging to the same radio source.
698      * @param initialPosition            initial position to start the estimation of radio
699      *                                   source position.
700      * @param initialTransmittedPowerdBm initial transmitted power to start the
701      *                                   estimation of radio source transmitted power
702      *                                   (expressed in dBm's).
703      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
704      * @throws IllegalArgumentException if readings are not valid, quality scores
705      *                                  is null, or length of quality scores is less than required minimum.
706      */
707     public SequentialRobustMixedRadioSourceEstimator2D(
708             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings,
709             final Point2D initialPosition, final Double initialTransmittedPowerdBm,
710             final double initialPathLossExponent) {
711         super(qualityScores, readings, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent);
712         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
713     }
714 
715     /**
716      * Constructor.
717      *
718      * @param qualityScores              quality scores corresponding to each provided
719      *                                   sample. The larger the score value the better
720      *                                   the quality of the sample.
721      * @param initialPosition            initial position to start the estimation of radio
722      *                                   source position.
723      * @param initialTransmittedPowerdBm initial transmitted power to start the
724      *                                   estimation of radio source transmitted power
725      *                                   (expressed in dBm's).
726      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
727      * @throws IllegalArgumentException if quality scores is null, or length
728      *                                  of quality scores is less than required minimum.
729      */
730     public SequentialRobustMixedRadioSourceEstimator2D(
731             final double[] qualityScores, final Point2D initialPosition, final Double initialTransmittedPowerdBm,
732             final double initialPathLossExponent) {
733         super(qualityScores, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent);
734         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
735     }
736 
737     /**
738      * Constructor.
739      *
740      * @param qualityScores              quality scores corresponding to each provided
741      *                                   sample. The larger the score value the better
742      *                                   the quality of the sample.
743      * @param initialPosition            initial position to start the estimation of radio
744      *                                   source position.
745      * @param initialTransmittedPowerdBm initial transmitted power to start the
746      *                                   estimation of radio source transmitted power
747      *                                   (expressed in dBm's).
748      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
749      * @param listener                   listener in charge of attending events raised by this instance.
750      * @throws IllegalArgumentException if quality scores is null, or length
751      *                                  of quality scores is less than required minimum.
752      */
753     public SequentialRobustMixedRadioSourceEstimator2D(
754             final double[] qualityScores, final Point2D initialPosition, final Double initialTransmittedPowerdBm,
755             final double initialPathLossExponent,
756             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
757         super(qualityScores, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent, listener);
758         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
759     }
760 
761     /**
762      * Constructors.
763      * Sets signal readings belonging to the same radio source.
764      *
765      * @param qualityScores              quality scores corresponding to each provided
766      *                                   sample. The larger the score value the better
767      *                                   the quality of the sample.
768      * @param readings                   signal readings belonging to the same radio source.
769      * @param initialPosition            initial position to start the estimation of radio
770      *                                   source position.
771      * @param initialTransmittedPowerdBm initial transmitted power to start the
772      *                                   estimation of radio source transmitted power
773      *                                   (expressed in dBm's).
774      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
775      * @param listener                   listener in charge of attending events raised by this instance.
776      * @throws IllegalArgumentException if readings are not valid, quality scores
777      *                                  is null, or length of quality scores is less than required minimum.
778      */
779     public SequentialRobustMixedRadioSourceEstimator2D(
780             final double[] qualityScores, final List<? extends ReadingLocated<Point2D>> readings,
781             final Point2D initialPosition, final Double initialTransmittedPowerdBm,
782             final double initialPathLossExponent,
783             final SequentialRobustMixedRadioSourceEstimatorListener<S, Point2D> listener) {
784         super(qualityScores, readings, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent, listener);
785         rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinReadings();
786     }
787 
788     /**
789      * Gets minimum required number of readings to estimate
790      * power, position and path-loss exponent.
791      * This value depends on the number of parameters to
792      * be estimated, but for position only, this is 3
793      * readings.
794      *
795      * @return minimum required number of readings.
796      */
797     @Override
798     public int getMinReadings() {
799         var minReadings = Point2D.POINT2D_INHOMOGENEOUS_COORDINATES_LENGTH;
800         if (isTransmittedPowerEstimationEnabled()) {
801             minReadings++;
802         }
803         if (isPathLossEstimationEnabled()) {
804             minReadings++;
805         }
806         return ++minReadings;
807     }
808 
809     /**
810      * Gets number of dimensions of position points.
811      *
812      * @return always returns 2 dimensions.
813      */
814     @Override
815     public int getNumberOfDimensions() {
816         return Point2D.POINT2D_INHOMOGENEOUS_COORDINATES_LENGTH;
817     }
818 
819     /**
820      * Gets estimated located radio source with estimated transmitted power.
821      *
822      * @return estimated located radio source with estimated transmitted power or null.
823      */
824     @Override
825     @SuppressWarnings("unchecked")
826     public RadioSourceLocated<Point2D> getEstimatedRadioSource() {
827         final var readings = getReadings();
828         if (readings == null || readings.isEmpty()) {
829             return null;
830         }
831 
832         final S source;
833         final var reading = readings.get(0);
834         if (reading instanceof RangingReadingLocated) {
835             source = ((RangingReadingLocated<S, Point2D>) reading).getSource();
836         } else if (reading instanceof RssiReadingLocated) {
837             source = ((RssiReadingLocated<S, Point2D>) reading).getSource();
838         } else if (reading instanceof RangingAndRssiReadingLocated) {
839             source = ((RangingAndRssiReadingLocated<S, Point2D>) reading).getSource();
840         } else {
841             return null;
842         }
843 
844         final var estimatedPosition = getEstimatedPosition();
845         if (estimatedPosition == null) {
846             return null;
847         }
848 
849         final var estimatedPositionCovariance = getEstimatedPositionCovariance();
850 
851         final var transmittedPowerdBm = getEstimatedTransmittedPowerdBm();
852 
853         final var transmittedPowerVariance = getEstimatedTransmittedPowerVariance();
854         final var transmittedPowerStandardDeviation = transmittedPowerVariance != null
855                 ? Math.sqrt(transmittedPowerVariance) : null;
856 
857         final var pathlossExponentVariance = getEstimatedPathLossExponentVariance();
858         final var pathlossExponentStandardDeviation = pathlossExponentVariance != null
859                 ? Math.sqrt(pathlossExponentVariance) : null;
860 
861         if (source instanceof WifiAccessPoint accessPoint) {
862             if (transmittedPowerdBm != null) {
863                 return new WifiAccessPointWithPowerAndLocated2D(accessPoint.getBssid(), source.getFrequency(),
864                         accessPoint.getSsid(), transmittedPowerdBm, transmittedPowerStandardDeviation,
865                         getEstimatedPathLossExponent(), pathlossExponentStandardDeviation, estimatedPosition,
866                         estimatedPositionCovariance);
867             } else {
868                 return new WifiAccessPointLocated2D(accessPoint.getBssid(),
869                         source.getFrequency(), accessPoint.getSsid(),
870                         estimatedPosition, estimatedPositionCovariance);
871             }
872         } else if (source instanceof Beacon beacon) {
873             return new BeaconWithPowerAndLocated2D(beacon.getIdentifiers(), beacon.getTransmittedPower(),
874                     beacon.getFrequency(), beacon.getBluetoothAddress(), beacon.getBeaconTypeCode(),
875                     beacon.getManufacturer(), beacon.getServiceUuid(), beacon.getBluetoothName(),
876                     getEstimatedPathLossExponent(), transmittedPowerStandardDeviation,
877                     pathlossExponentStandardDeviation, estimatedPosition, estimatedPositionCovariance);
878         } else {
879             return null;
880         }
881     }
882 
883     /**
884      * Builds ranging estimator.
885      */
886     @Override
887     protected void buildRangingEstimatorIfNeeded() {
888         if (rangingEstimator == null || rangingEstimator.getMethod() != rangingRobustMethod) {
889             rangingEstimator = RobustRangingRadioSourceEstimator2D.create(rangingRobustMethod);
890         }
891     }
892 
893     /**
894      * build RSSI estimator.
895      *
896      * @throws LockedException if estimator is locked.
897      */
898     @Override
899     protected void buildRssiEstimatorIfNeeded() throws LockedException {
900         if (rssiEstimator == null || rssiEstimator.getMethod() != rssiRobustMethod) {
901             rssiEstimator = RobustRssiRadioSourceEstimator2D.create(rssiRobustMethod);
902 
903             // rssi estimator will never need position estimator, but to
904             // ensure it is ready we need to provide an initial position
905             rssiEstimator.setPositionEstimationEnabled(false);
906             rssiEstimator.setInitialPosition(Point2D.create());
907         }
908     }
909 }