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.Beacon;
20 import com.irurueta.navigation.indoor.BeaconWithPowerAndLocated3D;
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.WifiAccessPointWithPowerAndLocated3D;
26
27 import java.util.List;
28
29 /**
30 * Estimates 3D 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 RangingAndRssiRadioSourceEstimator3D<S extends RadioSource> extends
59 RangingAndRssiRadioSourceEstimator<S, Point3D> {
60
61 /**
62 * Constructor.
63 */
64 public RangingAndRssiRadioSourceEstimator3D() {
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 RangingAndRssiRadioSourceEstimator3D(
77 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> 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 RangingAndRssiRadioSourceEstimator3D(final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> 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 RangingAndRssiRadioSourceEstimator3D(
99 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> readings,
100 final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> listener) {
101 super(readings, listener);
102 }
103
104 /**
105 * Constructor.
106 *
107 * @param initialPosition initial position to start the estimation of radio
108 * source position.
109 */
110 public RangingAndRssiRadioSourceEstimator3D(final Point3D initialPosition) {
111 super(initialPosition);
112 }
113
114 /**
115 * Constructor.
116 * Sets radio signal readings belonging to the same radio source.
117 *
118 * @param readings radio signal readings belonging to the same radio source.
119 * @param initialPosition initial position to start the estimation of radio
120 * source position.
121 * @throws IllegalArgumentException if readings are not valid.
122 */
123 public RangingAndRssiRadioSourceEstimator3D(
124 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> readings, final Point3D initialPosition) {
125 super(readings, initialPosition);
126 }
127
128 /**
129 * Constructor.
130 *
131 * @param initialPosition initial position to start the estimation of radio
132 * source position.
133 * @param listener listener in charge of attending events raised by this instance.
134 */
135 public RangingAndRssiRadioSourceEstimator3D(
136 final Point3D initialPosition, final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> listener) {
137 super(initialPosition, listener);
138 }
139
140 /**
141 * Constructor.
142 * Sets radio signal readings belonging to the same radio source.
143 *
144 * @param readings radio signal readings belonging to the same radio source.
145 * @param initialPosition initial position to start the estimation of radio
146 * source position.
147 * @param listener listener in charge of attending events raised by this instance.
148 * @throws IllegalArgumentException if readings are not valid.
149 */
150 public RangingAndRssiRadioSourceEstimator3D(
151 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> readings, final Point3D initialPosition,
152 final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> listener) {
153 super(readings, initialPosition, listener);
154 }
155
156 /**
157 * Constructor.
158 *
159 * @param initialTransmittedPowerDbm initial transmitted power to start the
160 * estimation of radio source transmitted power
161 * (expressed in dBm's).
162 */
163 public RangingAndRssiRadioSourceEstimator3D(final Double initialTransmittedPowerDbm) {
164 super(initialTransmittedPowerDbm);
165 }
166
167 /**
168 * Constructor.
169 * Sets radio signal readings belonging to the same radio source.
170 *
171 * @param readings radio signal readings belonging to the same radio source.
172 * @param initialTransmittedPowerdBm initial transmitted power to start the
173 * estimation of radio source transmitted power
174 * (expressed in dBm's).
175 * @throws IllegalArgumentException if readings are not valid.
176 */
177 public RangingAndRssiRadioSourceEstimator3D(
178 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> readings,
179 final Double initialTransmittedPowerdBm) {
180 super(readings, initialTransmittedPowerdBm);
181 }
182
183 /**
184 * Constructor.
185 *
186 * @param initialTransmittedPowerdBm initial transmitted power to start the
187 * estimation of radio source transmitted power
188 * (expressed in dBm's).
189 * @param listener listener in charge of attending events raised by this instance.
190 */
191 public RangingAndRssiRadioSourceEstimator3D(
192 final Double initialTransmittedPowerdBm,
193 final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> listener) {
194 super(initialTransmittedPowerdBm, listener);
195 }
196
197 /**
198 * Constructor.
199 * Sets radio signal readings belonging to the same radio source.
200 *
201 * @param readings radio signal readings belonging to the same radio source.
202 * @param initialTransmittedPowerdBm initial transmitted power to start the
203 * estimation of radio source transmitted power
204 * (expressed in dBm's).
205 * @param listener listener in charge of attending events raised by this instance.
206 * @throws IllegalArgumentException if readings are not valid.
207 */
208 public RangingAndRssiRadioSourceEstimator3D(
209 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> readings,
210 final Double initialTransmittedPowerdBm,
211 final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> listener) {
212 super(readings, initialTransmittedPowerdBm, listener);
213 }
214
215 /**
216 * Constructor.
217 * Sets radio signal readings belonging to the same radio source.
218 *
219 * @param readings radio signal readings belonging to the same radio source.
220 * @param initialPosition initial position to start the estimation of radio
221 * source position.
222 * @param initialTransmittedPowerdBm initial transmitted power to start the
223 * estimation of radio source transmitted power
224 * (expressed in dBm's).
225 * @throws IllegalArgumentException if readings are not valid.
226 */
227 public RangingAndRssiRadioSourceEstimator3D(
228 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> readings, final Point3D initialPosition,
229 final Double initialTransmittedPowerdBm) {
230 super(readings, initialPosition, initialTransmittedPowerdBm);
231 }
232
233 /**
234 * Constructor.
235 *
236 * @param initialPosition initial position to start the estimation of radio
237 * source position.
238 * @param initialTransmittedPowerdBm initial transmitted power to start the
239 * estimation of radio source transmitted power
240 * (expressed in dBm's).
241 */
242 public RangingAndRssiRadioSourceEstimator3D(final Point3D 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 RangingAndRssiRadioSourceEstimator3D(
257 final Point3D initialPosition, final Double initialTransmittedPowerdBm,
258 final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> 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 RangingAndRssiRadioSourceEstimator3D(
276 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> readings, final Point3D initialPosition,
277 final Double initialTransmittedPowerdBm,
278 final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> 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 RangingAndRssiRadioSourceEstimator3D(
296 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> readings, final Point3D 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 RangingAndRssiRadioSourceEstimator3D(
312 final Point3D 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 RangingAndRssiRadioSourceEstimator3D(
329 final Point3D initialPosition, final Double initialTransmittedPowerdBm,
330 final double initialPathLossExponent,
331 final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> 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 RangingAndRssiRadioSourceEstimator3D(
350 final List<? extends RangingAndRssiReadingLocated<S, Point3D>> readings, final Point3D initialPosition,
351 final Double initialTransmittedPowerdBm, final double initialPathLossExponent,
352 final RangingAndRssiRadioSourceEstimatorListener<S, Point3D> listener) {
353 super(readings, initialPosition, initialTransmittedPowerdBm, initialPathLossExponent, listener);
354 }
355
356 /**
357 * Gets number of dimensions of position points.
358 * This is always 3.
359 *
360 * @return number of dimensions of position points.
361 */
362 @Override
363 public int getNumberOfDimensions() {
364 return Point3D.POINT3D_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<Point3D> 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 WifiAccessPointWithPowerAndLocated3D(accessPoint.getBssid(), accessPoint.getFrequency(),
402 accessPoint.getSsid(), transmittedPowerdBm, transmittedPowerStandardDeviation, pathLossExponent,
403 pathLossExponentStandardDeviation, estimatedPosition, estimatedPositionCovariance);
404 } else if (source instanceof Beacon beacon) {
405 return new BeaconWithPowerAndLocated3D(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 RangingRadioSourceEstimator3D<>();
422 }
423
424 if (rssiInnerEstimator == null && (transmittedPowerEstimationEnabled || pathLossEstimationEnabled)) {
425 rssiInnerEstimator = new RssiRadioSourceEstimator3D<>();
426 }
427 }
428 }