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.fingerprint;
17
18 import com.irurueta.geometry.InhomogeneousPoint2D;
19 import com.irurueta.geometry.Point2D;
20 import com.irurueta.navigation.indoor.RadioSource;
21 import com.irurueta.navigation.indoor.RadioSourceLocated;
22 import com.irurueta.navigation.indoor.RssiFingerprint;
23 import com.irurueta.navigation.indoor.RssiFingerprintLocated;
24 import com.irurueta.navigation.indoor.RssiReading;
25
26 import java.util.List;
27
28 /**
29 * 2D position estimator based on located fingerprints containing only RSSI readings and
30 * having as well prior knowledge of the location of radio sources associated to those
31 * readings.
32 * This is a base implementation for all implementations using different orders of
33 * Taylor approximation to estimate position.
34 */
35 @SuppressWarnings("DuplicatedCode")
36 public abstract class NonLinearFingerprintPositionEstimator2D extends NonLinearFingerprintPositionEstimator<Point2D> {
37
38 /**
39 * Constructor.
40 */
41 protected NonLinearFingerprintPositionEstimator2D() {
42 }
43
44 /**
45 * Constructor.
46 *
47 * @param listener listener in charge of handling events.
48 */
49 protected NonLinearFingerprintPositionEstimator2D(final FingerprintPositionEstimatorListener<Point2D> listener) {
50 super(listener);
51 }
52
53 /**
54 * Constructor.
55 *
56 * @param locatedFingerprints located fingerprints containing RSSI readings.
57 * @param fingerprint fingerprint containing readings at an unknown location
58 * for provided located fingerprints.
59 * @param sources located radio sources.
60 * @throws IllegalArgumentException if provided non located fingerprint is null,
61 * located fingerprints value is null or there are not enough fingerprints or
62 * readings within provided fingerprints (for 2D position estimation at least 2
63 * located total readings are required among all fingerprints, for example 2
64 * readings are required in a single fingerprint, or at least 2 fingerprints at
65 * different locations containing a single reading are required).
66 */
67 protected NonLinearFingerprintPositionEstimator2D(
68 final List<? extends RssiFingerprintLocated<? extends RadioSource,
69 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
70 final RssiFingerprint<? extends RadioSource,
71 ? extends RssiReading<? extends RadioSource>> fingerprint,
72 final List<? extends RadioSourceLocated<Point2D>> sources) {
73 super(locatedFingerprints, fingerprint, sources);
74 }
75
76 /**
77 * Constructor.
78 *
79 * @param locatedFingerprints located fingerprints containing RSSI readings.
80 * @param fingerprint fingerprint containing readings at an unknown location
81 * for provided located fingerprints.
82 * @param sources located radio sources.
83 * @param listener listener in charge of handling events.
84 * @throws IllegalArgumentException if provided non located fingerprint is null,
85 * located fingerprints value is null or there are not enough fingerprints or
86 * readings within provided fingerprints (for 2D position estimation at least 2
87 * located total readings are required among all fingerprints, for example 2
88 * readings are required in a single fingerprint, or at least 2 fingerprints at
89 * different locations containing a single reading are required).
90 */
91 protected NonLinearFingerprintPositionEstimator2D(
92 final List<? extends RssiFingerprintLocated<? extends RadioSource,
93 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
94 final RssiFingerprint<? extends RadioSource,
95 ? extends RssiReading<? extends RadioSource>> fingerprint,
96 final List<? extends RadioSourceLocated<Point2D>> sources,
97 final FingerprintPositionEstimatorListener<Point2D> listener) {
98 super(locatedFingerprints, fingerprint, sources, listener);
99 }
100
101 /**
102 * Constructor.
103 *
104 * @param locatedFingerprints located fingerprints containing RSSI readings.
105 * @param fingerprint fingerprint containing readings at an unknown location
106 * for provided located fingerprints.
107 * @param sources located radio sources.
108 * @param initialPosition initial position to start the solving algorithm or null.
109 * @throws IllegalArgumentException if provided non located fingerprint is null,
110 * located fingerprints value is null or there are not enough fingerprints or
111 * readings within provided fingerprints (for 2D position estimation at least 2
112 * located total readings are required among all fingerprints, for example 2
113 * readings are required in a single fingerprint, or at least 2 fingerprints at
114 * different locations containing a single reading are required).
115 */
116 protected NonLinearFingerprintPositionEstimator2D(
117 final List<? extends RssiFingerprintLocated<? extends RadioSource,
118 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
119 final RssiFingerprint<? extends RadioSource,
120 ? extends RssiReading<? extends RadioSource>> fingerprint,
121 final List<? extends RadioSourceLocated<Point2D>> sources, Point2D initialPosition) {
122 super(locatedFingerprints, fingerprint, sources, initialPosition);
123 }
124
125 /**
126 * Constructor.
127 *
128 * @param locatedFingerprints located fingerprints containing RSSI readings.
129 * @param fingerprint fingerprint containing readings at an unknown location
130 * for provided located fingerprints.
131 * @param sources located radio sources.
132 * @param initialPosition initial position to start the solving algorithm or null.
133 * @param listener listener in charge of handling events.
134 * @throws IllegalArgumentException if provided non located fingerprint is null,
135 * located fingerprints value is null or there are not enough fingerprints or
136 * readings within provided fingerprints (for 2D position estimation at least 2
137 * located total readings are required among all fingerprints, for example 2
138 * readings are required in a single fingerprint, or at least 2 fingerprints at
139 * different locations containing a single reading are required).
140 */
141 protected NonLinearFingerprintPositionEstimator2D(
142 final List<? extends RssiFingerprintLocated<? extends RadioSource,
143 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
144 final RssiFingerprint<? extends RadioSource,
145 ? extends RssiReading<? extends RadioSource>> fingerprint,
146 final List<? extends RadioSourceLocated<Point2D>> sources, Point2D initialPosition,
147 final FingerprintPositionEstimatorListener<Point2D> listener) {
148 super(locatedFingerprints, fingerprint, sources, initialPosition, listener);
149 }
150
151 /**
152 * Gets number of dimensions of points.
153 *
154 * @return number of dimensions of points.
155 */
156 @Override
157 public int getNumberOfDimensions() {
158 return Point2D.POINT2D_INHOMOGENEOUS_COORDINATES_LENGTH;
159 }
160
161 /**
162 * Gets estimated position or null if not available yet.
163 *
164 * @return estimated position or null.
165 */
166 @Override
167 public Point2D getEstimatedPosition() {
168 if (estimatedPositionCoordinates == null) {
169 return null;
170 }
171
172 final var result = new InhomogeneousPoint2D();
173 getEstimatedPosition(result);
174 return result;
175 }
176
177 /**
178 * Creates an instance of a non-linear 2D position estimator using provided type.
179 *
180 * @param type type to be used.
181 * @return a non-linear 2D position estimator.
182 */
183 public static NonLinearFingerprintPositionEstimator2D create(final NonLinearFingerprintPositionEstimatorType type) {
184 return switch (type) {
185 case THIRD_ORDER -> new ThirdOrderNonLinearFingerprintPositionEstimator2D();
186 case SECOND_ORDER -> new SecondOrderNonLinearFingerprintPositionEstimator2D();
187 default -> new FirstOrderNonLinearFingerprintPositionEstimator2D();
188 };
189 }
190
191 /**
192 * Creates an instance of a non-linear 2D position estimator using provided type.
193 *
194 * @param listener listener in charge of handling events.
195 * @param type a non-linear 2D position estimator.
196 * @return a non-linear 2D position estimator.
197 */
198 public static NonLinearFingerprintPositionEstimator2D create(
199 final FingerprintPositionEstimatorListener<Point2D> listener,
200 final NonLinearFingerprintPositionEstimatorType type) {
201 return switch (type) {
202 case THIRD_ORDER -> new ThirdOrderNonLinearFingerprintPositionEstimator2D(listener);
203 case SECOND_ORDER -> new SecondOrderNonLinearFingerprintPositionEstimator2D(listener);
204 default -> new FirstOrderNonLinearFingerprintPositionEstimator2D(listener);
205 };
206 }
207
208 /**
209 * Creates an instance of a non-linear 2D position estimator using provided type.
210 *
211 * @param locatedFingerprints located fingerprints containing RSSI readings.
212 * @param fingerprint fingerprint containing readings at an unknown location
213 * for provided located fingerprints.
214 * @param sources located radio sources.
215 * @param type a non-linear 2D position estimator.
216 * @return a non-linear 2D position estimator.
217 * @throws IllegalArgumentException if provided non located fingerprint is null,
218 * located fingerprints value is null or there are not enough fingerprints or
219 * readings within provided fingerprints (for 2D position estimation at least 2
220 * located total readings are required among all fingerprints, for example 2
221 * readings are required in a single fingerprint, or at least 2 fingerprints at
222 * different locations containing a single reading are required).
223 */
224 public static NonLinearFingerprintPositionEstimator2D create(
225 final List<? extends RssiFingerprintLocated<? extends RadioSource,
226 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
227 final RssiFingerprint<? extends RadioSource,
228 ? extends RssiReading<? extends RadioSource>> fingerprint,
229 final List<? extends RadioSourceLocated<Point2D>> sources,
230 final NonLinearFingerprintPositionEstimatorType type) {
231 return switch (type) {
232 case THIRD_ORDER -> new ThirdOrderNonLinearFingerprintPositionEstimator2D(
233 locatedFingerprints, fingerprint, sources);
234 case SECOND_ORDER -> new SecondOrderNonLinearFingerprintPositionEstimator2D(
235 locatedFingerprints, fingerprint, sources);
236 default -> new FirstOrderNonLinearFingerprintPositionEstimator2D(
237 locatedFingerprints, fingerprint, sources);
238 };
239 }
240
241 /**
242 * Creates an instance of a non-linear 2D position estimator using provided type.
243 *
244 * @param locatedFingerprints located fingerprints containing RSSI readings.
245 * @param fingerprint fingerprint containing readings at an unknown location
246 * for provided located fingerprints.
247 * @param sources located radio sources.
248 * @param listener listener in charge of handling events.
249 * @param type a non-linear 2D position estimator.
250 * @return a non-linear 2D position estimator.
251 * @throws IllegalArgumentException if provided non located fingerprint is null,
252 * located fingerprints value is null or there are not enough fingerprints or
253 * readings within provided fingerprints (for 2D position estimation at least 2
254 * located total readings are required among all fingerprints, for example 2
255 * readings are required in a single fingerprint, or at least 2 fingerprints at
256 * different locations containing a single reading are required).
257 */
258 public static NonLinearFingerprintPositionEstimator2D create(
259 final List<? extends RssiFingerprintLocated<? extends RadioSource,
260 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
261 final RssiFingerprint<? extends RadioSource,
262 ? extends RssiReading<? extends RadioSource>> fingerprint,
263 final List<? extends RadioSourceLocated<Point2D>> sources,
264 final FingerprintPositionEstimatorListener<Point2D> listener,
265 final NonLinearFingerprintPositionEstimatorType type) {
266 return switch (type) {
267 case THIRD_ORDER -> new ThirdOrderNonLinearFingerprintPositionEstimator2D(
268 locatedFingerprints, fingerprint, sources, listener);
269 case SECOND_ORDER -> new SecondOrderNonLinearFingerprintPositionEstimator2D(
270 locatedFingerprints, fingerprint, sources, listener);
271 default -> new FirstOrderNonLinearFingerprintPositionEstimator2D(
272 locatedFingerprints, fingerprint, sources, listener);
273 };
274 }
275
276 /**
277 * Creates an instance of a non-linear 2D position estimator using provided type.
278 *
279 * @param locatedFingerprints located fingerprints containing RSSI readings.
280 * @param fingerprint fingerprint containing readings at an unknown location
281 * for provided located fingerprints.
282 * @param sources located radio sources.
283 * @param initialPosition initial position to start the solving algorithm or null.
284 * @param type a non-linear 2D position estimator.
285 * @return a non-linear 2D position estimator.
286 * @throws IllegalArgumentException if provided non located fingerprint is null,
287 * located fingerprints value is null or there are not enough fingerprints or
288 * readings within provided fingerprints (for 2D position estimation at least 2
289 * located total readings are required among all fingerprints, for example 2
290 * readings are required in a single fingerprint, or at least 2 fingerprints at
291 * different locations containing a single reading are required).
292 */
293 public static NonLinearFingerprintPositionEstimator2D create(
294 final List<? extends RssiFingerprintLocated<? extends RadioSource,
295 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
296 final RssiFingerprint<? extends RadioSource,
297 ? extends RssiReading<? extends RadioSource>> fingerprint,
298 final List<? extends RadioSourceLocated<Point2D>> sources,
299 final Point2D initialPosition,
300 final NonLinearFingerprintPositionEstimatorType type) {
301 return switch (type) {
302 case THIRD_ORDER -> new ThirdOrderNonLinearFingerprintPositionEstimator2D(
303 locatedFingerprints, fingerprint, sources, initialPosition);
304 case SECOND_ORDER -> new SecondOrderNonLinearFingerprintPositionEstimator2D(
305 locatedFingerprints, fingerprint, sources, initialPosition);
306 default -> new FirstOrderNonLinearFingerprintPositionEstimator2D(
307 locatedFingerprints, fingerprint, sources, initialPosition);
308 };
309 }
310
311 /**
312 * Creates an instance of a non-linear 2D position estimator using provided type.
313 *
314 * @param locatedFingerprints located fingerprints containing RSSI readings.
315 * @param fingerprint fingerprint containing readings at an unknown location
316 * for provided located fingerprints.
317 * @param sources located radio sources.
318 * @param initialPosition initial position to start the solving algorithm or null.
319 * @param listener listener in charge of handling events.
320 * @param type a non-linear 2D position estimator.
321 * @return a non-linear 2D position estimator.
322 * @throws IllegalArgumentException if provided non located fingerprint is null,
323 * located fingerprints value is null or there are not enough fingerprints or
324 * readings within provided fingerprints (for 2D position estimation at least 2
325 * located total readings are required among all fingerprints, for example 2
326 * readings are required in a single fingerprint, or at least 2 fingerprints at
327 * different locations containing a single reading are required).
328 */
329 public static NonLinearFingerprintPositionEstimator2D create(
330 final List<? extends RssiFingerprintLocated<
331 ? extends RadioSource, ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
332 final RssiFingerprint<? extends RadioSource,
333 ? extends RssiReading<? extends RadioSource>> fingerprint,
334 final List<? extends RadioSourceLocated<Point2D>> sources, Point2D initialPosition,
335 final FingerprintPositionEstimatorListener<Point2D> listener,
336 final NonLinearFingerprintPositionEstimatorType type) {
337 return switch (type) {
338 case THIRD_ORDER -> new ThirdOrderNonLinearFingerprintPositionEstimator2D(
339 locatedFingerprints, fingerprint, sources, initialPosition, listener);
340 case SECOND_ORDER -> new SecondOrderNonLinearFingerprintPositionEstimator2D(
341 locatedFingerprints, fingerprint, sources, initialPosition, listener);
342 default -> new FirstOrderNonLinearFingerprintPositionEstimator2D(
343 locatedFingerprints, fingerprint, sources, initialPosition, listener);
344 };
345 }
346
347 /**
348 * Creates an instance of a non-linear 2D position estimator using default type.
349 *
350 * @return a non-linear 2D position estimator.
351 */
352 public static NonLinearFingerprintPositionEstimator2D create() {
353 return create(DEFAULT_TYPE);
354 }
355
356 /**
357 * Creates an instance of a non-linear 2D position estimator using default type.
358 *
359 * @param listener listener in charge of handling events.
360 * @return a non-linear 2D position estimator.
361 */
362 public static NonLinearFingerprintPositionEstimator2D create(
363 final FingerprintPositionEstimatorListener<Point2D> listener) {
364 return create(listener, DEFAULT_TYPE);
365 }
366
367 /**
368 * Creates an instance of a non-linear 2D position estimator using provided type.
369 *
370 * @param locatedFingerprints located fingerprints containing RSSI readings.
371 * @param fingerprint fingerprint containing readings at an unknown location
372 * for provided located fingerprints.
373 * @param sources located radio sources.
374 * @return a non-linear 2D position estimator.
375 * @throws IllegalArgumentException if provided non located fingerprint is null,
376 * located fingerprints value is null or there are not enough fingerprints or
377 * readings within provided fingerprints (for 2D position estimation at least 2
378 * located total readings are required among all fingerprints, for example 2
379 * readings are required in a single fingerprint, or at least 2 fingerprints at
380 * different locations containing a single reading are required).
381 */
382 public static NonLinearFingerprintPositionEstimator2D create(
383 final List<? extends RssiFingerprintLocated<? extends RadioSource,
384 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
385 final RssiFingerprint<? extends RadioSource,
386 ? extends RssiReading<? extends RadioSource>> fingerprint,
387 final List<? extends RadioSourceLocated<Point2D>> sources) {
388 return create(locatedFingerprints, fingerprint, sources, DEFAULT_TYPE);
389 }
390
391 /**
392 * Creates an instance of a non-linear 2D position estimator using provided type.
393 *
394 * @param locatedFingerprints located fingerprints containing RSSI readings.
395 * @param fingerprint fingerprint containing readings at an unknown location
396 * for provided located fingerprints.
397 * @param sources located radio sources.
398 * @param listener listener in charge of handling events.
399 * @return a non-linear 2D position estimator.
400 * @throws IllegalArgumentException if provided non located fingerprint is null,
401 * located fingerprints value is null or there are not enough fingerprints or
402 * readings within provided fingerprints (for 2D position estimation at least 2
403 * located total readings are required among all fingerprints, for example 2
404 * readings are required in a single fingerprint, or at least 2 fingerprints at
405 * different locations containing a single reading are required).
406 */
407 public static NonLinearFingerprintPositionEstimator2D create(
408 final List<? extends RssiFingerprintLocated<? extends RadioSource,
409 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
410 final RssiFingerprint<? extends RadioSource,
411 ? extends RssiReading<? extends RadioSource>> fingerprint,
412 final List<? extends RadioSourceLocated<Point2D>> sources,
413 final FingerprintPositionEstimatorListener<Point2D> listener) {
414 return create(locatedFingerprints, fingerprint, sources, listener, DEFAULT_TYPE);
415 }
416
417 /**
418 * Creates an instance of a non-linear 2D position estimator using provided type.
419 *
420 * @param locatedFingerprints located fingerprints containing RSSI readings.
421 * @param fingerprint fingerprint containing readings at an unknown location
422 * for provided located fingerprints.
423 * @param sources located radio sources.
424 * @param initialPosition initial position to start the solving algorithm or null.
425 * @return a non-linear 2D position estimator.
426 * @throws IllegalArgumentException if provided non located fingerprint is null,
427 * located fingerprints value is null or there are not enough fingerprints or
428 * readings within provided fingerprints (for 2D position estimation at least 2
429 * located total readings are required among all fingerprints, for example 2
430 * readings are required in a single fingerprint, or at least 2 fingerprints at
431 * different locations containing a single reading are required).
432 */
433 public static NonLinearFingerprintPositionEstimator2D create(
434 final List<? extends RssiFingerprintLocated<? extends RadioSource,
435 ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
436 final RssiFingerprint<? extends RadioSource,
437 ? extends RssiReading<? extends RadioSource>> fingerprint,
438 final List<? extends RadioSourceLocated<Point2D>> sources,
439 final Point2D initialPosition) {
440 return create(locatedFingerprints, fingerprint, sources, initialPosition, DEFAULT_TYPE);
441 }
442
443 /**
444 * Creates an instance of a non-linear 2D position estimator using provided type.
445 *
446 * @param locatedFingerprints located fingerprints containing RSSI readings.
447 * @param fingerprint fingerprint containing readings at an unknown location
448 * for provided located fingerprints.
449 * @param sources located radio sources.
450 * @param initialPosition initial position to start the solving algorithm or null.
451 * @param listener listener in charge of handling events.
452 * @return a non-linear 2D position estimator.
453 * @throws IllegalArgumentException if provided non located fingerprint is null,
454 * located fingerprints value is null or there are not enough fingerprints or
455 * readings within provided fingerprints (for 2D position estimation at least 2
456 * located total readings are required among all fingerprints, for example 2
457 * readings are required in a single fingerprint, or at least 2 fingerprints at
458 * different locations containing a single reading are required).
459 */
460 public static NonLinearFingerprintPositionEstimator2D create(
461 final List<? extends RssiFingerprintLocated<
462 ? extends RadioSource, ? extends RssiReading<? extends RadioSource>, Point2D>> locatedFingerprints,
463 final RssiFingerprint<? extends RadioSource,
464 ? extends RssiReading<? extends RadioSource>> fingerprint,
465 final List<? extends RadioSourceLocated<Point2D>> sources, Point2D initialPosition,
466 final FingerprintPositionEstimatorListener<Point2D> listener) {
467 return create(locatedFingerprints, fingerprint, sources, initialPosition, listener, DEFAULT_TYPE);
468 }
469 }