1 /*
2 * Copyright (C) 2019 Alberto Irurueta Carro (alberto@irurueta.com)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.irurueta.navigation.indoor.position;
17
18 import com.irurueta.geometry.Point2D;
19 import com.irurueta.navigation.LockedException;
20 import com.irurueta.navigation.indoor.Fingerprint;
21 import com.irurueta.navigation.indoor.RadioSource;
22 import com.irurueta.navigation.indoor.RadioSourceLocated;
23 import com.irurueta.navigation.indoor.Reading;
24
25 import java.util.List;
26
27 /**
28 * Robustly estimates 2D position, using RSSI readings first to obtain an initial coarse
29 * position estimation, and then ranging readings to refine such estimation.
30 * <p>
31 * This implementation is like SequentialRobustRangingAndRssiPositionEstimator but
32 * allows mixing different kinds of readings (ranging, RSSI or ranging+RSSI).
33 */
34 public class SequentialRobustMixedPositionEstimator2D extends SequentialRobustMixedPositionEstimator<Point2D> {
35
36 /**
37 * Constructor.
38 */
39 public SequentialRobustMixedPositionEstimator2D() {
40 super();
41 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
42 }
43
44 /**
45 * Constructor.
46 *
47 * @param sources located radio sources used for lateration.
48 * @throws IllegalArgumentException if provided sources is null or the number of provided
49 * sources is less than the required minimum.
50 */
51 public SequentialRobustMixedPositionEstimator2D(final List<? extends RadioSourceLocated<Point2D>> sources) {
52 super(sources);
53 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
54 }
55
56 /**
57 * Constructor.
58 *
59 * @param fingerprint fingerprint containing RSSI readings at an unknown location for
60 * provided located radio sources.
61 * @throws IllegalArgumentException if provided fingerprint is null.
62 */
63 public SequentialRobustMixedPositionEstimator2D(
64 final Fingerprint<? extends RadioSource, ? extends Reading<? extends RadioSource>> fingerprint) {
65 super(fingerprint);
66 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
67 }
68
69 /**
70 * Constructor.
71 *
72 * @param sources located radio sources used for lateration.
73 * @param fingerprint fingerprint containing readings at an unknown location for provided
74 * located radio sources.
75 * @throws IllegalArgumentException if either provided sources or fingerprint is null or
76 * the number of provided sources is less than the
77 * required minimum.
78 */
79 public SequentialRobustMixedPositionEstimator2D(
80 final List<? extends RadioSourceLocated<Point2D>> sources,
81 final Fingerprint<? extends RadioSource, ? extends Reading<? extends RadioSource>> fingerprint) {
82 super(sources, fingerprint);
83 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
84 }
85
86 /**
87 * Constructor.
88 *
89 * @param listener listener in charge of handling events.
90 */
91 public SequentialRobustMixedPositionEstimator2D(
92 final SequentialRobustMixedPositionEstimatorListener<Point2D> listener) {
93 super(listener);
94 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
95 }
96
97 /**
98 * Constructor.
99 *
100 * @param sources located radio sources used for lateration.
101 * @param listener listener in charge of handling events.
102 * @throws IllegalArgumentException if provided sources is null or the number of provided
103 * sources is less than the required minimum.
104 */
105 public SequentialRobustMixedPositionEstimator2D(
106 final List<? extends RadioSourceLocated<Point2D>> sources,
107 final SequentialRobustMixedPositionEstimatorListener<Point2D> listener) {
108 super(sources, listener);
109 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
110 }
111
112 /**
113 * Constructor.
114 *
115 * @param fingerprint fingerprint containing readings at an unknown location for provided
116 * located radio sources.
117 * @param listener listener in charge of handling events.
118 * @throws IllegalArgumentException if provided fingerprint is null.
119 */
120 public SequentialRobustMixedPositionEstimator2D(
121 final Fingerprint<? extends RadioSource, ? extends Reading<? extends RadioSource>> fingerprint,
122 final SequentialRobustMixedPositionEstimatorListener<Point2D> listener) {
123 super(fingerprint, listener);
124 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
125 }
126
127 /**
128 * Constructor.
129 *
130 * @param sources located radio sources used for lateration.
131 * @param fingerprint fingerprint containing readings at an unknown location for provided
132 * located radio sources.
133 * @param listener listener in charge of handling events.
134 * @throws IllegalArgumentException if either provided sources or fingerprint is null or
135 * the number of provided sources is less than the
136 * required minimum.
137 */
138 public SequentialRobustMixedPositionEstimator2D(
139 final List<? extends RadioSourceLocated<Point2D>> sources,
140 final Fingerprint<? extends RadioSource, ? extends Reading<? extends RadioSource>> fingerprint,
141 final SequentialRobustMixedPositionEstimatorListener<Point2D> listener) {
142 super(sources, fingerprint, listener);
143 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
144 }
145
146 /**
147 * Constructor.
148 *
149 * @param sourceQualityScores quality scores corresponding to each provided
150 * located radio source. The larger the score value
151 * the better the quality of the radio source.
152 * @param fingerprintReadingQualityScores quality scores corresponding to readings within
153 * provided fingerprint. The larger the score the
154 * better the quality of the reading.
155 */
156 public SequentialRobustMixedPositionEstimator2D(
157 final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores) {
158 super(sourceQualityScores, fingerprintReadingQualityScores);
159 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
160 }
161
162 /**
163 * Constructor.
164 *
165 * @param sourceQualityScores quality scores corresponding to each provided
166 * located radio source. The larger the score value
167 * the better the quality of the radio source.
168 * @param fingerprintReadingQualityScores quality scores corresponding to readings within
169 * provided fingerprint. The larger the score the
170 * better the quality of the reading.
171 * @param sources located radio sources used for lateration.
172 * @throws IllegalArgumentException if provided sources is null or the number of provided sources is less than the
173 * required minimum.
174 */
175 public SequentialRobustMixedPositionEstimator2D(
176 final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
177 final List<? extends RadioSourceLocated<Point2D>> sources) {
178 super(sourceQualityScores, fingerprintReadingQualityScores, sources);
179 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
180 }
181
182 /**
183 * Constructor.
184 *
185 * @param sourceQualityScores quality scores corresponding to each provided
186 * located radio source. The larger the score value
187 * the better the quality of the radio source.
188 * @param fingerprintReadingQualityScores quality scores corresponding to readings within
189 * provided fingerprint. The larger the score the
190 * better the quality of the reading.
191 * @param fingerprint fingerprint containing readings at an unknown
192 * location for provided located radio sources.
193 * @throws IllegalArgumentException if provided fingerprint is null.
194 */
195 public SequentialRobustMixedPositionEstimator2D(
196 final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
197 final Fingerprint<? extends RadioSource, ? extends Reading<? extends RadioSource>> fingerprint) {
198 super(sourceQualityScores, fingerprintReadingQualityScores, fingerprint);
199 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
200 }
201
202 /**
203 * Constructor.
204 *
205 * @param sourceQualityScores quality scores corresponding to each provided
206 * located radio source. The larger the score value
207 * the better the quality of the radio source.
208 * @param fingerprintReadingQualityScores quality scores corresponding to readings within
209 * provided fingerprint. The larger the score the
210 * better the quality of the reading.
211 * @param sources located radio sources used for lateration.
212 * @param fingerprint fingerprint containing readings at an unknown
213 * location for provided located radio sources.
214 * @throws IllegalArgumentException if either provided sources or fingerprint is null or
215 * the number of provided sources is less than the
216 * required minimum.
217 */
218 public SequentialRobustMixedPositionEstimator2D(
219 final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
220 final List<? extends RadioSourceLocated<Point2D>> sources,
221 final Fingerprint<? extends RadioSource, ? extends Reading<? extends RadioSource>> fingerprint) {
222 super(sourceQualityScores, fingerprintReadingQualityScores, sources, fingerprint);
223 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
224 }
225
226 /**
227 * Constructor.
228 *
229 * @param sourceQualityScores quality scores corresponding to each provided
230 * located radio source. The larger the score value
231 * the better the quality of the radio source.
232 * @param fingerprintReadingQualityScores quality scores corresponding to readings within
233 * provided fingerprint. The larger the score the
234 * better the quality of the reading.
235 * @param listener listener in charge of handling events.
236 */
237 public SequentialRobustMixedPositionEstimator2D(
238 final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
239 final SequentialRobustMixedPositionEstimatorListener<Point2D> listener) {
240 super(sourceQualityScores, fingerprintReadingQualityScores, listener);
241 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
242 }
243
244 /**
245 * Constructor.
246 *
247 * @param sourceQualityScores quality scores corresponding to each provided
248 * located radio source. The larger the score value
249 * the better the quality of the radio source.
250 * @param fingerprintReadingQualityScores quality scores corresponding to readings within
251 * provided fingerprint. The larger the score the
252 * better the quality of the reading.
253 * @param sources located radio sources used for lateration.
254 * @param listener listener in charge of handling events.
255 * @throws IllegalArgumentException if provided sources is null or the number of provided
256 * sources is less than the required minimum.
257 */
258 public SequentialRobustMixedPositionEstimator2D(
259 final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
260 final List<? extends RadioSourceLocated<Point2D>> sources,
261 final SequentialRobustMixedPositionEstimatorListener<Point2D> listener) {
262 super(sourceQualityScores, fingerprintReadingQualityScores, sources, listener);
263 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
264 }
265
266 /**
267 * Constructor.
268 *
269 * @param sourceQualityScores quality scores corresponding to each provided
270 * located radio source. The larger the score value
271 * the better the quality of the radio source.
272 * @param fingerprintReadingQualityScores quality scores corresponding to readings within
273 * provided fingerprint. The larger the score the
274 * better the quality of the reading.
275 * @param fingerprint fingerprint containing readings at an unknown
276 * location for provided located radio sources.
277 * @param listener listener in charge of handling events.
278 * @throws IllegalArgumentException if provided fingerprint is null.
279 */
280 public SequentialRobustMixedPositionEstimator2D(
281 final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
282 final Fingerprint<? extends RadioSource, ? extends Reading<? extends RadioSource>> fingerprint,
283 final SequentialRobustMixedPositionEstimatorListener<Point2D> listener) {
284 super(sourceQualityScores, fingerprintReadingQualityScores, fingerprint, listener);
285 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
286 }
287
288 /**
289 * Constructor.
290 *
291 * @param sourceQualityScores quality scores corresponding to each provided
292 * located radio source. The larger the score value
293 * the better the quality of the radio source.
294 * @param fingerprintReadingQualityScores quality scores corresponding to readings within
295 * provided fingerprint. The larger the score the
296 * better the quality of the reading.
297 * @param sources located radio sources used for lateration.
298 * @param fingerprint fingerprint containing readings at an unknown
299 * location for provided located radio sources.
300 * @param listener listener in charge of handling events.
301 * @throws IllegalArgumentException if either provided sources or fingerprint is null or
302 * the number of provided sources is less than the
303 * required minimum.
304 */
305 public SequentialRobustMixedPositionEstimator2D(
306 final double[] sourceQualityScores, final double[] fingerprintReadingQualityScores,
307 final List<? extends RadioSourceLocated<Point2D>> sources,
308 final Fingerprint<? extends RadioSource, ? extends Reading<? extends RadioSource>> fingerprint,
309 final SequentialRobustMixedPositionEstimatorListener<Point2D> listener) {
310 super(sourceQualityScores, fingerprintReadingQualityScores, sources, fingerprint, listener);
311 rangingPreliminarySubsetSize = rssiPreliminarySubsetSize = getMinRequiredSources();
312 }
313
314 /**
315 * Gets number of dimensions of provided and estimated points.
316 *
317 * @return number of dimensions of provided and estimated points.
318 */
319 @Override
320 public int getNumberOfDimensions() {
321 return Point2D.POINT2D_INHOMOGENEOUS_COORDINATES_LENGTH;
322 }
323
324 /**
325 * Gets minimum required number of located radio sources to perform lateration.
326 *
327 * @return minimum required number of located radio sources to perform lateration.
328 */
329 @Override
330 public int getMinRequiredSources() {
331 return Point2D.POINT2D_HOMOGENEOUS_COORDINATES_LENGTH;
332 }
333
334 /**
335 * Builds ranging internal estimator.
336 */
337 @Override
338 protected void buildRangingEstimator() {
339 rangingEstimator = RobustRangingPositionEstimator2D.create(rangingRobustMethod);
340 }
341
342 /**
343 * Builds RSSI internal estimator.
344 */
345 @Override
346 protected void buildRssiEstimator() {
347 rssiEstimator = RobustRssiPositionEstimator2D.create(rssiRobustMethod);
348 }
349
350 /**
351 * Setup ranging internal estimator.
352 *
353 * @throws LockedException if estimator is locked.
354 */
355 @Override
356 protected void setupRangingEstimator() throws LockedException {
357 super.setupRangingEstimator();
358 if (rangingThreshold != null) {
359 switch (rangingRobustMethod) {
360 case RANSAC:
361 ((RANSACRobustRangingPositionEstimator2D) rangingEstimator).setThreshold(rangingThreshold);
362 break;
363 case LMEDS:
364 ((LMedSRobustRangingPositionEstimator2D) rangingEstimator).setStopThreshold(rangingThreshold);
365 break;
366 case MSAC:
367 ((MSACRobustRangingPositionEstimator2D) rangingEstimator).setThreshold(rangingThreshold);
368 break;
369 case PROSAC:
370 ((PROSACRobustRangingPositionEstimator2D) rangingEstimator).setThreshold(rangingThreshold);
371 break;
372 case PROMEDS:
373 default:
374 ((PROMedSRobustRangingPositionEstimator2D) rangingEstimator).setStopThreshold(rangingThreshold);
375 break;
376 }
377 }
378 }
379
380 /**
381 * Setup RSSI internal estimator.
382 *
383 * @throws LockedException if estimator is locked.
384 */
385 @Override
386 protected void setupRssiEstimator() throws LockedException {
387 super.setupRssiEstimator();
388 if (rssiThreshold != null) {
389 switch (rssiRobustMethod) {
390 case RANSAC:
391 ((RANSACRobustRssiPositionEstimator2D) rssiEstimator).setThreshold(rssiThreshold);
392 break;
393 case LMEDS:
394 ((LMedSRobustRssiPositionEstimator2D) rssiEstimator).setStopThreshold(rssiThreshold);
395 break;
396 case MSAC:
397 ((MSACRobustRssiPositionEstimator2D) rssiEstimator).setThreshold(rssiThreshold);
398 break;
399 case PROSAC:
400 ((PROSACRobustRssiPositionEstimator2D) rssiEstimator).setThreshold(rssiThreshold);
401 break;
402 case PROMEDS:
403 default:
404 ((PROMedSRobustRssiPositionEstimator2D) rssiEstimator).setStopThreshold(rssiThreshold);
405 break;
406 }
407 }
408 }
409 }