Home » Android » bluetooth lowenergy – Distance calculation from RSSI BLE android

bluetooth lowenergy – Distance calculation from RSSI BLE android

Posted by: admin May 14, 2020 Leave a comment

Questions:

I know there is lot of question on stackoverflow related to my question, but I would like to know if there is any way to get the exact distance from RSSI.

I have followed this link and some other git library methods for distance calculation as well as this tutorial. But I can’t get the correct solution.

This is what I’m using to measure the distance:

protected double calculateDistance(float txPower, double rssi) {

    if (rssi == 0) {
        return -1.0; // if we cannot determine distance, return -1.
    }

    double ratio = rssi * 1.0 / txPower;

    if (ratio < 1.0) {
        return Math.pow(ratio, 10);
    } else {
        double accuracy = (0.89976) * Math.pow(ratio, 7.7095) + 0.111;
        return accuracy;
    }
}

When I call this method I pass the standard and rssi what i’m get from my mLeScanCallBack()

private BluetoothAdapter.LeScanCallback mLeScanCallback =
        new BluetoothAdapter.LeScanCallback() {

            @Override
            public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                        BluetoothDeviceModel bluetoothDeviceModel = new BluetoothDeviceModel(device, rssi);

                        mLeDeviceListAdapter.addDevice(bluetoothDeviceModel, rssi, bluetoothDeviceModel.device.getAddress());
                        mLeDeviceListAdapter.notifyDataSetChanged();

                        if (mapBluetooth != null) {
                            mapBluetooth.put(bluetoothDeviceModel.getDevice().getAddress(), bluetoothDeviceModel);
                            mLeDeviceListAdapter.refresh(mapBluetooth);
                        }
                    }
                });
            }
        };

What Problem i’m facing?

There is nothing wrong with the code above. It gives me the distance but i’m not satisfied with that because it’s not the correct distance. So can anyone tell me if it is possible to get the exact distance with the above method or if there is any other way?

How to&Answers:

I am also working on the same thing. With this method you are able to calculate the distance but that distance is changing frequently. This is because RSSI value is also changing frequently.

What you need to do is to smooth out your result and for that you have to apply Kalman Filter or (linear quadratic estimation). If you want to stick with kalman filter then start from here.
Beacon Tracking

Still I am looking for better implementation of Kalman Filter for my project. Alternatively, you can smooth up your RSSI value

𝑅𝑆𝑆𝐼𝑠𝑚𝑜𝑜𝑡h = 𝛼 ∗ 𝑅𝑆𝑆𝐼𝑛 + (1 − 𝛼) ∗ 𝑅𝑆𝑆𝐼𝑛−1

𝑅𝑆𝑆𝐼𝑛 is the recent 𝑅𝑆𝑆𝐼 value and 𝑅𝑆𝑆𝐼𝑛−1 is the mean 𝑅𝑆𝑆𝐼 value till previous 𝑅𝑆𝑆𝐼.

𝛼 varies from 0 to 1 [consider 𝛼=0.75]

Source :- RSSI Smoothing

Answer:

(Credit:
wouterbulten – kalmanjs – GitHub)

Kalman Filter in Java (used on Android):

private class KalmanFilter implements Serializable {

    private double R;   //  Process Noise
    private double Q;   //  Measurement Noise
    private double A;   //  State Vector
    private double B;   //  Control Vector
    private double C;   //  Measurement Vector

    private Double x;   //  Filtered Measurement Value (No Noise)
    private double cov; //  Covariance

    public KalmanFilter(double r, double q, double a, double b, double c) {
        R = r;
        Q = q;
        A = a;
        B = b;
        C = c;
    }

    public KalmanFilter(double r, double q){
        R = r;
        Q = q;
        A = 1;
        B = 0;
        C = 1;
    }

    /** Public Methods **/
    public double applyFilter(double rssi){
        return applyFilter(rssi, 0.0d);
    }

    /**
     * Filters a measurement
     *
     * @param measurement The measurement value to be filtered
     * @param u The controlled input value
     * @return The filtered value
     */
    public double applyFilter(double measurement, double u) {
        double predX;           //  Predicted Measurement Value
        double K;               //  Kalman Gain
        double predCov;         //  Predicted Covariance
        if (x == null) {
            x = (1 / C) * measurement;
            cov = (1 / C) * Q * (1 / C);
        } else {
            predX = predictValue(u);
            predCov = getUncertainty();
            K = predCov * C * (1 / ((C * predCov * C) + Q));
            x = predX + K * (measurement - (C * predX));
            cov = predCov - (K * C * predCov);
        }
        return x;
    }

    /** Private Methods **/
    private double predictValue(double control){
        return (A * x) + (B * control);
    }

    private double getUncertainty(){
        return ((A * cov) * A) + R;
    }

    @Override
    public String toString() {
        return "KalmanFilter{" +
                "R=" + R +
                ", Q=" + Q +
                ", A=" + A +
                ", B=" + B +
                ", C=" + C +
                ", x=" + x +
                ", cov=" + cov +
                '}';
    }
}

Usage:

private KalmanFilter mKalmanFilter; // Property of your class to store kalman filter values

mKalmanFilter = new KalmanFilter(KALMAN_R, KALMAN_Q); // init Kalman Filter

// Method Apply Filter
private void applyKalmanFilterToRssi(){
     mFilteredRSSI = mKalmanFilter.applyFilter(mRSSI);
}

Constants Values:

// Kalman R & Q
    private static final double KALMAN_R = 0.125d;
    private static final double KALMAN_Q = 0.5d;