package org.altbeacon.beacon.distance;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.logging.LogManager;
/**
* This class estimates the distance between the mobile device and a BLE beacon based on the measured
* RSSI and a txPower calibration value that represents the expected RSSI for an iPhone 5 receiving
* the signal when it is 1 meter away.
*
* This class uses a best-fit curve equation with configurable coefficients. The coefficients must
* be supplied by the caller and are specific to the Android device being used. See the
* <code>ModelSpecificDistanceCalculator</code> for more information on the coefficients.
*
* Created by dyoung on 8/28/14.
*/
public class CurveFittedDistanceCalculator implements DistanceCalculator {
public static final String TAG = "CurveFittedDistanceCalculator";
private double mCoefficient1;
private double mCoefficient2;
private double mCoefficient3;
/**
* Construct a calculator with coefficients specific for the device's signal vs. distance
*
* @param coefficient1
* @param coefficient2
* @param coefficient3
*/
public CurveFittedDistanceCalculator(double coefficient1, double coefficient2, double coefficient3) {
mCoefficient1 = coefficient1;
mCoefficient2 = coefficient2;
mCoefficient3 = coefficient3;
}
/**
* Calculated the estimated distance in meters to the beacon based on a reference rssi at 1m
* and the known actual rssi at the current location
*
* @param txPower
* @param rssi
* @return estimated distance
*/
@Override
public double calculateDistance(int txPower, double rssi) {
if (rssi == 0) {
return -1.0; // if we cannot determine accuracy, return -1.
}
LogManager.d(TAG, "calculating distance based on mRssi of %s and txPower of %s", rssi, txPower);
double ratio = rssi*1.0/txPower;
double distance;
if (ratio < 1.0) {
distance = Math.pow(ratio,10);
}
else {
distance = (mCoefficient1)*Math.pow(ratio,mCoefficient2) + mCoefficient3;
}
LogManager.d(TAG, "avg mRssi: %s distance: %s", rssi, distance);
return distance;
}
}