AltBeacon / spec

AltBeacon Technical Specification

Home Page:http://altbeacon.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Distance equation wrong?

WallyHale opened this issue · comments

Testing Android and iOS devices side by side, using 7 beacons on their "loudest" setting (-63 Tx), we find that -

  • Both Android and iOS devices show similar RSSI signal readings at various distances
  • With the formula used on Android version the same RSSI reading is converted to a very different distance on Android as compared to IOS (see table below)
  • RSSI readings were similar on 3 Android devices used for testing (Nexus 5, Nexus 4, Samsung Galaxy S5)
  • In fact Android device never showed distance further then 5 meters away for any RSSI which is logical based on the trend you see for Android in the table below

Distance, iOS (RSSI)
0m (-35), 1m (-63 = Tx), 2m (-70), 4.5m (-75), 10m (-80), 25 (-90)

Distance, Android (RSSI)
0m (-35), 1m (-63 = Tx), 1.2m (-70), 1.6m (-75), 2.7m (-80), 4 (-90)

Is it possible to either find a way to adjust parameter in the formula to mach iOS calculations closer or use liner approximation based on the experimental data above

@WallyHale, you are correct in your observations. The current formula used by the library is imperfect and has real problems on underestimating distance for weaker transmitters.

We have been experimenting with a different formula in this branch here: https://github.com/AltBeacon/android-beacon-library/tree/path-loss-distance-calculations. We are trying to use this formula under the theory that we can simply calculate a single dB difference between the receiver sensitivity of various device models and apply that device-specific correction constant before calculating distance. If this works, it should give better distance estimates for different beacon transmitter power levels.

However, we are still having trouble because we are finding that the RSSI returned by some Android devices at larger distances is inconsistent with what would be expected. Doing tests with the Samsung Galaxy S6 vs. the iPhone, we found that the delta in the RSSI between the devices seeing the same beacon at various distances did not stay consistent:

The RSSI offset between the iPhone and the Galaxy S6 Edge + does not stay consistent with changes in distance. For this technique to work, we need the delta RSSI in dB to be consistent for a device even as the distance increases. Unfortunately, we saw RSSI numbers like this:

Rad Beacon Dot Beacon @ 1m
iPhone     Galaxy S6      Delta
-48.1        -50.8        -2.7

Rad Beacon Dot Beacon @ 5m
iPhone     Galaxy S6     Delta
-70.0       -81.1         -11.1

I'd appreciate help from folks with any expertise in this area to figure out a solution.

The RSSI offset between the iPhone and the Galaxy S6 Edge + does not stay consistent with changes in distance.

While I understand that it is VERY difficult to have a one solution fits all (especially with the variety of Android devices), that doesn't explain the distance calculations with similar, and consistent RSSI values.

If similar RSSI readings to that of an iOS device, the formula should be able to be tweaked so the distance calculation in relation to the RSSI should be somewhat accurate, or at least a lot more accurate than what we are currently seeing? ie. a -90 RSSI with a Tx of -63, should never equal 4 metres?

I too am seeing massive differences with the RSSI reading, when comparing a Nexus 5X to a Nexus 5, but difference in receivers and devices aside, the formula should be accurate for whatever RSSI / Tx values it's being fed.

If, in the end, the device has a stronger receiver, so the beacon appears closer than it actually is, this shouldn't matter, the important thing is a sound calculation when the RSSI's DO match

I just realised that the figures and explanation may be misleading.

The distance and RSSI quoted above is the calculated distance (beacon.getDistance()) value, NOT the actual physical distance of the device from the beacon.

So, the Android and iOS devices are side by side, moving away from beacon and taking readings, and the RSSI values are similar on both devices, but the calculated distance is wildly incorrect on Android compared to

  1. the iOS distance reading
  2. the actual physical distance the device is from the beacon

So this is not to do with the Bluetooth receiver picking up weaker signals, it's the calculation of the RSSI.

The beacons were physically ~25m from the devices, the RSSI are similar (-90), the Android device says the beacon is 4m away, while iOS more on the money.

I hope this clears any confusion!

Understood. As I mentioned before, the current formula in the library has a significant flaw. It works well with higher powered transmitters but exhibits the results you see on lower power transmitters. This is why we proposed switching to a different formula that works better in the referenced pull request: https://github.com/AltBeacon/android-beacon-library/tree/path-loss-distance-calculations It will help the problem you see.

The trouble is that we have not gotten far enough with this formula to merge it into the release. I'd welcome any help you could give in testing with the branch associated with that pull request to see how well it predicts the distances on the devices you have.

Thanks @davidgyoung - I've built the path-loss-distance-calculation branch and included it in my project (removing the 2.6 build references to be certain), but I'm still seeing much shorter calculated distances when RSSI is -90 to -100 .. beacon.getDistance returns 5 metres or so away, when it's physically ~17 metres.

We'll keep investigating!

Two things you can experiment with, @WallyHale:

  1. Try adjusting the 0.35 constant in the formula: distance = Math.pow(10.0, ((-adjustedRssi+txPower)/10*0.35)); This constant needs to be the same across all devices, but may be changed to give the best results.
  2. Try changing the receiver_rssi_offset for each of your mobile devices in model-distance-calculations-r2.json. This is designed to adjust the RSSI values you get to make them more similar to what an iOS device sees at the same distance. The theory is that a static offset can correct for differences in antenna gain.

I have been working at tuning this off and on for months, and would love to get this to the point where it gives consistently better results than the current built-in formula.

We have come up with a linear approximation algorithm that meets our needs, and importantly, giving similar and consistent readings to iOS on various devices tested.

Wally, that sounds very promising. Do you plan to submit a pull request to incorporate this into the library?

David Helms
Chief Product Officer
Radius Networks
dhelms@radiusnetworks.com
703.582.1576

On Nov 20, 2015, at 7:34 AM, WallyHale notifications@github.com wrote:

We have come up with a linear approximation algorithm that meets our needs, and importantly, giving similar and consistent readings to iOS on various devices tested.


Reply to this email directly or view it on GitHub #30 (comment).

I'd love to see what you have come up with if you can share.

It probably won't suit all uses, but maybe you can work with / refine it further. The calculations were done from our testing at loudest beacon setting (-63), but it also works when changing beacon loudness to lower (weaker) values too without modifying the code.

public double calculateDistance(int tx, double rssi) {
    //define reference points based on iOS test
    //point 1
    double x_1 = (double) -35 / -63;
    double y_1 = 0;

    //point 2
    double x_2 = (double) -63 / -63;
    double y_2 = 1;

    //point 3
    double x_3 = (double) -70 / -63;
    double y_3 = 2;

    //point 4
    double x_4 = (double) -75 / -63;
    double y_4 = 4.5;

    //point 5
    double x_5 = (double) -80 / -63;
    double y_5 = 10;

    //point 6
    double x_6 = (double) -90 / -63;
    double y_6 = 25;

    //calculate relative signal strength the distance depends on
    double x = rssi / tx;

    //calculate distance
    double distance = 0.0;
    double x_startpoint = 0;
    double y_startpoint = 0;
    double x_endpoint = 0;
    double y_endpoint = 0;


    //check if x less than x_1 first, set distance to 0 in this case
    if (x < x_1)
        distance = 0.0;
    else // check if x is larger then x_6  set distance to unknown in this case
        if (x > x_6) distance = 0.0;
        else
            // find 2 points to use for approximation
            if (x >= x_5) {
                // x is between 5 and 6
                x_startpoint = x_5;
                y_startpoint = y_5;
                x_endpoint = x_6;
                y_endpoint = y_6;
            } else if (x >= x_4) {
                // x is between 4 and 5
                x_startpoint = x_4;
                y_startpoint = y_4;
                x_endpoint = x_5;
                y_endpoint = y_5;
            } else if (x >= x_3) {
                // x is between 3 and 4
                x_startpoint = x_3;
                y_startpoint = y_3;
                x_endpoint = x_4;
                y_endpoint = y_4;
            } else if (x >= x_2) {
                // x is between 2 and 3
                x_startpoint = x_2;
                y_startpoint = y_2;
                x_endpoint = x_3;
                y_endpoint = y_3;
            } else if (x >= x_1) {
                // x is between 1 and 2
                x_startpoint = x_1;
                y_startpoint = y_1;
                x_endpoint = x_2;
                y_endpoint = y_2;
            }

    Log.i("CalculateDistance", "x_startpoint= " + x_startpoint);
    Log.i("CalculateDistance", "y_startpoint= " + y_startpoint);
    Log.i("CalculateDistance", "x_endpoint= " + x_endpoint);
    Log.i("CalculateDistance", "y_endpoint= " + y_endpoint);

    // if we found 2 points use linear approximation formula below
    if (x_startpoint > 0 && x_endpoint > 0)
        distance = ((y_endpoint - y_startpoint) / (x_endpoint - x_startpoint)) * (x - x_startpoint) + y_startpoint;


    // display distance
    Log.i("CalculateDistance", "distance= " + distance);
    return distance;
}

I have created an issue to track this here: AltBeacon/android-beacon-library#318 as it is more appropriate to be in the repo for the Android Beacon Library.