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;
17
18 /**
19 * Utility class to handle Android's AltBeacon library coefficients used te determine distance for calibrated devices.
20 * AltBeacon uses the following formula to estimate Beacon's distance:
21 * d = coefficient1 * ratio^coefficient2 + coefficient3
22 * <p>
23 * Considered that radio signal propagation follows equation:
24 * Pr = Pt * k / d^n,
25 * where:
26 * - Pr is received signal strength (expressed in mW),
27 * - Pt is transmitted signal strength (expressed in mW),
28 * - k is equal to k = c / (4 * pi * f), where:
29 * - c is speed of light (which is approximately 9*10^8 m/s)
30 * - f is the radio link frequency used by the beacon.
31 * <p>
32 * Hence, considering:
33 * ratio = Pr / Pt
34 * <p>
35 * which is equal to:
36 * ratio = k / d^n
37 * <p>
38 * And isolating d, whe obtain that:
39 * d^n = k / ratio
40 * <p>
41 * d = (k / ratio)^(1/n)
42 * d = k^(1/n)*ratio^(-1/n)
43 * <p>
44 * And thus we can see from this last expression that:
45 * coefficient1 = k^(1/n) = (c / (4 * pi * f))^(1/n)
46 * coefficient2 = -1/n, where n is the path loss exponent and depends on the
47 * environment where the device is used (typically on free space n is equal to
48 * 2.0, but can usually range from 1.6 to 1.8 on indoor environments)
49 * coefficient3 is a bias term calibrated for each device.
50 */
51 public class AltBeaconUtils {
52
53 /**
54 * Speed of light expressed in meters per second (m/s).
55 */
56 public static final double SPEED_OF_LIGHT = 299792458.0;
57
58 /**
59 * Constructor to prevent instantiation of utility class.
60 */
61 private AltBeaconUtils() {
62 }
63
64 /**
65 * Gets k value using provided frequency.
66 * K is defined as k = c / (4 * pi * f), where:
67 * - c is the speed of light expressed in m/s.
68 * - f is the frequency expressed in Hz.
69 *
70 * @param frequency a frequency (expressed in Hz).
71 * @return k value.
72 */
73 public static double getK(final double frequency) {
74 //k = c / (4 * pi * f)
75 return SPEED_OF_LIGHT / (4.0 * Math.PI * frequency);
76 }
77
78 /**
79 * Gets k value using AltBeacon's coefficients.
80 *
81 * @param coefficient1 1st coefficient.
82 * @param coefficient2 2nd coefficient.
83 * @return k value.
84 */
85 public static double getK(final double coefficient1, final double coefficient2) {
86 //coefficient1 = k^(1/n), hence
87 //k = coefficient1^n
88 final var n = -1.0 / coefficient2;
89 return Math.pow(coefficient1, n);
90 }
91
92 /**
93 * Gets frequency from k value.
94 *
95 * @param k k value.
96 * @return frequency expressed in Hz.
97 */
98 public static double getFrequency(final double k) {
99 //k = c / (4*pi*f) --> f = c / (4*pi*k)
100 return SPEED_OF_LIGHT / (4.0 * Math.PI * k);
101 }
102
103 /**
104 * Gets frequency using AltBeacon's coefficients.
105 *
106 * @param coefficient1 1st coefficient.
107 * @param coefficient2 2nd coefficient.
108 * @return frequency expressed in Hz.
109 */
110 public static double getFrequency(final double coefficient1, final double coefficient2) {
111 return getFrequency(getK(coefficient1, coefficient2));
112 }
113
114 /**
115 * Gets path loss exponent using AltBeacon's coefficient.
116 *
117 * @param coefficient2 2nd coefficient.
118 * @return path loss exponent.
119 */
120 public static double getPathLossExponent(final double coefficient2) {
121 //coefficient2 = -1/n
122 return -1.0 / coefficient2;
123 }
124
125 /**
126 * Gets distance using AltBeacon's coefficients.
127 *
128 * @param coefficient1 1st coefficient.
129 * @param coefficient2 2nd coefficient.
130 * @param coefficient3 3rd coefficient.
131 * @param ratio ratio between received power and transmitted power.
132 * @return distance expressed in meters.
133 */
134 public static double getDistance(
135 final double coefficient1, final double coefficient2, final double coefficient3, final double ratio) {
136 //d = coefficient1 * ratio^coefficient2 + coefficient3
137 return coefficient1 * Math.pow(ratio, coefficient2) + coefficient3;
138 }
139
140 /**
141 * Gets distance using AltBeacon's coefficients.
142 *
143 * @param coefficient1 1st coefficient.
144 * @param coefficient2 2nd coefficient.
145 * @param coefficient3 3rd coefficient.
146 * @param receivedPower received power (expressed in mW).
147 * @param transmittedPower transmitted power (expressed in mW).
148 * @return distance expressed in meters.
149 */
150 public static double getDistance(
151 final double coefficient1, final double coefficient2, final double coefficient3, final double receivedPower,
152 final double transmittedPower) {
153 return getDistance(coefficient1, coefficient2, coefficient3, receivedPower / transmittedPower);
154 }
155
156 /**
157 * Gets power ratio between received power and transmitted power
158 * using AltBeacon's coefficients.
159 *
160 * @param coefficient1 1st coefficient.
161 * @param coefficient2 2nd coefficient.
162 * @param coefficient3 3rd coefficient.
163 * @param distance distance expressed in meters.
164 * @return power ratio.
165 */
166 public static double getRatio(
167 final double coefficient1, final double coefficient2, final double coefficient3, final double distance) {
168 //d = coefficient1 * ratio^coefficient2 + coefficient3
169 //d - coefficient3 = coefficient1 * ratio^coefficient2
170 //(d - coefficient3) / coefficient1 = ratio^coefficient2
171 //ratio = ((d - coefficient3) / coefficient1)^(1/coefficient2)
172 return Math.pow((distance - coefficient3) / coefficient1, 1.0 / coefficient2);
173 }
174
175 /**
176 * Gets power ratio between received power and transmitted power.
177 *
178 * @param receivedPower received power (expressed in mW).
179 * @param transmittedPower transmitted power (expressed in mW).
180 * @return power ratio.
181 */
182 public static double getRatio(final double receivedPower, final double transmittedPower) {
183 return receivedPower / transmittedPower;
184 }
185
186 /**
187 * Gets received power.
188 *
189 * @param ratio ratio between received power and transmitted power.
190 * @param transmittedPower transmitted power (expressed in mW).
191 * @return received power (expressed in mW).
192 */
193 public static double getReceivedPower(final double ratio, final double transmittedPower) {
194 //ratio = Pr / Pt
195 return ratio * transmittedPower;
196 }
197
198 /**
199 * Gets received power using AltBeacon's coefficients.
200 *
201 * @param coefficient1 1st coefficient.
202 * @param coefficient2 2nd coefficient.
203 * @param coefficient3 3rd coefficient.
204 * @param distance distance expressed in meters.
205 * @param transmittedPower transmitted power expressed in mW.
206 * @return received power expressed in mW.
207 */
208 public static double getReceivedPower(
209 final double coefficient1, final double coefficient2, final double coefficient3, final double distance,
210 final double transmittedPower) {
211 return getReceivedPower(getRatio(coefficient1, coefficient2, coefficient3, distance), transmittedPower);
212 }
213
214 /**
215 * Gets transmitted power.
216 *
217 * @param ratio ratio between received power and transmitted power.
218 * @param receivedPower received power expressed in mW.
219 * @return transmitted power expressed in mW.
220 */
221 public static double getTransmittedPower(final double ratio, final double receivedPower) {
222 //ratio = Pr / Pt
223 return receivedPower / ratio;
224 }
225
226 /**
227 * Gets transmitted power using AltBeacon's coefficients.
228 *
229 * @param coefficient1 1st coefficient.
230 * @param coefficient2 2nd coefficient.
231 * @param coefficient3 3rd coefficient.
232 * @param distance distance expressed in meters.
233 * @param receivedPower received power expressed in mW.
234 * @return transmitted power expressed in mW.
235 */
236 public static double getTransmittedPower(
237 final double coefficient1, final double coefficient2, final double coefficient3, final double distance,
238 final double receivedPower) {
239 return getTransmittedPower(getRatio(coefficient1, coefficient2, coefficient3, distance), receivedPower);
240 }
241
242 /**
243 * Gets AltBeacon's 1st coefficient.
244 *
245 * @param k k value.
246 * @param pathLossExponent path loss exponent.
247 * @return AltBeacon's 1st coefficient.
248 */
249 public static double getCoefficient1(final double k, final double pathLossExponent) {
250 //coefficient1 = k^(1/n)
251 return Math.pow(k, 1.0 / pathLossExponent);
252 }
253
254 /**
255 * Gets AltBeacon's 1st coefficient.
256 *
257 * @param frequency frequency expressed in Hz.
258 * @param pathLossExponent path loss exponent.
259 * @return AltBeacon's 1st coefficient.
260 */
261 public static double getCoefficient1WithFrequency(final double frequency, final double pathLossExponent) {
262 return getCoefficient1(getK(frequency), pathLossExponent);
263 }
264
265 /**
266 * Gets AltBeacon's 2nd coefficient.
267 *
268 * @param pathLossExponent path loss exponent.
269 * @return AltBeacon's 2nd coefficient.
270 */
271 public static double getCoefficient2(final double pathLossExponent) {
272 //coefficient2 = -1/n
273 return -1.0 / pathLossExponent;
274 }
275 }