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