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;
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 }