Tuesday, July 28, 2015

Calculating distance from WiFi AP using RSSI

Certainly the best approach to start looking into this is using a free-space path loss. It is by no means optimal - notice the free-space part of its name, so you actually need no obstacles between measuring device and AP. But it's at least a good approximation.
Wikipedia defines free-space path loss in decibels as follows:

This is for distance d in km and frequency f in GHz. We want to measure distance in m and frequency in MHz, so the formula becomes:

Solving for d, we got:

Now, what to do with the FSPL? Is it equal to RSSI? Unfrotunately no. First, let's understand, what we can expect as FSPL values.

First, we made a series of measurements with different devices to analyze, how RSSI changes over distance and we averaged them (blue RSSI series). We can see that values up to -50 dBm, can be used for somewhat relevant calculation. Lower values are highly unstable.
Second, let's have a look on FSPL values. If we calculate for 2412 MHz, and for the distance we use values (1, 2, ..., 20 m), we can get the FSPL, from the first formula. Note that calculated values are positive, so I took the liberty of inverting them over distance axis (orange calcRSSI series). This looks a lot like our first graph series. We just need to shift it up (gray corrRSSI series).
Now we can say that for measuring on Android, FSPL = approximately 6.7 - RSSI.

My high school physics teacher would probably kick my ass for this, but it works.

So written in Java, the final formula is:
public static double calculateDistance(double rssi, double freq) {
        return Math.pow(10.0d, (27.55d - 40d * Math.log10(freq) + 6.7d - rssi) / 20.0d);


  1. Hi! I have tried this but it only works if the router and the android device has the same height or level of elevation. How do you code this so that its reading will be like the reading in the Accelerometer onSensorChange method that it will change every single time.


    1. Note that this is only approximation and is highly inaccurate. For periodic readings you can use Handler and continuous posting of the reading event.

  2. Great work... Are the results of the calculateDistance method in km?