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 }