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.algebra.AlgebraException;
19 import com.irurueta.algebra.Matrix;
20 import com.irurueta.geometry.Point;
21 import com.irurueta.navigation.LockedException;
22 import com.irurueta.navigation.NotReadyException;
23 import com.irurueta.navigation.indoor.RadioSource;
24 import com.irurueta.navigation.indoor.RadioSourceLocated;
25 import com.irurueta.navigation.indoor.RangingAndRssiReadingLocated;
26 import com.irurueta.navigation.indoor.RangingReadingLocated;
27 import com.irurueta.navigation.indoor.RssiReadingLocated;
28 import com.irurueta.navigation.indoor.Utils;
29 import com.irurueta.numerical.robust.InliersData;
30 import com.irurueta.numerical.robust.RobustEstimatorException;
31 import com.irurueta.numerical.robust.RobustEstimatorMethod;
32
33 import java.util.ArrayList;
34 import java.util.List;
35
36 /**
37 * This is an abstract class to robustly estimate position, transmitted power and path-loss
38 * exponent of a radio source (e.g. Wi-Fi access point or bluetooth beacon), by discarding
39 * outliers and assuming that the ranging data is available to obtain position with
40 * greater accuracy and that the radio source emits isotropically following the
41 * expression below:
42 * Pr = Pt*Gt*Gr*lambda^2 / (4*pi*d)^2,
43 * where Pr is the received power (expressed in mW),
44 * Gt is the Gain of the transmission antenna
45 * Gr is the Gain of the receiver antenna
46 * d is the distance between emitter and receiver
47 * and lambda is the wavelength and is equal to: lambda = c / f,
48 * where c is the speed of light
49 * and f is the carrier frequency of the radio signal.
50 * <p>
51 * Implementations of this class sequentially estimate position and then remaining
52 * parameters. First ranging data is used to robustly estimate position and then
53 * remaining parameters are robustly estimated using former estimated position as
54 * an initial guess.
55 * <p>
56 * Because usually information about the antenna of the radio source cannot be
57 * retrieved (because many measurements are made on unknown devices where
58 * physical access is not possible), this implementation will estimate the
59 * equivalent transmitted power as: Pte = Pt * Gt * Gr.
60 * If Readings contain RSSI standard deviations, those values will be used,
61 * otherwise it will be assumed an RSSI standard deviation of 1 dB.
62 * <p>
63 * Implementations of this class might produce more stable positions of estimated
64 * radio sources than implementations of RobustRangingAndRssiRadioSourceEstimator.
65 *
66 * @param <S> a {@link RadioSource} type.
67 * @param <P> a {@link Point} type.
68 */
69 @SuppressWarnings("DuplicatedCode")
70 public abstract class SequentialRobustRangingAndRssiRadioSourceEstimator<S extends RadioSource, P extends Point<P>> {
71
72 /**
73 * Default robust estimator method for robust position estimation using ranging
74 * data when no robust method is provided.
75 */
76 public static final RobustEstimatorMethod DEFAULT_PANGING_ROBUST_METHOD = RobustEstimatorMethod.PROMEDS;
77
78 /**
79 * Default robust estimator method for path-loss exponent and transmitted power
80 * estimation using RSSI data when no robust method is provided.
81 */
82 public static final RobustEstimatorMethod DEFAULT_RSSI_ROBUST_METHOD = RobustEstimatorMethod.PROMEDS;
83
84 /**
85 * Indicates that result is refined by default using all found inliers.
86 */
87 public static final boolean DEFAULT_REFINE_RESULT = true;
88
89 /**
90 * Indicates that covariance is kept by default after refining result.
91 */
92 public static final boolean DEFAULT_KEEP_COVARIANCE = true;
93
94 /**
95 * Default amount of progress variation before notifying a change in estimation progress.
96 * By default, this is set to 5%.
97 */
98 public static final float DEFAULT_PROGRESS_DELTA = 0.05f;
99
100 /**
101 * Minimum allowed value for progress delta.
102 */
103 public static final float MIN_PROGRESS_DELTA = 0.0f;
104
105 /**
106 * Maximum allowed value for progress delta.
107 */
108 public static final float MAX_PROGRESS_DELTA = 1.0f;
109
110 /**
111 * Constant defining default confidence of the estimated result, which is
112 * 99%. This means that with a probability of 99% estimation will be
113 * accurate because chosen sub-samples will be inliers.
114 */
115 public static final double DEFAULT_CONFIDENCE = 0.99;
116
117 /**
118 * Default maximum allowed number of iterations.
119 */
120 public static final int DEFAULT_MAX_ITERATIONS = 5000;
121
122 /**
123 * Minimum allowed confidence value.
124 */
125 public static final double MIN_CONFIDENCE = 0.0;
126
127 /**
128 * Maximum allowed confidence value.
129 */
130 public static final double MAX_CONFIDENCE = 1.0;
131
132 /**
133 * Minimum allowed number of iterations.
134 */
135 public static final int MIN_ITERATIONS = 1;
136
137 /**
138 * Indicates that by default position covariances of readings must be taken into account to increase
139 * the amount of standard deviation of each ranging measure by the amount of position standard deviation
140 * assuming that both measures are statistically independent.
141 */
142 public static final boolean DEFAULT_USE_READING_POSITION_COVARIANCES = true;
143
144 /**
145 * Internal robust estimator for position estimation.
146 */
147 protected RobustRangingRadioSourceEstimator<S, P> rangingEstimator;
148
149 /**
150 * Internal robust estimator for path-loss exponent and transmitted power
151 * estimation.
152 */
153 protected RobustRssiRadioSourceEstimator<S, P> rssiEstimator;
154
155 /**
156 * Robust method used for robust position estimation using ranging data.
157 */
158 protected RobustEstimatorMethod rangingRobustMethod = DEFAULT_PANGING_ROBUST_METHOD;
159
160 /**
161 * Robust method used for path-loss exponent and transmitted power estimation
162 * using RSSI data.
163 */
164 protected RobustEstimatorMethod rssiRobustMethod = DEFAULT_RSSI_ROBUST_METHOD;
165
166 /**
167 * Size of subsets to be checked during ranging robust estimation.
168 */
169 protected int rangingPreliminarySubsetSize;
170
171 /**
172 * Size of subsets to be checked during RSSI robust estimation.
173 */
174 protected int rssiPreliminarySubsetSize;
175
176 /**
177 * Threshold to determine when samples are inliers or not used during robust
178 * position estimation.
179 * If not defined, default threshold will be used.
180 */
181 protected Double rangingThreshold;
182
183 /**
184 * Threshold to determine when samples are inliers or not used during robust
185 * path-loss exponent and transmitted power estimation.
186 */
187 protected Double rssiThreshold;
188
189 /**
190 * Signal readings belonging to the same radio source to be estimated.
191 */
192 private List<? extends RangingAndRssiReadingLocated<S, P>> readings;
193
194 /**
195 * Quality scores corresponding to each provided sample.
196 * The larger the score value the better the quality of the sample.
197 */
198 private double[] qualityScores;
199
200 /**
201 * Listener to be notified of events such as when estimation starts, ends or its
202 * progress significantly changes.
203 */
204 private SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener;
205
206 /**
207 * Estimated position.
208 */
209 private P estimatedPosition;
210
211 /**
212 * Indicates if this instance is locked because estimation is being executed.
213 */
214 private boolean locked;
215
216 /**
217 * Amount of progress variation before notifying a progress change during estimation.
218 */
219 private float progressDelta = DEFAULT_PROGRESS_DELTA;
220
221 /**
222 * Amount of confidence expressed as a value between 0.0 and 1.0 (which is equivalent
223 * to 100%) for robust position estimation. The amount of confidence indicates the
224 * probability that the estimated result is correct. Usually this value will be
225 * close to 1.0, but not exactly 1.0.
226 */
227 private double rangingConfidence = DEFAULT_CONFIDENCE;
228
229 /**
230 * Amount of confidence expressed as a value between 0.0 and 1.0 (which is equivalent
231 * to 100%) for robust path-loss exponent and transmitted power estimation. The amount
232 * of confidence indicates the probability that the estimated result is correct.
233 * Usually this value will be close to 1.0, but not exactly 1.0.
234 */
235 private double rssiConfidence = DEFAULT_CONFIDENCE;
236
237 /**
238 * Maximum allowed number of iterations for robust position estimation. When the
239 * maximum number of iterations is exceeded, an approximate result might be
240 * available for retrieval.
241 */
242 private int rangingMaxIterations = DEFAULT_MAX_ITERATIONS;
243
244 /**
245 * Maximum allowed number of iterations for robust path-loss exponent and transmitted
246 * power estimation. When the maximum number of iterations is exceeded, an
247 * approximate result might be available for retrieval.
248 */
249 private int rssiMaxIterations = DEFAULT_MAX_ITERATIONS;
250
251 /**
252 * Indicates whether result must be refined using found inliers.
253 * If true, inliers will be computed and kept in any implementation regardless of the
254 * settings.
255 */
256 private boolean refineResult = DEFAULT_REFINE_RESULT;
257
258 /**
259 * Indicates whether covariance must be kept after refining result.
260 * This setting is only taken into account if result is refined.
261 */
262 private boolean keepCovariance = DEFAULT_KEEP_COVARIANCE;
263
264 /**
265 * Covariance of estimated position, power and/or path-loss exponent.
266 * This is only available when result has been refined and covariance is kept.
267 */
268 private Matrix covariance;
269
270 /**
271 * Covariance of estimated position.
272 * Size of this matrix will depend on the number of dimensions
273 * of estimated position (either 2 or 3).
274 * This value will only be available when position estimation is enabled.
275 */
276 private Matrix estimatedPositionCovariance;
277
278 /**
279 * Initially transmitted power to start the estimation of radio source
280 * transmitted power.
281 * If not defined, average value of received power readings will be used.
282 */
283 private Double initialTransmittedPowerdBm;
284
285 /**
286 * Initial position to start the estimation of radio source position.
287 * If not defined, centroid of provided located readings will be used.
288 */
289 private P initialPosition;
290
291 /**
292 * Initial exponent typically used on free space for path loss propagation in
293 * terms of distance.
294 * On different environments path loss exponent might have different values:
295 * - Free space: 2.0
296 * - Urban Area: 2.7 to 3.5
297 * - Suburban Area: 3 to 5
298 * - Indoor (line-of-sight): 1.6 to 1.8
299 * <p>
300 * If path loss exponent estimation is enabled, estimation will start at this
301 * value and will converge to the most appropriate value.
302 * If path loss exponent estimation is disabled, this value will be assumed
303 * to be exact and the estimated path loss exponent will be equal to this
304 * value.
305 */
306 private double initialPathLossExponent = RangingAndRssiRadioSourceEstimator.DEFAULT_PATH_LOSS_EXPONENT;
307
308 /**
309 * Indicates whether transmitted power estimation is enabled or not.
310 */
311 private boolean transmittedPowerEstimationEnabled =
312 RangingAndRssiRadioSourceEstimator.DEFAULT_TRANSMITTED_POWER_ESTIMATION_ENABLED;
313
314 /**
315 * Indicates whether path loss estimation is enabled or not.
316 */
317 private boolean pathLossEstimationEnabled =
318 RangingAndRssiRadioSourceEstimator.DEFAULT_PATHLOSS_ESTIMATION_ENABLED;
319
320 /**
321 * Estimated transmitted power expressed in dBm's.
322 */
323 private double estimatedTransmittedPowerdBm;
324
325 /**
326 * Estimated exponent typically used on free space for path loss propagation in
327 * terms of distance.
328 * On different environments path loss exponent might have different values:
329 * - Free space: 2.0
330 * - Urban Area: 2.7 to 3.5
331 * - Suburban Area: 3 to 5
332 * - Indoor (line-of-sight): 1.6 to 1.8
333 * If path loss exponent estimation is not enabled, this value will always be equal to
334 * {@link RssiRadioSourceEstimator#DEFAULT_PATH_LOSS_EXPONENT}
335 */
336 private double estimatedPathLossExponent = RangingAndRssiRadioSourceEstimator.DEFAULT_PATH_LOSS_EXPONENT;
337
338 /**
339 * Variance of estimated transmitted power.
340 * This value will only be available when transmitted power
341 * estimation is enabled.
342 */
343 private Double estimatedTransmittedPowerVariance;
344
345 /**
346 * Variance of estimated path loss exponent.
347 * This value will only be available when path-loss
348 * exponent estimation is enabled.
349 */
350 private Double estimatedPathLossExponentVariance;
351
352 /**
353 * Data related to inliers found after estimation.
354 */
355 private InliersData inliersData;
356
357 /**
358 * Indicates whether position covariances of readings must be taken into account to increase
359 * the amount of standard deviation of each ranging measure by the amount of position standard deviation
360 * assuming that both measures are statistically independent.
361 */
362 private boolean useReadingPositionCovariances = DEFAULT_USE_READING_POSITION_COVARIANCES;
363
364 /**
365 * Indicates whether an homogeneous ranging linear solver is used to estimate preliminary positions.
366 */
367 private boolean useHomogeneousRangingLinearSolver =
368 RangingRadioSourceEstimator.DEFAULT_USE_HOMOGENEOUS_LINEAR_SOLVER;
369
370 /**
371 * Constructor.
372 */
373 protected SequentialRobustRangingAndRssiRadioSourceEstimator() {
374 }
375
376 /**
377 * Constructor.
378 * Sets signal readings belonging to the same radio source.
379 *
380 * @param readings signal readings belonging to the same radio source.
381 * @throws IllegalArgumentException if readings are not valid.
382 */
383 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
384 final List<? extends RangingAndRssiReadingLocated<S, P>> readings) {
385 internalSetReadings(readings);
386 }
387
388 /**
389 * Constructor.
390 *
391 * @param listener listener in charge of attending events raised by this instance.
392 */
393 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
394 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
395 this.listener = listener;
396 }
397
398 /**
399 * Constructor.
400 * Sets signal readings belonging to the same radio source.
401 *
402 * @param readings signal readings belonging to the same radio source.
403 * @param listener listener in charge of attending events raised by this instance.
404 * @throws IllegalArgumentException if readings are not valid.
405 */
406 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
407 final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
408 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
409 this(readings);
410 this.listener = listener;
411 }
412
413 /**
414 * Constructor.
415 * Sets signal readings belonging to the same radio source.
416 *
417 * @param readings signal readings belonging to the same radio source.
418 * @param initialPosition initial position to start the estimation of radio
419 * source position.
420 * @throws IllegalArgumentException if readings are not valid.
421 */
422 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
423 final List<? extends RangingAndRssiReadingLocated<S, P>> readings, final P initialPosition) {
424 this(readings);
425 this.initialPosition = initialPosition;
426 }
427
428 /**
429 * Constructor.
430 *
431 * @param initialPosition initial position to start the estimation of radio
432 * source position.
433 */
434 protected SequentialRobustRangingAndRssiRadioSourceEstimator(final P initialPosition) {
435 this.initialPosition = initialPosition;
436 }
437
438 /**
439 * Constructor.
440 *
441 * @param initialPosition initial position to start the estimation of radio
442 * source position.
443 * @param listener listener in charge of attending events raised by this instance.
444 */
445 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
446 final P initialPosition, final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
447 this(listener);
448 this.initialPosition = initialPosition;
449 }
450
451 /**
452 * Constructor.
453 * Sets signal readings belonging to the same radio source.
454 *
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 * @param listener listener in charge of attending events raised by this instance.
459 * @throws IllegalArgumentException if readings are not valid.
460 */
461 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
462 final List<? extends RangingAndRssiReadingLocated<S, P>> readings, final P initialPosition,
463 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
464 this(readings, listener);
465 this.initialPosition = initialPosition;
466 }
467
468 /**
469 * Constructor.
470 *
471 * @param initialTransmittedPowerdBm initial transmitted power to start the
472 * estimation of radio source transmitted power
473 * (expressed in dBm's).
474 */
475 protected SequentialRobustRangingAndRssiRadioSourceEstimator(final Double initialTransmittedPowerdBm) {
476 this.initialTransmittedPowerdBm = initialTransmittedPowerdBm;
477 }
478
479 /**
480 * Constructor.
481 * Sets signal readings belonging to the same radio source.
482 *
483 * @param readings signal readings belonging to the same radio source.
484 * @param initialTransmittedPowerdBm initial transmitted power to start the
485 * estimation of radio source transmitted power
486 * (expressed in dBm's).
487 * @throws IllegalArgumentException if readings are not valid.
488 */
489 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
490 final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
491 final Double initialTransmittedPowerdBm) {
492 this(readings);
493 this.initialTransmittedPowerdBm = initialTransmittedPowerdBm;
494 }
495
496 /**
497 * Constructor.
498 *
499 * @param initialTransmittedPowerdBm initial transmitted power to start the
500 * estimation of radio source transmitted power
501 * (expressed in dBm's).
502 * @param listener listener in charge of attending events raised by this instance.
503 */
504 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
505 final Double initialTransmittedPowerdBm,
506 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
507 this(listener);
508 this.initialTransmittedPowerdBm = initialTransmittedPowerdBm;
509 }
510
511 /**
512 * Constructor.
513 * Sets signal readings belonging to the same radio source.
514 *
515 * @param readings signal readings belonging to the same radio source.
516 * @param initialTransmittedPowerdBm initial transmitted power to start the
517 * estimation of radio source transmitted power
518 * (expressed in dBm's).
519 * @param listener listener in charge of attending events raised by this instance.
520 * @throws IllegalArgumentException if readings are not valid.
521 */
522 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
523 final List<? extends RangingAndRssiReadingLocated<S, P>> readings, final Double initialTransmittedPowerdBm,
524 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
525 this(readings, listener);
526 this.initialTransmittedPowerdBm = initialTransmittedPowerdBm;
527 }
528
529 /**
530 * Constructor.
531 * Sets signal readings belonging to the same radio source.
532 *
533 * @param readings signal readings belonging to the same radio source.
534 * @param initialPosition initial position to start the estimation of radio
535 * source position.
536 * @param initialTransmittedPowerdBm initial transmitted power to start the
537 * estimation of radio source transmitted power
538 * (expressed in dBm's).
539 * @throws IllegalArgumentException if readings are not valid.
540 */
541 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
542 final List<? extends RangingAndRssiReadingLocated<S, P>> readings, final P initialPosition,
543 final Double initialTransmittedPowerdBm) {
544 this(readings);
545 this.initialPosition = initialPosition;
546 this.initialTransmittedPowerdBm = initialTransmittedPowerdBm;
547 }
548
549 /**
550 * Constructor.
551 *
552 * @param initialPosition initial position to start the estimation of radio
553 * source position.
554 * @param initialTransmittedPowerdBm initial transmitted power to start the
555 * estimation of radio source transmitted power
556 * (expressed in dBm's).
557 */
558 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
559 final P initialPosition, final Double initialTransmittedPowerdBm) {
560 this.initialPosition = initialPosition;
561 this.initialTransmittedPowerdBm = initialTransmittedPowerdBm;
562 }
563
564 /**
565 * Constructor.
566 *
567 * @param initialPosition initial position to start the estimation of radio
568 * source position.
569 * @param initialTransmittedPowerdBm initial transmitted power to start the
570 * estimation of radio source transmitted power
571 * (expressed in dBm's).
572 * @param listener in charge of attending events raised by this instance.
573 */
574 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
575 final P initialPosition, final Double initialTransmittedPowerdBm,
576 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
577 this(listener);
578 this.initialPosition = initialPosition;
579 this.initialTransmittedPowerdBm = initialTransmittedPowerdBm;
580 }
581
582 /**
583 * Constructor.
584 * Sets signal readings belonging to the same radio source.
585 *
586 * @param readings signal readings belonging to the same radio source.
587 * @param initialPosition initial position to start the estimation of radio
588 * source position.
589 * @param initialTransmittedPowerdBm initial transmitted power to start the
590 * estimation of radio source transmitted power
591 * (expressed in dBm's).
592 * @param listener listener in charge of attending events raised by this instance.
593 * @throws IllegalArgumentException if readings are not valid.
594 */
595 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
596 final List<? extends RangingAndRssiReadingLocated<S, P>> readings, final P initialPosition,
597 final Double initialTransmittedPowerdBm,
598 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
599 this(readings, listener);
600 this.initialPosition = initialPosition;
601 this.initialTransmittedPowerdBm = initialTransmittedPowerdBm;
602 }
603
604 /**
605 * Constructor.
606 * Sets signal readings belonging to the same radio source.
607 *
608 * @param readings signal readings belonging to the same radio source.
609 * @param initialPosition initial position to start the estimation of radio
610 * source position.
611 * @param initialTransmittedPowerdBm initial transmitted power to start the
612 * estimation of radio source transmitted power
613 * (expressed in dBm's).
614 * @param initialPathLossExponent initial path loss exponent. A typical value is 2.0.
615 * @throws IllegalArgumentException if readings are not valid.
616 */
617 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
618 final List<? extends RangingAndRssiReadingLocated<S, P>> readings, final P initialPosition,
619 final Double initialTransmittedPowerdBm, final double initialPathLossExponent) {
620 this(readings, initialPosition, initialTransmittedPowerdBm);
621 this.initialPathLossExponent = initialPathLossExponent;
622 }
623
624 /**
625 * Constructor.
626 *
627 * @param initialPosition initial position to start the estimation of radio
628 * source position.
629 * @param initialTransmittedPowerdBm initial transmitted power to start the
630 * estimation of radio source transmitted power
631 * (expressed in dBm's).
632 * @param initialPathLossExponent initial path loss exponent. A typical value is 2.0.
633 */
634 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
635 final P initialPosition, final Double initialTransmittedPowerdBm, final double initialPathLossExponent) {
636 this(initialPosition, initialTransmittedPowerdBm);
637 this.initialPathLossExponent = initialPathLossExponent;
638 }
639
640 /**
641 * Constructor.
642 *
643 * @param initialPosition initial position to start the estimation of radio
644 * source position.
645 * @param initialTransmittedPowerdBm initial transmitted power to start the
646 * estimation of radio source transmitted power
647 * (expressed in dBm's).
648 * @param initialPathLossExponent initial path loss exponent. A typical value is 2.0.
649 * @param listener listener in charge of attending events raised by this instance.
650 */
651 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
652 final P initialPosition, final Double initialTransmittedPowerdBm, final double initialPathLossExponent,
653 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
654 this(initialPosition, initialTransmittedPowerdBm, listener);
655 this.initialPathLossExponent = initialPathLossExponent;
656 }
657
658 /**
659 * Constructors.
660 * Sets signal readings belonging to the same radio source.
661 *
662 * @param readings signal readings belonging to the same radio source.
663 * @param initialPosition initial position to start the estimation of radio
664 * source position.
665 * @param initialTransmittedPowerdBm initial transmitted power to start the
666 * estimation of radio source transmitted power
667 * (expressed in dBm's).
668 * @param initialPathLossExponent initial path loss exponent. A typical value is 2.0.
669 * @param listener listener in charge of attending events raised by this instance.
670 * @throws IllegalArgumentException if readings are not valid.
671 */
672 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
673 final List<? extends RangingAndRssiReadingLocated<S, P>> readings, final P initialPosition,
674 final Double initialTransmittedPowerdBm, final double initialPathLossExponent,
675 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
676 this(readings, initialPosition, initialTransmittedPowerdBm, listener);
677 this.initialPathLossExponent = initialPathLossExponent;
678 }
679
680 /**
681 * Constructor.
682 *
683 * @param qualityScores quality scores corresponding to each provided sample.
684 * The larger the score value the better the quality of
685 * the sample.
686 * @throws IllegalArgumentException if quality scores is null, or length of
687 * quality scores is less than required minimum.
688 */
689 protected SequentialRobustRangingAndRssiRadioSourceEstimator(final double[] qualityScores) {
690 this();
691 internalSetQualityScores(qualityScores);
692 }
693
694 /**
695 * Constructor.
696 * Sets signal readings belonging to the same radio source.
697 *
698 * @param qualityScores quality scores corresponding to each provided sample.
699 * The larger the score value the better the quality of
700 * the sample.
701 * @param readings signal readings belonging to the same radio source.
702 * @throws IllegalArgumentException if readings are not valid, quality scores is
703 * null, or length of quality scores is less than required minimum.
704 */
705 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
706 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings) {
707 this(readings);
708 internalSetQualityScores(qualityScores);
709 }
710
711 /**
712 * Constructor.
713 *
714 * @param qualityScores quality scores corresponding to each provided sample.
715 * The larger the score value the better the quality of
716 * the sample.
717 * @param listener listener in charge of attending events raised by this instance.
718 * @throws IllegalArgumentException if quality scores is null, or length
719 * of quality scores is less than required minimum.
720 */
721 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
722 final double[] qualityScores,
723 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
724 this(listener);
725 internalSetQualityScores(qualityScores);
726 }
727
728 /**
729 * Constructor.
730 * Sets signal readings belonging to the same radio source.
731 *
732 * @param qualityScores quality scores corresponding to each provided sample.
733 * The larger the score value the better the quality of
734 * the sample.
735 * @param readings signal readings belonging to the same radio source.
736 * @param listener listener in charge of attending events raised by this instance.
737 * @throws IllegalArgumentException if readings are not valid, quality scores is
738 * null, or length of quality scores is less than required minimum.
739 */
740 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
741 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
742 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
743 this(readings, listener);
744 internalSetQualityScores(qualityScores);
745 }
746
747 /**
748 * Constructor.
749 * Sets signal readings belonging to the same radio source.
750 *
751 * @param qualityScores quality scores corresponding to each provided sample.
752 * The larger the score value the better the quality of
753 * the sample.
754 * @param readings signal readings belonging to the same radio source.
755 * @param initialPosition initial position to start the estimation of radio
756 * source position.
757 * @throws IllegalArgumentException if readings are not valid, quality scores is
758 * null, or length of quality scores is less than required minimum.
759 */
760 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
761 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
762 final P initialPosition) {
763 this(readings, initialPosition);
764 internalSetQualityScores(qualityScores);
765 }
766
767 /**
768 * Constructor.
769 *
770 * @param qualityScores quality scores corresponding to each provided sample.
771 * The larger the score value the better the quality of
772 * the sample.
773 * @param initialPosition initial position to start the estimation of radio
774 * source position.
775 * @throws IllegalArgumentException if quality scores is null, or length
776 * of quality scores is less than required minimum.
777 */
778 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
779 final double[] qualityScores, final P initialPosition) {
780 this(initialPosition);
781 internalSetQualityScores(qualityScores);
782 }
783
784 /**
785 * Constructor.
786 *
787 * @param qualityScores quality scores corresponding to each provided sample.
788 * The larger the score value the better the quality of
789 * the sample.
790 * @param initialPosition initial position to start the estimation of radio
791 * source position.
792 * @param listener listener in charge of attending events raised by this instance.
793 * @throws IllegalArgumentException if quality scores is null, or length
794 * of quality scores is less than required minimum.
795 */
796 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
797 final double[] qualityScores, final P initialPosition,
798 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
799 this(initialPosition, listener);
800 internalSetQualityScores(qualityScores);
801 }
802
803 /**
804 * Constructor.
805 * Sets signal readings belonging to the same radio source.
806 *
807 * @param qualityScores quality scores corresponding to each provided sample.
808 * The larger the score value the better the quality of
809 * the sample.
810 * @param readings signal readings belonging to the same radio source.
811 * @param initialPosition initial position to start the estimation of radio
812 * source position.
813 * @param listener listener in charge of attending events raised by this instance.
814 * @throws IllegalArgumentException if readings are not valid, quality scores
815 * is null, or length of quality scores is less than required minimum.
816 */
817 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
818 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
819 final P initialPosition, final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
820 this(readings, initialPosition, listener);
821 internalSetQualityScores(qualityScores);
822 }
823
824 /**
825 * Constructor.
826 *
827 * @param qualityScores quality scores corresponding to each provided sample.
828 * The larger the score value the better the quality of
829 * the sample.
830 * @param initialTransmittedPowerdBm initial transmitted power to start the
831 * estimation of radio source transmitted power
832 * (expressed in dBm's).
833 * @throws IllegalArgumentException if quality scores is null, or length
834 * of quality scores is less than required minimum.
835 */
836 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
837 final double[] qualityScores, final Double initialTransmittedPowerdBm) {
838 this(initialTransmittedPowerdBm);
839 internalSetQualityScores(qualityScores);
840 }
841
842 /**
843 * Constructor.
844 * Sets signal readings belonging to the same radio source.
845 *
846 * @param qualityScores quality scores corresponding to each provided sample.
847 * The larger the score value the better the quality of
848 * the sample.
849 * @param readings signal readings belonging to the same radio source.
850 * @param initialTransmittedPowerdBm initial transmitted power to start the
851 * estimation of radio source transmitted power
852 * (expressed in dBm's).
853 * @throws IllegalArgumentException if readings are not valid, quality scores
854 * is null, or length of quality scores is less than required minimum.
855 */
856 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
857 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
858 final Double initialTransmittedPowerdBm) {
859 this(readings, initialTransmittedPowerdBm);
860 internalSetQualityScores(qualityScores);
861 }
862
863 /**
864 * Constructor.
865 *
866 * @param qualityScores quality scores corresponding to each provided sample.
867 * The larger the score value the better the quality of
868 * the sample.
869 * @param initialTransmittedPowerdBm initial transmitted power to start the
870 * estimation of radio source transmitted power
871 * (expressed in dBm's).
872 * @param listener listener in charge of attending events raised by this instance.
873 * @throws IllegalArgumentException if quality scores is null, or length
874 * of quality scores is less than required minimum.
875 */
876 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
877 final double[] qualityScores, final Double initialTransmittedPowerdBm,
878 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
879 this(initialTransmittedPowerdBm, listener);
880 internalSetQualityScores(qualityScores);
881 }
882
883 /**
884 * Constructor.
885 * Sets signal readings belonging to the same radio source.
886 *
887 * @param qualityScores quality scores corresponding to each provided
888 * sample. The larger the score value the better
889 * the quality of the sample.
890 * @param readings signal readings belonging to the same radio source.
891 * @param initialTransmittedPowerdBm initial transmitted power to start the
892 * estimation of radio source transmitted power
893 * (expressed in dBm's).
894 * @param listener listener in charge of attending events raised by this instance.
895 * @throws IllegalArgumentException if readings are not valid, quality scores
896 * is null, or length of quality scores is less than required minimum.
897 */
898 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
899 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
900 final Double initialTransmittedPowerdBm,
901 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
902 this(readings, initialTransmittedPowerdBm, listener);
903 internalSetQualityScores(qualityScores);
904 }
905
906 /**
907 * Constructor.
908 * Sets signal readings belonging to the same radio source.
909 *
910 * @param qualityScores quality scores corresponding to each provided
911 * sample. The larger the score value the better
912 * the quality of the sample.
913 * @param readings signal readings belonging to the same radio source.
914 * @param initialPosition initial position to start the estimation of radio
915 * source position.
916 * @param initialTransmittedPowerdBm initial transmitted power to start the
917 * estimation of radio source transmitted power
918 * (expressed in dBm's).
919 * @throws IllegalArgumentException if readings are not valid, quality scores
920 * is null, or length of quality scores is less than required minimum.
921 */
922 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
923 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
924 final P initialPosition, final Double initialTransmittedPowerdBm) {
925 this(readings, initialPosition, initialTransmittedPowerdBm);
926 internalSetQualityScores(qualityScores);
927 }
928
929 /**
930 * Constructor.
931 *
932 * @param qualityScores quality scores corresponding to each provided
933 * sample. The larger the score value the better
934 * the quality of the sample.
935 * @param initialPosition initial position to start the estimation of radio
936 * source position.
937 * @param initialTransmittedPowerdBm initial transmitted power to start the
938 * estimation of radio source transmitted power
939 * (expressed in dBm's).
940 * @throws IllegalArgumentException if quality scores is null, or length
941 * of quality scores is less than required minimum.
942 */
943 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
944 final double[] qualityScores, final P initialPosition, final Double initialTransmittedPowerdBm) {
945 this(initialPosition, initialTransmittedPowerdBm);
946 internalSetQualityScores(qualityScores);
947 }
948
949 /**
950 * Constructor.
951 *
952 * @param qualityScores quality scores corresponding to each provided
953 * sample. The larger the score value the better
954 * the quality of the sample.
955 * @param initialPosition initial position to start the estimation of radio
956 * source position.
957 * @param initialTransmittedPowerdBm initial transmitted power to start the
958 * estimation of radio source transmitted power
959 * (expressed in dBm's).
960 * @param listener in charge of attending events raised by this instance.
961 * @throws IllegalArgumentException if quality scores is null, or length
962 * of quality scores is less than required minimum.
963 */
964 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
965 final double[] qualityScores, final P initialPosition, final Double initialTransmittedPowerdBm,
966 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
967 this(initialPosition, initialTransmittedPowerdBm, listener);
968 internalSetQualityScores(qualityScores);
969 }
970
971 /**
972 * Constructor.
973 * Sets signal readings belonging to the same radio source.
974 *
975 * @param qualityScores quality scores corresponding to each provided
976 * sample. The larger the score value the better
977 * the quality of the sample.
978 * @param readings signal readings belonging to the same radio source.
979 * @param initialPosition initial position to start the estimation of radio
980 * source position.
981 * @param initialTransmittedPowerdBm initial transmitted power to start the
982 * estimation of radio source transmitted power
983 * (expressed in dBm's).
984 * @param listener listener in charge of attending events raised by this instance.
985 * @throws IllegalArgumentException if readings are not valid, quality scores
986 * is null, or length of quality scores is less than required minimum.
987 */
988 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
989 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
990 final P initialPosition, final Double initialTransmittedPowerdBm,
991 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
992 this(readings, initialPosition, initialTransmittedPowerdBm, listener);
993 internalSetQualityScores(qualityScores);
994 }
995
996 /**
997 * Constructor.
998 * Sets signal readings belonging to the same radio source.
999 *
1000 * @param qualityScores quality scores corresponding to each provided
1001 * sample. The larger the score value the better
1002 * the quality of the sample.
1003 * @param readings signal readings belonging to the same radio source.
1004 * @param initialPosition initial position to start the estimation of radio
1005 * source position.
1006 * @param initialTransmittedPowerdBm initial transmitted power to start the
1007 * estimation of radio source transmitted power
1008 * (expressed in dBm's).
1009 * @param initialPathLossExponent initial path loss exponent. A typical value is 2.0.
1010 * @throws IllegalArgumentException if readings are not valid, quality scores
1011 * is null, or length of quality scores is less than required minimum.
1012 */
1013 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
1014 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
1015 final P initialPosition, final Double initialTransmittedPowerdBm, final double initialPathLossExponent) {
1016 this(readings, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent);
1017 internalSetQualityScores(qualityScores);
1018 }
1019
1020 /**
1021 * Constructor.
1022 *
1023 * @param qualityScores quality scores corresponding to each provided
1024 * sample. The larger the score value the better
1025 * the quality of the sample.
1026 * @param initialPosition initial position to start the estimation of radio
1027 * source position.
1028 * @param initialTransmittedPowerdBm initial transmitted power to start the
1029 * estimation of radio source transmitted power
1030 * (expressed in dBm's).
1031 * @param initialPathLossExponent initial path loss exponent. A typical value is 2.0.
1032 * @throws IllegalArgumentException if quality scores is null, or length
1033 * of quality scores is less than required minimum.
1034 */
1035 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
1036 final double[] qualityScores, final P initialPosition, final Double initialTransmittedPowerdBm,
1037 final double initialPathLossExponent) {
1038 this(initialPosition, initialTransmittedPowerdBm, initialPathLossExponent);
1039 internalSetQualityScores(qualityScores);
1040 }
1041
1042 /**
1043 * Constructor.
1044 *
1045 * @param qualityScores quality scores corresponding to each provided
1046 * sample. The larger the score value the better
1047 * the quality of the sample.
1048 * @param initialPosition initial position to start the estimation of radio
1049 * source position.
1050 * @param initialTransmittedPowerdBm initial transmitted power to start the
1051 * estimation of radio source transmitted power
1052 * (expressed in dBm's).
1053 * @param initialPathLossExponent initial path loss exponent. A typical value is 2.0.
1054 * @param listener listener in charge of attending events raised by this instance.
1055 * @throws IllegalArgumentException if quality scores is null, or length
1056 * of quality scores is less than required minimum.
1057 */
1058 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
1059 final double[] qualityScores, final P initialPosition, final Double initialTransmittedPowerdBm,
1060 final double initialPathLossExponent,
1061 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
1062 this(initialPosition, initialTransmittedPowerdBm, initialPathLossExponent, listener);
1063 internalSetQualityScores(qualityScores);
1064 }
1065
1066 /**
1067 * Constructors.
1068 * Sets signal readings belonging to the same radio source.
1069 *
1070 * @param qualityScores quality scores corresponding to each provided
1071 * sample. The larger the score value the better
1072 * the quality of the sample.
1073 * @param readings signal readings belonging to the same radio source.
1074 * @param initialPosition initial position to start the estimation of radio
1075 * source position.
1076 * @param initialTransmittedPowerdBm initial transmitted power to start the
1077 * estimation of radio source transmitted power
1078 * (expressed in dBm's).
1079 * @param initialPathLossExponent initial path loss exponent. A typical value is 2.0.
1080 * @param listener listener in charge of attending events raised by this instance.
1081 * @throws IllegalArgumentException if readings are not valid, quality scores
1082 * is null, or length of quality scores is less than required minimum.
1083 */
1084 protected SequentialRobustRangingAndRssiRadioSourceEstimator(
1085 final double[] qualityScores, final List<? extends RangingAndRssiReadingLocated<S, P>> readings,
1086 final P initialPosition, final Double initialTransmittedPowerdBm, final double initialPathLossExponent,
1087 final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener) {
1088 this(readings, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent, listener);
1089 internalSetQualityScores(qualityScores);
1090 }
1091
1092 /**
1093 * Indicates whether estimator is locked during estimation.
1094 *
1095 * @return true if estimator is locked, false otherwise.
1096 */
1097 public boolean isLocked() {
1098 return locked;
1099 }
1100
1101 /**
1102 * Returns amount of progress variation before notifying a progress change during
1103 * estimation.
1104 *
1105 * @return amount of progress variation before notifying a progress change during
1106 * estimation.
1107 */
1108 public float getProgressDelta() {
1109 return progressDelta;
1110 }
1111
1112 /**
1113 * Sets amount of progress variation before notifying a progress change during
1114 * estimation.
1115 *
1116 * @param progressDelta amount of progress variation before notifying a progress
1117 * change during estimation.
1118 * @throws IllegalArgumentException if progress delta is less than zero or greater than 1.
1119 * @throws LockedException if this estimator is locked.
1120 */
1121 public void setProgressDelta(final float progressDelta) throws LockedException {
1122 if (isLocked()) {
1123 throw new LockedException();
1124 }
1125 if (progressDelta < MIN_PROGRESS_DELTA || progressDelta > MAX_PROGRESS_DELTA) {
1126 throw new IllegalArgumentException();
1127 }
1128 this.progressDelta = progressDelta;
1129 }
1130
1131 /**
1132 * Gets robust method used for robust position estimation using ranging data.
1133 *
1134 * @return robust method used for robust position estimation.
1135 */
1136 public RobustEstimatorMethod getRangingRobustMethod() {
1137 return rangingRobustMethod;
1138 }
1139
1140 /**
1141 * Sets robust method used for robust position estimation using ranging data.
1142 *
1143 * @param rangingRobustMethod robust method used for robust position estimation.
1144 * @throws LockedException if estimator is locked.
1145 */
1146 public void setRangingRobustMethod(final RobustEstimatorMethod rangingRobustMethod) throws LockedException {
1147 if (isLocked()) {
1148 throw new LockedException();
1149 }
1150 this.rangingRobustMethod = rangingRobustMethod;
1151 }
1152
1153 /**
1154 * Gets robust method used for path-loss exponent and transmitted power estimation
1155 * using RSSI data.
1156 *
1157 * @return robust method used for path-loss exponent and transmitted power
1158 * estimation.
1159 */
1160 public RobustEstimatorMethod getRssiRobustMethod() {
1161 return rssiRobustMethod;
1162 }
1163
1164 /**
1165 * Sets robust method used for path-loss exponent and transmitted power estimation
1166 * using RSSI data.
1167 *
1168 * @param rssiRobustMethod robust method used for path-loss exponent and transmitted
1169 * power estimation.
1170 * @throws LockedException if estimator is locked.
1171 */
1172 public void setRssiRobustMethod(final RobustEstimatorMethod rssiRobustMethod) throws LockedException {
1173 if (isLocked()) {
1174 throw new LockedException();
1175 }
1176 this.rssiRobustMethod = rssiRobustMethod;
1177 }
1178
1179 /**
1180 * Gets size of subsets to be checked during ranging robust estimation.
1181 *
1182 * @return size of subsets to be checked during ranging robust estimation.
1183 */
1184 public int getRangingPreliminarySubsetSize() {
1185 return rangingPreliminarySubsetSize;
1186 }
1187
1188 /**
1189 * Sets size of subsets to be checked during ranging robust estimation.
1190 *
1191 * @param rangingPreliminarySubsetSize size of subsets to be checked during
1192 * ranging robust estimation.
1193 * @throws LockedException if estimator is locked.
1194 * @throws IllegalArgumentException if provided value is less than {@link #getMinReadings()}.
1195 */
1196 public void setRangingPreliminarySubsetSize(final int rangingPreliminarySubsetSize) throws LockedException {
1197 if (isLocked()) {
1198 throw new LockedException();
1199 }
1200 if (rangingPreliminarySubsetSize < getMinReadings()) {
1201 throw new IllegalArgumentException();
1202 }
1203
1204 this.rangingPreliminarySubsetSize = rangingPreliminarySubsetSize;
1205 }
1206
1207 /**
1208 * Gets size of subsets to be checked during RSSI robust estimation.
1209 *
1210 * @return size of subsets to be checked during RSSI robust estimation.
1211 */
1212 public int getRssiPreliminarySubsetSize() {
1213 return rssiPreliminarySubsetSize;
1214 }
1215
1216 /**
1217 * Sets size of subsets to be checked during RSSI robust estimation.
1218 *
1219 * @param rssiPreliminarySubsetSize size of subsets to be checked during
1220 * RSSI robust estimation.
1221 * @throws LockedException if estimator is locked.
1222 * @throws IllegalArgumentException if provided value is less than {@link #getMinReadings()}.
1223 */
1224 public void setRssiPreliminarySubsetSize(final int rssiPreliminarySubsetSize) throws LockedException {
1225 if (isLocked()) {
1226 throw new LockedException();
1227 }
1228 if (rssiPreliminarySubsetSize < getMinReadings()) {
1229 throw new IllegalArgumentException();
1230 }
1231
1232 this.rssiPreliminarySubsetSize = rssiPreliminarySubsetSize;
1233 }
1234
1235 /**
1236 * Gets threshold to determine when samples are inliers or not, used during robust
1237 * position estimation.
1238 * If not defined, default threshold will be used.
1239 *
1240 * @return threshold for ranging estimation or null.
1241 */
1242 public Double getRangingThreshold() {
1243 return rangingThreshold;
1244 }
1245
1246 /**
1247 * Sets threshold to determine when samples are inliers or not, used during robust
1248 * position estimation.
1249 * If not defined, default threshold will be used.
1250 *
1251 * @param rangingThreshold threshold for ranging estimation or null.
1252 * @throws LockedException if estimator is locked.
1253 */
1254 public void setRangingThreshold(final Double rangingThreshold) throws LockedException {
1255 if (isLocked()) {
1256 throw new LockedException();
1257 }
1258 this.rangingThreshold = rangingThreshold;
1259 }
1260
1261 /**
1262 * Gets threshold to determine when samples are inliers or not, used during robust
1263 * path-loss exponent and transmitted power estimation.
1264 * If not defined, default threshold will be used.
1265 *
1266 * @return threshold for RSSI estimation or null.
1267 */
1268 public Double getRssiThreshold() {
1269 return rssiThreshold;
1270 }
1271
1272 /**
1273 * Sets threshold to determine when samples are inliers or not, used during robust
1274 * path-loss exponent and transmitted power estimation.
1275 * If not defined, default threshold will be used.
1276 *
1277 * @param rssiThreshold threshold for RSSI estimation or null.
1278 * @throws LockedException if estimator is locked.
1279 */
1280 public void setRssiThreshold(final Double rssiThreshold) throws LockedException {
1281 if (isLocked()) {
1282 throw new LockedException();
1283 }
1284 this.rssiThreshold = rssiThreshold;
1285 }
1286
1287 /**
1288 * Returns amount of confidence expressed as a value between 0.0 and 1.0
1289 * (which is equivalent to 100%) for robust position estimation. The amount of
1290 * confidence indicates the probability that the estimated result is correct.
1291 * Usually this value will be close to 1.0, but not exactly 1.0.
1292 *
1293 * @return amount of confidence for robust position estimation as a value
1294 * between 0.0 and 1.0.
1295 */
1296 public double getRangingConfidence() {
1297 return rangingConfidence;
1298 }
1299
1300 /**
1301 * Sets amount of confidence expressed as a value between 0.0 and 1.0 (which is
1302 * equivalent to 100%) for robust position estimation. The amount of confidence
1303 * indicates the probability that the estimated result is correct. Usually this
1304 * value will be close to 1.0, but not exactly 1.0.
1305 *
1306 * @param rangingConfidence confidence to be set for robust position estimation
1307 * as a value between 0.0 and 1.0.
1308 * @throws IllegalArgumentException if provided value is not between 0.0 and 1.0.
1309 * @throws LockedException if estimator is locked.
1310 */
1311 public void setRangingConfidence(final double rangingConfidence) throws LockedException {
1312 if (isLocked()) {
1313 throw new LockedException();
1314 }
1315 if (rangingConfidence < MIN_CONFIDENCE || rangingConfidence > MAX_CONFIDENCE) {
1316 throw new IllegalArgumentException();
1317 }
1318 this.rangingConfidence = rangingConfidence;
1319 }
1320
1321 /**
1322 * Returns amount of confidence expressed as a value between 0.0 and 1.0
1323 * (which is equivalent to 100%) for path-loss exponent and transmitted power
1324 * estimation. The amount of confidence indicates the probability that the
1325 * estimated result is correct.
1326 * Usually this value will be close to 1.0, but not exactly 1.0.
1327 *
1328 * @return amount of confidence for robust path-loss exponent and transmitted power
1329 * estimation as a value between 0.0 and 1.0.
1330 */
1331 public double getRssiConfidence() {
1332 return rssiConfidence;
1333 }
1334
1335 /**
1336 * Sets amount of confidence expressed as a value between 0.0 and 1.0
1337 * (which is equivalent to 100%) for path-loss exponent and transmitted power
1338 * estimation. The amount of confidence indicates the probability that the
1339 * estimated result is correct. Usually this value will be close to 10.0, but
1340 * not exactly 1.0.
1341 *
1342 * @param rssiConfidence confidence to be set for robust path-loss exponent and
1343 * transmitted power estimation as a value between 0.0 and
1344 * 1.0.
1345 * @throws IllegalArgumentException if provided value is not between 0.0 and 1.0.
1346 * @throws LockedException if estimator is locked.
1347 */
1348 public void setRssiConfidence(final double rssiConfidence) throws LockedException {
1349 if (isLocked()) {
1350 throw new LockedException();
1351 }
1352 if (rssiConfidence < MIN_CONFIDENCE || rssiConfidence > MAX_CONFIDENCE) {
1353 throw new IllegalArgumentException();
1354 }
1355 this.rssiConfidence = rssiConfidence;
1356 }
1357
1358 /**
1359 * Returns maximum allowed number of iterations for robust position estimation. If
1360 * maximum allowed number of iterations is achieved without converging to a result
1361 * when calling estimate(), a RobustEstimatorException will be raised.
1362 *
1363 * @return maximum allowed number of iterations for position estimation.
1364 */
1365 public int getRangingMaxIterations() {
1366 return rangingMaxIterations;
1367 }
1368
1369 /**
1370 * Sets maximum allowed number of iterations for robust position estimation. When
1371 * the maximum number of iterations is exceeded, an approximate result might be
1372 * available for retrieval.
1373 *
1374 * @param rangingMaxIterations maximum allowed number of iterations to be set
1375 * for position estimation.
1376 * @throws IllegalArgumentException if provided value is less than 1.
1377 * @throws LockedException if this estimator is locked.
1378 */
1379 public void setRangingMaxIterations(final int rangingMaxIterations) throws LockedException {
1380 if (isLocked()) {
1381 throw new LockedException();
1382 }
1383 if (rangingMaxIterations < MIN_ITERATIONS) {
1384 throw new IllegalArgumentException();
1385 }
1386 this.rangingMaxIterations = rangingMaxIterations;
1387 }
1388
1389 /**
1390 * Returns maximum allowed number of iterations for robust path-loss exponent and
1391 * transmitted power estimation. If maximum allowed number of iterations is achieved
1392 * without converging to a result when calling estimate(), a RobustEstimatorException
1393 * will be raised.
1394 *
1395 * @return maximum allowed number of iterations for path-loss exponent and transmitted
1396 * power estimation.
1397 */
1398 public int getRssiMaxIterations() {
1399 return rssiMaxIterations;
1400 }
1401
1402 /**
1403 * Sets maximum allowed number of iterations for robust path-loss exponent and
1404 * transmitted power estimation. When the maximum number of iterations is exceeded,
1405 * an approximate result might be available for retrieval.
1406 *
1407 * @param rssiMaxIterations maximum allowed number of iterations to be set for
1408 * path-loss exponent and transmitted power estimation.
1409 * @throws IllegalArgumentException if provided value is less than 1.
1410 * @throws LockedException if this estimator is locked.
1411 */
1412 public void setRssiMaxIterations(final int rssiMaxIterations) throws LockedException {
1413 if (isLocked()) {
1414 throw new LockedException();
1415 }
1416 if (rssiMaxIterations < MIN_ITERATIONS) {
1417 throw new IllegalArgumentException();
1418 }
1419 this.rssiMaxIterations = rssiMaxIterations;
1420 }
1421
1422 /**
1423 * Indicates whether result must be refined using a non-linear solver over found inliers.
1424 *
1425 * @return true to refine result, false to simply use result found by robust estimator
1426 * without further refining.
1427 */
1428 public boolean isResultRefined() {
1429 return refineResult;
1430 }
1431
1432 /**
1433 * Specifies whether result must be refined using a non-linear solver over found inliers.
1434 *
1435 * @param refineResult true to refine result, false to simply use result found by robust
1436 * estimator without further refining.
1437 * @throws LockedException if estimator is locked.
1438 */
1439 public void setResultRefined(final boolean refineResult) throws LockedException {
1440 if (isLocked()) {
1441 throw new LockedException();
1442 }
1443 this.refineResult = refineResult;
1444 }
1445
1446 /**
1447 * Indicates whether covariance must be kept after refining result.
1448 * This setting is only taken into account if result is refined.
1449 *
1450 * @return true if covariance must be kept after refining result, false otherwise.
1451 */
1452 public boolean isCovarianceKept() {
1453 return keepCovariance;
1454 }
1455
1456 /**
1457 * Specifies whether covariance must be kept after refining result.
1458 * This setting is only taken into account if result is refined.
1459 *
1460 * @param keepCovariance true if covariance must be kept after refining result,
1461 * false otherwise.
1462 * @throws LockedException if estimator is locked.
1463 */
1464 public void setCovarianceKept(final boolean keepCovariance) throws LockedException {
1465 if (isLocked()) {
1466 throw new LockedException();
1467 }
1468 this.keepCovariance = keepCovariance;
1469 }
1470
1471 /**
1472 * Gets signal readings belonging to the same radio source.
1473 *
1474 * @return signal readings belonging to the same radio source.
1475 */
1476 public List<RangingAndRssiReadingLocated<S, P>> getReadings() {
1477 //noinspection unchecked
1478 return (List<RangingAndRssiReadingLocated<S,P>>) readings;
1479 }
1480
1481 /**
1482 * Sets signal readings belonging to the same radio source.
1483 *
1484 * @param readings signal readings belonging to the same
1485 * radio source.
1486 * @throws LockedException if estimator is locked.
1487 * @throws IllegalArgumentException if readings are not valid.
1488 */
1489 public void setReadings(final List<? extends RangingAndRssiReadingLocated<S, P>> readings) throws LockedException {
1490 if (isLocked()) {
1491 throw new LockedException();
1492 }
1493
1494 internalSetReadings(readings);
1495 }
1496
1497 /**
1498 * Gets listener in charge of attending events raised by this instance.
1499 *
1500 * @return listener in charge of attending events raised by this instance.
1501 */
1502 public SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> getListener() {
1503 return listener;
1504 }
1505
1506 /**
1507 * Sets listener in charge of attending events raised by this instance.
1508 *
1509 * @param listener listener in charge of attending events raised by this
1510 * instance.
1511 * @throws LockedException if estimator is locked.
1512 */
1513 public void setListener(final SequentialRobustRangingAndRssiRadioSourceEstimatorListener<S, P> listener)
1514 throws LockedException {
1515 if (isLocked()) {
1516 throw new LockedException();
1517 }
1518
1519 this.listener = listener;
1520 }
1521
1522 /**
1523 * Returns quality scores corresponding to each pair of
1524 * positions and distances (i.e. sample).
1525 * The larger the score value the better the quality of the sample.
1526 * This implementation always returns null.
1527 * Subclasses using quality scores must implement proper behavior.
1528 *
1529 * @return quality scores corresponding to each sample.
1530 */
1531 public double[] getQualityScores() {
1532 return qualityScores;
1533 }
1534
1535 /**
1536 * Sets quality scores corresponding to each pair of positions and
1537 * distances (i.e. sample).
1538 * The larger the score value the better the quality of the sample.
1539 * This implementation makes no action.
1540 * Subclasses using quality scores must implement proper behaviour.
1541 *
1542 * @param qualityScores quality scores corresponding to each pair of
1543 * matched points.
1544 * @throws IllegalArgumentException if provided quality scores length
1545 * is smaller than minimum required samples.
1546 * @throws LockedException if robust solver is locked because an
1547 * estimation is already in progress.
1548 */
1549 public void setQualityScores(final double[] qualityScores) throws LockedException {
1550 if (isLocked()) {
1551 throw new LockedException();
1552 }
1553 internalSetQualityScores(qualityScores);
1554 }
1555
1556 /**
1557 * Gets initial transmitted power to start the estimation of radio source
1558 * transmitted power (expressed in dBm's).
1559 * If not defined, average value of received power readings will be used.
1560 *
1561 * @return initial transmitted power to start the estimation of radio source
1562 * transmitted power.
1563 */
1564 public Double getInitialTransmittedPowerdBm() {
1565 return initialTransmittedPowerdBm;
1566 }
1567
1568 /**
1569 * Sets initial transmitted power to start the estimation of radio source
1570 * transmitted power (expressed in dBm's).
1571 * If not defined, average value of received power readings will be used.
1572 *
1573 * @param initialTransmittedPowerdBm initial transmitted power to start the
1574 * estimation of radio source transmitted
1575 * power.
1576 * @throws LockedException if estimator is locked.
1577 */
1578 public void setInitialTransmittedPowerdBm(final Double initialTransmittedPowerdBm) throws LockedException {
1579 if (isLocked()) {
1580 throw new LockedException();
1581 }
1582 this.initialTransmittedPowerdBm = initialTransmittedPowerdBm;
1583 }
1584
1585 /**
1586 * Gets initial transmitted power to start the estimation of radio source
1587 * transmitted power (expressed in mW).
1588 * If not defined, average value of received power readings will be used.
1589 *
1590 * @return initial transmitted power to start the estimation of radio source
1591 * transmitted power.
1592 */
1593 public Double getInitialTransmittedPower() {
1594 return initialTransmittedPowerdBm != null ? Utils.dBmToPower(initialTransmittedPowerdBm) : null;
1595 }
1596
1597 /**
1598 * Sets initial transmitted power to start the estimation of radio source
1599 * transmitted power (expressed in mW).
1600 * If not defined, average value of received power readings will be used.
1601 *
1602 * @param initialTransmittedPower initial transmitted power to start the
1603 * estimation of radio source transmitted power.
1604 * @throws LockedException if estimator is locked.
1605 * @throws IllegalArgumentException if provided value is negative.
1606 */
1607 public void setInitialTransmittedPower(final Double initialTransmittedPower) throws LockedException {
1608 if (isLocked()) {
1609 throw new LockedException();
1610 }
1611 if (initialTransmittedPower != null) {
1612 if (initialTransmittedPower < 0.0) {
1613 throw new IllegalArgumentException();
1614 }
1615 initialTransmittedPowerdBm = Utils.powerTodBm(initialTransmittedPower);
1616 } else {
1617 initialTransmittedPowerdBm = null;
1618 }
1619 }
1620
1621 /**
1622 * Gets initial position to start the estimation of radio source position.
1623 * If not defined, centroid of provided fingerprints will be used.
1624 *
1625 * @return initial position to start the estimation of radio source position.
1626 */
1627 public P getInitialPosition() {
1628 return initialPosition;
1629 }
1630
1631 /**
1632 * Sets initial position to start the estimation of radio source position.
1633 * If not defined, centroid of provided fingerprints will be used.
1634 *
1635 * @param initialPosition initial position to start the estimation of radio
1636 * source position.
1637 * @throws LockedException if estimator is locked.
1638 */
1639 public void setInitialPosition(final P initialPosition) throws LockedException {
1640 if (isLocked()) {
1641 throw new LockedException();
1642 }
1643 this.initialPosition = initialPosition;
1644 }
1645
1646 /**
1647 * Gets initial exponent typically used on free space for path loss propagation
1648 * in terms of distance.
1649 * On different environments path loss exponent might have different value:
1650 * - Free space: 2.0
1651 * - Urban Area: 2.7 to 3.5
1652 * - Suburban Area: 3 to 5
1653 * - Indoor (line-of-sight): 1.6 to 1.8
1654 * <p>
1655 * If path loss exponent estimation is enabled, estimation will start at this
1656 * value and will converge to the most appropriate value.
1657 * If path loss exponent estimation is disabled, this value will be assumed
1658 * to be exact and the estimated path loss exponent will be equal to this
1659 * value.
1660 *
1661 * @return initial path loss exponent.
1662 */
1663 public double getInitialPathLossExponent() {
1664 return initialPathLossExponent;
1665 }
1666
1667 /**
1668 * Sets initial exponent typically used on free space for path loss propagation
1669 * in terms of distance.
1670 * On different environments path loss exponent might have different value:
1671 * - Free space: 2.0
1672 * - Urban Area: 2.7 to 3.5
1673 * - Suburban Area: 3 to 5
1674 * - Indoor (line-of-sight): 1.6 to 1.8
1675 * <p>
1676 * If path loss exponent estimation is enabled, estimation will start at this
1677 * value and will converge to the most appropriate value.
1678 * If path loss exponent estimation is disabled, this value will be assumed
1679 * to be exact and the estimated path loss exponent will be equal to this
1680 * value.
1681 *
1682 * @param initialPathLossExponent initial path loss exponent.
1683 * @throws LockedException if estimator is locked.
1684 */
1685 public void setInitialPathLossExponent(final double initialPathLossExponent) throws LockedException {
1686 if (isLocked()) {
1687 throw new LockedException();
1688 }
1689 this.initialPathLossExponent = initialPathLossExponent;
1690 }
1691
1692 /**
1693 * Indicates whether transmitted power estimation is enabled or not.
1694 *
1695 * @return true if transmitted power estimation is enabled, false otherwise.
1696 */
1697 public boolean isTransmittedPowerEstimationEnabled() {
1698 return transmittedPowerEstimationEnabled;
1699 }
1700
1701 /**
1702 * Specifies whether transmitted power estimation is enabled or not.
1703 *
1704 * @param transmittedPowerEstimationEnabled true if transmitted power estimation is enabled,
1705 * false otherwise.
1706 * @throws LockedException if estimator is locked.
1707 */
1708 public void setTransmittedPowerEstimationEnabled(final boolean transmittedPowerEstimationEnabled)
1709 throws LockedException {
1710 if (isLocked()) {
1711 throw new LockedException();
1712 }
1713 this.transmittedPowerEstimationEnabled = transmittedPowerEstimationEnabled;
1714 }
1715
1716 /**
1717 * Indicates whether path loss estimation is enabled or not.
1718 *
1719 * @return true if path loss estimation is enabled, false otherwise.
1720 */
1721 public boolean isPathLossEstimationEnabled() {
1722 return pathLossEstimationEnabled;
1723 }
1724
1725 /**
1726 * Specifies whether path loss estimation is enabled or not.
1727 *
1728 * @param pathLossEstimationEnabled true if path loss estimation is enabled,
1729 * false otherwise.
1730 * @throws LockedException if estimator is locked.
1731 */
1732 public void setPathLossEstimationEnabled(final boolean pathLossEstimationEnabled) throws LockedException {
1733 if (isLocked()) {
1734 throw new LockedException();
1735 }
1736 this.pathLossEstimationEnabled = pathLossEstimationEnabled;
1737 }
1738
1739 /**
1740 * Indicates whether position covariances of readings must be taken into account to increase
1741 * the amount of standard deviation of each ranging measure by the amount of position standard
1742 * deviation assuming that both measures are statistically independent.
1743 *
1744 * @return true to take into account reading position covariances, false otherwise.
1745 */
1746 public boolean getUseReadingPositionCovariance() {
1747 return useReadingPositionCovariances;
1748 }
1749
1750 /**
1751 * Specifies whether position covariances of readings must be taken into account to increase
1752 * the amount of standard deviation of each ranging measure by the amount of position standard
1753 * deviation assuming that both measures are statistically independent.
1754 *
1755 * @param useReadingPositionCovariances true to take into account reading position covariances, false
1756 * otherwise.
1757 * @throws LockedException if estimator is locked.
1758 */
1759 public void setUseReadingPositionCovariances(final boolean useReadingPositionCovariances) throws LockedException {
1760 if (isLocked()) {
1761 throw new LockedException();
1762 }
1763 this.useReadingPositionCovariances = useReadingPositionCovariances;
1764 }
1765
1766 /**
1767 * Indicates whether an homogeneous ranging linear solver is used to estimate preliminary
1768 * positions.
1769 *
1770 * @return true if homogeneous ranging linear solver is used, false if an inhomogeneous ranging linear
1771 * one is used instead.
1772 */
1773 public boolean isHomogeneousRangingLinearSolverUsed() {
1774 return useHomogeneousRangingLinearSolver;
1775 }
1776
1777 /**
1778 * Specifies whether an homogeneous ranging linear solver is used to estimate preliminary
1779 * positions.
1780 *
1781 * @param useHomogeneousRangingLinearSolver true if homogeneous ranging linear solver is used, false
1782 * if an inhomogeneous ranging linear one is used instead.
1783 * @throws LockedException if estimator is locked.
1784 */
1785 public void setHomogeneousRangingLinearSolverUsed(final boolean useHomogeneousRangingLinearSolver)
1786 throws LockedException {
1787 if (isLocked()) {
1788 throw new LockedException();
1789 }
1790
1791 this.useHomogeneousRangingLinearSolver = useHomogeneousRangingLinearSolver;
1792 }
1793
1794 /**
1795 * Gets covariance for estimated position and power.
1796 * Matrix contains information in the following order:
1797 * Top-left sub-matrix contains covariance of position,
1798 * then follows transmitted power variance, and finally
1799 * the last element contains path-loss exponent variance.
1800 * This is only available when result has been refined and covariance is kept.
1801 *
1802 * @return covariance for estimated position and power.
1803 */
1804 public Matrix getCovariance() {
1805 return covariance;
1806 }
1807
1808 /**
1809 * Gets estimated position covariance.
1810 * Size of this matrix will depend on the number of dimensions
1811 * of estimated position (either 2 or 3).
1812 * This is only available when result has been refined and covariance is kept.
1813 *
1814 * @return estimated position covariance.
1815 */
1816 public Matrix getEstimatedPositionCovariance() {
1817 return estimatedPositionCovariance;
1818 }
1819
1820 /**
1821 * Gets estimated position.
1822 *
1823 * @return estimated position.
1824 */
1825 public P getEstimatedPosition() {
1826 return estimatedPosition;
1827 }
1828
1829 /**
1830 * Indicates whether readings are valid or not.
1831 * Readings are considered valid when there are enough readings.
1832 *
1833 * @param readings readings to be validated.
1834 * @return true if readings are valid, false otherwise.
1835 */
1836 public boolean areValidReadings(final List<? extends RangingAndRssiReadingLocated<S, P>> readings) {
1837 return readings != null && readings.size() >= getMinReadings();
1838 }
1839
1840 /**
1841 * Indicates whether this instance is ready to start the estimation.
1842 *
1843 * @return true if this instance is ready, false otherwise.
1844 * @throws LockedException if estimator is locked
1845 */
1846 public boolean isReady() throws LockedException {
1847 buildRangingEstimatorIfNeeded();
1848 setupRangingEstimator();
1849
1850 if (transmittedPowerEstimationEnabled || pathLossEstimationEnabled) {
1851 buildRssiEstimatorIfNeeded();
1852 setupRssiEstimator();
1853 }
1854
1855 return rangingEstimator.isReady() && ((!transmittedPowerEstimationEnabled && !pathLossEstimationEnabled)
1856 || rssiEstimator.isReady());
1857 }
1858
1859 /**
1860 * Gets estimated transmitted power variance.
1861 * This is only available when result has been refined and covariance is kept.
1862 *
1863 * @return estimated transmitted power variance.
1864 */
1865 public Double getEstimatedTransmittedPowerVariance() {
1866 return estimatedTransmittedPowerVariance;
1867 }
1868
1869 /**
1870 * Gets estimated path loss exponent variance.
1871 * This is only available when result has been refined and covariance is kept.
1872 *
1873 * @return estimated path loss exponent variance.
1874 */
1875 public Double getEstimatedPathLossExponentVariance() {
1876 return estimatedPathLossExponentVariance;
1877 }
1878
1879 /**
1880 * Gets estimated transmitted power expressed in milli watts (mW).
1881 *
1882 * @return estimated transmitted power expressed in milli watts.
1883 */
1884 public double getEstimatedTransmittedPower() {
1885 return Utils.dBmToPower(estimatedTransmittedPowerdBm);
1886 }
1887
1888 /**
1889 * Gets estimated transmitted power expressed in dBm's.
1890 *
1891 * @return estimated transmitted power expressed in dBm's.
1892 */
1893 public double getEstimatedTransmittedPowerdBm() {
1894 return estimatedTransmittedPowerdBm;
1895 }
1896
1897 /**
1898 * Gets estimated exponent typically used on free space for path loss propagation in
1899 * terms of distance.
1900 * On different environments path loss exponent might have different values:
1901 * - Free space: 2.0
1902 * - Urban Area: 2.7 to 3.5
1903 * - Suburban Area: 3 to 5
1904 * - Indoor (line-of-sight): 1.6 to 1.8
1905 * If path loss exponent estimation is not enabled, this value will always be equal to
1906 * {@link RssiRadioSourceEstimator#DEFAULT_PATH_LOSS_EXPONENT}
1907 *
1908 * @return estimated path loss exponent.
1909 */
1910 public double getEstimatedPathLossExponent() {
1911 return estimatedPathLossExponent;
1912 }
1913
1914 /**
1915 * Robustly estimates position, transmitted power and path-loss exponent for a
1916 * radio source.
1917 *
1918 * @throws LockedException if instance is busy during estimation.
1919 * @throws NotReadyException if estimator is not ready.
1920 * @throws RobustEstimatorException if estimation fails for any reason
1921 * (i.e. numerical instability, no solution available, etc).
1922 */
1923 public void estimate() throws LockedException, NotReadyException, RobustEstimatorException {
1924 if (isLocked()) {
1925 throw new LockedException();
1926 }
1927 try {
1928 locked = true;
1929
1930 // when checking for readiness, inner estimators are created and setup
1931 if (!isReady()) {
1932 throw new NotReadyException();
1933 }
1934
1935
1936 if (listener != null) {
1937 listener.onEstimateStart(this);
1938 }
1939
1940 // estimate position
1941 rangingEstimator.setPreliminarySubsetSize(rangingPreliminarySubsetSize);
1942
1943 rangingEstimator.estimate();
1944
1945 estimatedPosition = rangingEstimator.getEstimatedPosition();
1946 estimatedPositionCovariance = rangingEstimator.getEstimatedPositionCovariance();
1947 inliersData = rangingEstimator.getInliersData();
1948
1949 // estimate transmitted power and/or path-loss if enabled
1950 if (transmittedPowerEstimationEnabled || pathLossEstimationEnabled) {
1951 rssiEstimator.setPositionEstimationEnabled(false);
1952 rssiEstimator.setInitialPosition(estimatedPosition);
1953 rssiEstimator.setPreliminarySubsetSize(rssiPreliminarySubsetSize);
1954
1955 rssiEstimator.estimate();
1956
1957 if (transmittedPowerEstimationEnabled) {
1958 // transmitted power estimation enabled
1959 estimatedTransmittedPowerdBm = rssiEstimator.getEstimatedTransmittedPowerdBm();
1960 estimatedTransmittedPowerVariance = rssiEstimator.getEstimatedTransmittedPowerVariance();
1961 } else {
1962 // transmitted power estimation disabled
1963 if (initialTransmittedPowerdBm != null) {
1964 estimatedTransmittedPowerdBm = initialTransmittedPowerdBm;
1965 }
1966 estimatedTransmittedPowerVariance = null;
1967 }
1968
1969 if (pathLossEstimationEnabled) {
1970 // path-loss exponent estimation enabled
1971 estimatedPathLossExponent = rssiEstimator.getEstimatedPathLossExponent();
1972 estimatedPathLossExponentVariance = rssiEstimator.getEstimatedPathLossExponentVariance();
1973 } else {
1974 // path-loss exponent estimation disabled
1975 estimatedPathLossExponent = initialPathLossExponent;
1976 estimatedPathLossExponentVariance = null;
1977 }
1978
1979 // build covariance matrix
1980 final var rssiCov = rssiEstimator.getCovariance();
1981 if (estimatedPositionCovariance != null && rssiCov != null) {
1982 final var dims = getNumberOfDimensions();
1983 var n = dims;
1984 if (transmittedPowerEstimationEnabled) {
1985 n++;
1986 }
1987 if (pathLossEstimationEnabled) {
1988 n++;
1989 }
1990
1991 final var dimsMinus1 = dims - 1;
1992 final var nMinus1 = n - 1;
1993 covariance = new Matrix(n, n);
1994 covariance.setSubmatrix(0, 0, dimsMinus1, dimsMinus1,
1995 estimatedPositionCovariance);
1996 covariance.setSubmatrix(dims, dims, nMinus1, nMinus1, rssiCov);
1997 } else {
1998 covariance = null;
1999 }
2000 } else {
2001 covariance = estimatedPositionCovariance;
2002 if (initialTransmittedPowerdBm != null) {
2003 estimatedTransmittedPowerdBm = initialTransmittedPowerdBm;
2004 }
2005 estimatedTransmittedPowerVariance = null;
2006
2007 estimatedPathLossExponent = initialPathLossExponent;
2008 estimatedPathLossExponentVariance = null;
2009 }
2010
2011 if (listener != null) {
2012 listener.onEstimateEnd(this);
2013 }
2014 } catch (final AlgebraException e) {
2015 throw new RobustEstimatorException(e);
2016 } finally {
2017 locked = false;
2018 }
2019 }
2020
2021 /**
2022 * Gets data related to inliers found after estimation.
2023 *
2024 * @return data related to inliers found after estimation.
2025 */
2026 public InliersData getInliersData() {
2027 return inliersData;
2028 }
2029
2030 /**
2031 * Gets minimum required number of readings to estimate
2032 * power, position and path-loss exponent.
2033 * This value depends on the number of parameters to
2034 * be estimated, but for position only, this is 3
2035 * readings for 2D, and 4 readings for 3D.
2036 *
2037 * @return minimum required number of readings.
2038 */
2039 public abstract int getMinReadings();
2040
2041 /**
2042 * Gets number of dimensions of position points.
2043 *
2044 * @return number of dimensions of position points.
2045 */
2046 public abstract int getNumberOfDimensions();
2047
2048 /**
2049 * Gets estimated located radio source.
2050 *
2051 * @param <S2> type of located radio source.
2052 * @return estimated located radio source.
2053 */
2054 public abstract <S2 extends RadioSourceLocated<P>> S2 getEstimatedRadioSource();
2055
2056 /**
2057 * Builds ranging estimator.
2058 */
2059 protected abstract void buildRangingEstimatorIfNeeded();
2060
2061 /**
2062 * Build RSSI estimator.
2063 *
2064 * @throws LockedException if estimator is locked.
2065 */
2066 protected abstract void buildRssiEstimatorIfNeeded() throws LockedException;
2067
2068 /**
2069 * Setups ranging estimator.
2070 *
2071 * @throws LockedException if estimator is locked.
2072 */
2073 protected void setupRangingEstimator() throws LockedException {
2074 if (readings != null) {
2075 //build ranging readings
2076 final var rangingReadings = new ArrayList<RangingReadingLocated<S, P>>();
2077 for (final var reading : readings) {
2078 rangingReadings.add(createRangingReading(reading));
2079 }
2080 rangingEstimator.setReadings(rangingReadings);
2081 }
2082
2083 if (qualityScores != null) {
2084 rangingEstimator.setQualityScores(qualityScores);
2085 }
2086
2087 rangingEstimator.setProgressDelta(2.0f * progressDelta);
2088 rangingEstimator.setConfidence(rangingConfidence);
2089 rangingEstimator.setMaxIterations(rangingMaxIterations);
2090 rangingEstimator.setResultRefined(refineResult);
2091 rangingEstimator.setCovarianceKept(keepCovariance);
2092 rangingEstimator.setUseReadingPositionCovariances(useReadingPositionCovariances);
2093 rangingEstimator.setHomogeneousLinearSolverUsed(useHomogeneousRangingLinearSolver);
2094
2095 rangingEstimator.setInitialPosition(initialPosition);
2096
2097 rangingEstimator.setListener(new RobustRangingRadioSourceEstimatorListener<>() {
2098 @Override
2099 public void onEstimateStart(final RobustRangingRadioSourceEstimator<S, P> estimator) {
2100 // not used
2101 }
2102
2103 @Override
2104 public void onEstimateEnd(final RobustRangingRadioSourceEstimator<S, P> estimator) {
2105 // not used
2106 }
2107
2108 @Override
2109 public void onEstimateNextIteration(
2110 final RobustRangingRadioSourceEstimator<S, P> estimator, final int iteration) {
2111 // not used
2112 }
2113
2114 @Override
2115 public void onEstimateProgressChange(
2116 final RobustRangingRadioSourceEstimator<S, P> estimator, final float progress) {
2117 if (listener != null) {
2118 listener.onEstimateProgressChange(
2119 SequentialRobustRangingAndRssiRadioSourceEstimator.this, 0.5f * progress);
2120 }
2121 }
2122 });
2123 }
2124
2125 /**
2126 * Setups RSSI estimator.
2127 *
2128 * @throws LockedException if estimator is locked.
2129 */
2130 protected void setupRssiEstimator() throws LockedException {
2131 if (readings != null) {
2132 // build RSSI readings
2133 final var rssiReadings = new ArrayList<RssiReadingLocated<S, P>>();
2134 for (final var reading : readings) {
2135 rssiReadings.add(createRssiReading(reading));
2136 }
2137 rssiEstimator.setReadings(rssiReadings);
2138 }
2139
2140 if (qualityScores != null) {
2141 rssiEstimator.setQualityScores(qualityScores);
2142 }
2143
2144 rssiEstimator.setProgressDelta(2.0f * progressDelta);
2145 rssiEstimator.setConfidence(rssiConfidence);
2146 rssiEstimator.setMaxIterations(rssiMaxIterations);
2147 rssiEstimator.setResultRefined(refineResult);
2148 rssiEstimator.setCovarianceKept(keepCovariance);
2149
2150 // initial position is not set because position estimated from ranging measures
2151 // will be later used
2152 rssiEstimator.setInitialTransmittedPowerdBm(initialTransmittedPowerdBm);
2153 rssiEstimator.setInitialPathLossExponent(initialPathLossExponent);
2154
2155 rssiEstimator.setTransmittedPowerEstimationEnabled(
2156 transmittedPowerEstimationEnabled);
2157 rssiEstimator.setPathLossEstimationEnabled(pathLossEstimationEnabled);
2158
2159 rssiEstimator.setListener(new RobustRssiRadioSourceEstimatorListener<>() {
2160 @Override
2161 public void onEstimateStart(final RobustRssiRadioSourceEstimator<S, P> estimator) {
2162 // not used
2163 }
2164
2165 @Override
2166 public void onEstimateEnd(final RobustRssiRadioSourceEstimator<S, P> estimator) {
2167 // not used
2168 }
2169
2170 @Override
2171 public void onEstimateNextIteration(
2172 final RobustRssiRadioSourceEstimator<S, P> estimator, final int iteration) {
2173 // not used
2174 }
2175
2176 @Override
2177 public void onEstimateProgressChange(
2178 final RobustRssiRadioSourceEstimator<S, P> estimator, final float progress) {
2179 if (listener != null) {
2180 listener.onEstimateProgressChange(
2181 SequentialRobustRangingAndRssiRadioSourceEstimator.this,
2182 0.5f + 0.5f * progress);
2183 }
2184 }
2185 });
2186 }
2187
2188 /**
2189 * Internally sets signal readings belonging to the same radio source.
2190 *
2191 * @param readings signal readings belonging to the same radio source.
2192 * @throws IllegalArgumentException if readings are null, not enough readings
2193 * are available, or readings do not belong to the same access point.
2194 */
2195 private void internalSetReadings(final List<? extends RangingAndRssiReadingLocated<S, P>> readings) {
2196 if (!areValidReadings(readings)) {
2197 throw new IllegalArgumentException();
2198 }
2199
2200 this.readings = readings;
2201 }
2202
2203 /**
2204 * Sets quality scores corresponding to each provided sample.
2205 * This method is used internally and does not check whether instance is
2206 * locked or not.
2207 *
2208 * @param qualityScores quality scores to be set.
2209 * @throws IllegalArgumentException if provided quality scores length
2210 * is smaller than required minimum.
2211 */
2212 private void internalSetQualityScores(final double[] qualityScores) {
2213 if (qualityScores == null || qualityScores.length < getMinReadings()) {
2214 throw new IllegalArgumentException();
2215 }
2216
2217 this.qualityScores = qualityScores;
2218 }
2219
2220 /**
2221 * Creates a ranging reading from a ranging and RSSI reading.
2222 *
2223 * @param reading input reading to convert from.
2224 * @return a ranging reading containing only the ranging data of input reading.
2225 */
2226 private RangingReadingLocated<S, P> createRangingReading(final RangingAndRssiReadingLocated<S, P> reading) {
2227 return new RangingReadingLocated<>(reading.getSource(), reading.getDistance(), reading.getPosition(),
2228 reading.getDistanceStandardDeviation(), reading.getPositionCovariance());
2229 }
2230
2231 /**
2232 * Creates an RSSI reading from a ranging and RSSI reading.
2233 *
2234 * @param reading input reading to convert from.
2235 * @return an RSSI reading containing only the RSSI data of input reading.
2236 */
2237 private RssiReadingLocated<S, P> createRssiReading(final RangingAndRssiReadingLocated<S, P> reading) {
2238 return new RssiReadingLocated<>(reading.getSource(), reading.getRssi(), reading.getPosition(),
2239 reading.getRssiStandardDeviation(), reading.getPositionCovariance());
2240 }
2241 }