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 }