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.radiosource;
17  
18  import com.irurueta.geometry.Point2D;
19  import com.irurueta.navigation.indoor.Beacon;
20  import com.irurueta.navigation.indoor.BeaconWithPowerAndLocated2D;
21  import com.irurueta.navigation.indoor.RadioSource;
22  import com.irurueta.navigation.indoor.RadioSourceLocated;
23  import com.irurueta.navigation.indoor.RangingAndRssiReadingLocated;
24  import com.irurueta.navigation.indoor.WifiAccessPoint;
25  import com.irurueta.navigation.indoor.WifiAccessPointWithPowerAndLocated2D;
26  
27  import java.util.List;
28  
29  /**
30   * Estimates 2D position, transmitted power and path loss exponent of a
31   * radio source (e.g. Wi-Fi access point or bluetooth beacon) assuming
32   * that the ranging data is available to obtain position with greater
33   * accuracy and that the radio source emits isotropically following the
34   * expression below:
35   * Pr = Pt*Gt*Gr*lambda^2 / (4*pi*d)^2,
36   * where Pr is the received power (expressed in mW),
37   * Gt is the Gain of the transmission antenna
38   * Gr is the Gain of the receiver antenna
39   * d is the distance between emitter and receiver
40   * and lambda is the wavelength and is equal to: lambda = c / f,
41   * where c is the speed of light
42   * and f is the carrier frequency of the radio signal.
43   * Because usually information about the antenna of the radio source cannot be
44   * retrieved (because many measurements are made on unknown devices where
45   * physical access is not possible), this implementation will estimate the
46   * equivalent transmitted power as: Pte = Pt * Gt * Gr.
47   * If Readings contain RSSI standard deviations, those values will be used,
48   * otherwise it will be assumed an RSSI standard deviation of 1 dB.
49   * <p>
50   * Although RssiRadioSourceEstimator can estimate the same parameters of a radio
51   * source, when ranging measures are available along with RSSI measurements,
52   * implementations of this class should be preferred instead as they can provide
53   * greater accuracy.
54   *
55   * @param <S> a {@link RadioSource} type.
56   */
57  @SuppressWarnings("Duplicates")
58  public class RangingAndRssiRadioSourceEstimator2D<S extends RadioSource> extends
59          RangingAndRssiRadioSourceEstimator<S, Point2D> {
60  
61      /**
62       * Constructor.
63       */
64      public RangingAndRssiRadioSourceEstimator2D() {
65          super();
66      }
67  
68      /**
69       * Constructor.
70       * Sets radio signal readings belonging to the same radio source.
71       *
72       * @param readings radio signal readings belonging to the same
73       *                 radio sources.
74       * @throws IllegalArgumentException if readings are not valid.
75       */
76      public RangingAndRssiRadioSourceEstimator2D(
77              final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings) {
78          super(readings);
79      }
80  
81      /**
82       * Constructor.
83       *
84       * @param listener listener in charge of attending events raised by this instance.
85       */
86      public RangingAndRssiRadioSourceEstimator2D(final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
87          super(listener);
88      }
89  
90      /**
91       * Constructor.
92       * Sets radio signal readings belonging to the same radio source.
93       *
94       * @param readings radio signal readings belonging to the same radio source.
95       * @param listener listener in charge of attending events raised by this instance.
96       * @throws IllegalArgumentException if readings are not valid.
97       */
98      public RangingAndRssiRadioSourceEstimator2D(final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings,
99                                                  final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
100         super(readings, listener);
101     }
102 
103     /**
104      * Constructor.
105      *
106      * @param initialPosition initial position to start the estimation of radio
107      *                        source position.
108      */
109     public RangingAndRssiRadioSourceEstimator2D(final Point2D initialPosition) {
110         super(initialPosition);
111     }
112 
113     /**
114      * Constructor.
115      * Sets radio signal readings belonging to the same radio source.
116      *
117      * @param readings        radio signal readings belonging to the same radio source.
118      * @param initialPosition initial position to start the estimation of radio
119      *                        source position.
120      * @throws IllegalArgumentException if readings are not valid.
121      */
122     public RangingAndRssiRadioSourceEstimator2D(
123             final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings, final Point2D initialPosition) {
124         super(readings, initialPosition);
125     }
126 
127     /**
128      * Constructor.
129      *
130      * @param initialPosition initial position to start the estimation of radio
131      *                        source position.
132      * @param listener        listener in charge of attending events raised by this instance.
133      */
134     public RangingAndRssiRadioSourceEstimator2D(
135             final Point2D initialPosition, final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
136         super(initialPosition, listener);
137     }
138 
139     /**
140      * Constructor.
141      * Sets radio signal readings belonging to the same radio source.
142      *
143      * @param readings        radio signal readings belonging to the same radio source.
144      * @param initialPosition initial position to start the estimation of radio
145      *                        source position.
146      * @param listener        listener in charge of attending events raised by this instance.
147      * @throws IllegalArgumentException if readings are not valid.
148      */
149     public RangingAndRssiRadioSourceEstimator2D(
150             final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings, final Point2D initialPosition,
151             final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
152         super(readings, initialPosition, listener);
153     }
154 
155     /**
156      * Constructor.
157      *
158      * @param initialTransmittedPowerDbm initial transmitted power to start the
159      *                                   estimation of radio source transmitted power
160      *                                   (expressed in dBm's).
161      */
162     public RangingAndRssiRadioSourceEstimator2D(final Double initialTransmittedPowerDbm) {
163         super(initialTransmittedPowerDbm);
164     }
165 
166     /**
167      * Constructor.
168      * Sets radio signal readings belonging to the same radio source.
169      *
170      * @param readings                   radio signal readings belonging to the same radio source.
171      * @param initialTransmittedPowerdBm initial transmitted power to start the
172      *                                   estimation of radio source transmitted power
173      *                                   (expressed in dBm's).
174      * @throws IllegalArgumentException if readings are not valid.
175      */
176     public RangingAndRssiRadioSourceEstimator2D(
177             final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings,
178             final Double initialTransmittedPowerdBm) {
179         super(readings, initialTransmittedPowerdBm);
180     }
181 
182     /**
183      * Constructor.
184      *
185      * @param initialTransmittedPowerdBm initial transmitted power to start the
186      *                                   estimation of radio source transmitted power
187      *                                   (expressed in dBm's).
188      * @param listener                   listener in charge of attending events raised by this instance.
189      */
190     public RangingAndRssiRadioSourceEstimator2D(
191             final Double initialTransmittedPowerdBm,
192             final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
193         super(initialTransmittedPowerdBm, listener);
194     }
195 
196     /**
197      * Constructor.
198      * Sets radio signal readings belonging to the same radio source.
199      *
200      * @param readings                   radio signal readings belonging to the same radio source.
201      * @param initialTransmittedPowerdBm initial transmitted power to start the
202      *                                   estimation of radio source transmitted power
203      *                                   (expressed in dBm's).
204      * @param listener                   listener in charge of attending events raised by this instance.
205      * @throws IllegalArgumentException if readings are not valid.
206      */
207     public RangingAndRssiRadioSourceEstimator2D(
208             final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings,
209             final Double initialTransmittedPowerdBm,
210             final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
211         super(readings, initialTransmittedPowerdBm, listener);
212     }
213 
214     /**
215      * Constructor.
216      * Sets radio signal readings belonging to the same radio source.
217      *
218      * @param readings                   radio signal readings belonging to the same radio source.
219      * @param initialPosition            initial position to start the estimation of radio
220      *                                   source position.
221      * @param initialTransmittedPowerdBm initial transmitted power to start the
222      *                                   estimation of radio source transmitted power
223      *                                   (expressed in dBm's).
224      * @throws IllegalArgumentException if readings are not valid.
225      */
226     public RangingAndRssiRadioSourceEstimator2D(
227             final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings, final Point2D initialPosition,
228             final Double initialTransmittedPowerdBm) {
229         super(readings, initialPosition, initialTransmittedPowerdBm);
230     }
231 
232     /**
233      * Constructor.
234      *
235      * @param initialPosition            initial position to start the estimation of radio
236      *                                   source position.
237      * @param initialTransmittedPowerdBm initial transmitted power to start the
238      *                                   estimation of radio source transmitted power
239      *                                   (expressed in dBm's).
240      */
241     public RangingAndRssiRadioSourceEstimator2D(
242             final Point2D initialPosition, final Double initialTransmittedPowerdBm) {
243         super(initialPosition, initialTransmittedPowerdBm);
244     }
245 
246     /**
247      * Constructor.
248      *
249      * @param initialPosition            initial position to start the estimation of radio
250      *                                   source position.
251      * @param initialTransmittedPowerdBm initial transmitted power to start the
252      *                                   estimation of radio source transmitted power
253      *                                   (expressed in dBm's).
254      * @param listener                   listener in charge of attending events raised by this instance.
255      */
256     public RangingAndRssiRadioSourceEstimator2D(
257             final Point2D initialPosition, final Double initialTransmittedPowerdBm,
258             final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
259         super(initialPosition, initialTransmittedPowerdBm, listener);
260     }
261 
262     /**
263      * Constructor.
264      * Sets radio signal readings belonging to the same radio source.
265      *
266      * @param readings                   radio signal readings belonging to the same radio source.
267      * @param initialPosition            initial position to start the estimation of radio
268      *                                   source position.
269      * @param initialTransmittedPowerdBm initial transmitted power to start the
270      *                                   estimation of radio source transmitted power
271      *                                   (expressed in dBm's).
272      * @param listener                   listener in charge of attending events raised by this instance.
273      * @throws IllegalArgumentException if readings are not valid.
274      */
275     public RangingAndRssiRadioSourceEstimator2D(
276             final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings, final Point2D initialPosition,
277             final Double initialTransmittedPowerdBm,
278             final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
279         super(readings, initialPosition, initialTransmittedPowerdBm, listener);
280     }
281 
282     /**
283      * Constructor.
284      * Sets radio signal readings belonging to the same radio source.
285      *
286      * @param readings                   radio signal readings belonging to the same radio source.
287      * @param initialPosition            initial position to start the estimation of radio
288      *                                   source position.
289      * @param initialTransmittedPowerdBm initial transmitted power to start the
290      *                                   estimation of radio source transmitted power
291      *                                   (expressed in dBm's).
292      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
293      * @throws IllegalArgumentException if readings are not valid.
294      */
295     public RangingAndRssiRadioSourceEstimator2D(
296             final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings, final Point2D initialPosition,
297             final Double initialTransmittedPowerdBm, final double initialPathLossExponent) {
298         super(readings, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent);
299     }
300 
301     /**
302      * Constructor.
303      *
304      * @param initialPosition            initial position to start the estimation of radio
305      *                                   source position.
306      * @param initialTransmittedPowerdBm initial transmitted power to start the
307      *                                   estimation of radio source transmitted power
308      *                                   (expressed in dBm's).
309      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
310      */
311     public RangingAndRssiRadioSourceEstimator2D(
312             final Point2D initialPosition, final Double initialTransmittedPowerdBm,
313             final double initialPathLossExponent) {
314         super(initialPosition, initialTransmittedPowerdBm, initialPathLossExponent);
315     }
316 
317     /**
318      * Constructor.
319      *
320      * @param initialPosition            initial position to start the estimation of radio
321      *                                   source position.
322      * @param initialTransmittedPowerdBm initial transmitted power to start the
323      *                                   estimation of radio source transmitted power
324      *                                   (expressed in dBm's).
325      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
326      * @param listener                   listener in charge of attending events raised by this instance.
327      */
328     public RangingAndRssiRadioSourceEstimator2D(
329             final Point2D initialPosition, final Double initialTransmittedPowerdBm,
330             final double initialPathLossExponent,
331             final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
332         super(initialPosition, initialTransmittedPowerdBm, initialPathLossExponent, listener);
333     }
334 
335     /**
336      * Constructor.
337      * Sets radio signal readings belonging to the same radio source.
338      *
339      * @param readings                   radio signal readings belonging to the same radio source.
340      * @param initialPosition            initial position to start the estimation of radio
341      *                                   source position.
342      * @param initialTransmittedPowerdBm initial transmitted power to start the
343      *                                   estimation of radio source transmitted power
344      *                                   (expressed in dBm's).
345      * @param initialPathLossExponent    initial path loss exponent. A typical value is 2.0.
346      * @param listener                   listener in charge of attending events raised by this instance.
347      * @throws IllegalArgumentException if readings are not valid.
348      */
349     public RangingAndRssiRadioSourceEstimator2D(
350             final List<? extends RangingAndRssiReadingLocated<S, Point2D>> readings, final Point2D initialPosition,
351             final Double initialTransmittedPowerdBm, final double initialPathLossExponent,
352             final RangingAndRssiRadioSourceEstimatorListener<S, Point2D> listener) {
353         super(readings, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent, listener);
354     }
355 
356     /**
357      * Gets number of dimensions of position points.
358      * This is always 2.
359      *
360      * @return number of dimensions of position points.
361      */
362     @Override
363     public int getNumberOfDimensions() {
364         return Point2D.POINT2D_INHOMOGENEOUS_COORDINATES_LENGTH;
365     }
366 
367     /**
368      * Gets estimated located radio source.
369      *
370      * @return estimated located radio source or null.
371      */
372     @Override
373     @SuppressWarnings("unchecked")
374     public RadioSourceLocated<Point2D> getEstimatedRadioSource() {
375         final var readings = getReadings();
376         if (readings == null || readings.isEmpty()) {
377             return null;
378         }
379         final var source = readings.get(0).getSource();
380 
381         final var estimatedPosition = getEstimatedPosition();
382         if (estimatedPosition == null) {
383             return null;
384         }
385 
386         final var estimatedPositionCovariance = getEstimatedPositionCovariance();
387 
388         final var transmittedPowerdBm = getEstimatedTransmittedPowerdBm();
389 
390         final var transmittedPowerVariance = getEstimatedTransmittedPowerVariance();
391         final var transmittedPowerStandardDeviation = transmittedPowerVariance != null
392                 ? Math.sqrt(transmittedPowerVariance) : null;
393 
394         final var pathLossExponent = getEstimatedPathLossExponent();
395 
396         final var pathLossExponentVariance = getEstimatedPathLossExponentVariance();
397         final var pathLossExponentStandardDeviation = pathLossExponentVariance != null
398                 ? Math.sqrt(pathLossExponentVariance) : null;
399 
400         if (source instanceof WifiAccessPoint accessPoint) {
401             return new WifiAccessPointWithPowerAndLocated2D(accessPoint.getBssid(), accessPoint.getFrequency(),
402                     accessPoint.getSsid(), transmittedPowerdBm, transmittedPowerStandardDeviation, pathLossExponent,
403                     pathLossExponentStandardDeviation, estimatedPosition, estimatedPositionCovariance);
404         } else if (source instanceof Beacon beacon) {
405             return new BeaconWithPowerAndLocated2D(beacon.getIdentifiers(), beacon.getTransmittedPower(),
406                     beacon.getFrequency(), beacon.getBluetoothAddress(), beacon.getBeaconTypeCode(),
407                     beacon.getManufacturer(), beacon.getServiceUuid(), beacon.getBluetoothName(), pathLossExponent,
408                     transmittedPowerStandardDeviation, pathLossExponentStandardDeviation, estimatedPosition,
409                     estimatedPositionCovariance);
410         } else {
411             return null;
412         }
413     }
414 
415     /**
416      * Creates inner estimators if needed.
417      */
418     @Override
419     protected void createInnerEstimatorsIfNeeded() {
420         if (rangingInnerEstimator == null) {
421             rangingInnerEstimator = new RangingRadioSourceEstimator2D<>();
422         }
423 
424         if (rssiInnerEstimator == null && (transmittedPowerEstimationEnabled || pathLossEstimationEnabled)) {
425             rssiInnerEstimator = new RssiRadioSourceEstimator2D<>();
426         }
427     }
428 }