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 }