View Javadoc
1   /*
2    * Copyright (C) 2018 Alberto Irurueta Carro (alberto@irurueta.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.irurueta.navigation.indoor.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 }