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