View Javadoc
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 }