From 1a6e67a0d6a96ce1b939552dd51cc335dad3fe63 Mon Sep 17 00:00:00 2001 From: Grishma Date: Tue, 6 Nov 2018 16:23:51 +0530 Subject: [PATCH 1/4] added kalman filter to reduce noice in geo locations --- .../java/com/marianhello/bgloc/Config.java | 18 ++ .../sqlite/SQLiteConfigurationContract.java | 1 + .../data/sqlite/SQLiteConfigurationDAO.java | 6 +- .../bgloc/data/sqlite/SQLiteOpenHelper.java | 3 +- .../ActivityRecognitionLocationProvider.java | 122 +++++++++++++- .../marianhello/bgloc/provider/Tracker1D.java | 158 ++++++++++++++++++ 6 files changed, 298 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/marianhello/bgloc/provider/Tracker1D.java diff --git a/src/main/java/com/marianhello/bgloc/Config.java b/src/main/java/com/marianhello/bgloc/Config.java index db809d0d..39e0beba 100644 --- a/src/main/java/com/marianhello/bgloc/Config.java +++ b/src/main/java/com/marianhello/bgloc/Config.java @@ -63,6 +63,7 @@ public class Config implements Parcelable private HashMap httpHeaders; private Integer maxLocations; private LocationTemplate template; + private Boolean applyKalmanFilter; public Config () { } @@ -95,6 +96,7 @@ public Config(Config config) { if (config.template instanceof AbstractLocationTemplate) { this.template = ((AbstractLocationTemplate)config.template).clone(); } + this.applyKalmanFilter = config.applyKalmanFilter; } private Config(Parcel in) { @@ -123,6 +125,7 @@ private Config(Parcel in) { Bundle bundle = in.readBundle(); setHttpHeaders((HashMap) bundle.getSerializable("httpHeaders")); setTemplate((LocationTemplate) bundle.getSerializable(AbstractLocationTemplate.BUNDLE_KEY)); + setApplyKalmanFilter((Boolean) in.readValue(null)); } public static Config getDefault() { @@ -151,6 +154,7 @@ public static Config getDefault() { config.httpHeaders = null; config.maxLocations = 10000; config.template = null; + config.applyKalmanFilter = true; return config; } @@ -183,6 +187,7 @@ public void writeToParcel(Parcel out, int flags) { out.writeString(getSyncUrl()); out.writeInt(getSyncThreshold()); out.writeInt(getMaxLocations()); + out.writeValue(getApplyKalmanFilter()); Bundle bundle = new Bundle(); bundle.putSerializable("httpHeaders", getHttpHeaders()); bundle.putSerializable(AbstractLocationTemplate.BUNDLE_KEY, (AbstractLocationTemplate) getTemplate()); @@ -520,6 +525,15 @@ public void setTemplate(LocationTemplate template) { this.template = template; } + public boolean hasApplyKalmanFilter() { + return applyKalmanFilter != null; + } + + public void setApplyKalmanFilter(Boolean applyKalmanFilter) { this.applyKalmanFilter = applyKalmanFilter; } + + public Boolean getApplyKalmanFilter() { return applyKalmanFilter; } + + @Override public String toString () { return new StringBuffer() @@ -547,6 +561,7 @@ public String toString () { .append(" httpHeaders=").append(getHttpHeaders().toString()) .append(" maxLocations=").append(getMaxLocations()) .append(" postTemplate=").append(hasTemplate() ? getTemplate().toString() : null) + .append(" applyKalmanFilter=").append(getApplyKalmanFilter()) .append("]") .toString(); } @@ -639,6 +654,9 @@ public static Config merge(Config config1, Config config2) { if (config2.hasTemplate()) { merger.setTemplate(config2.getTemplate()); } + if (config2.hasApplyKalmanFilter()) { + merger.setApplyKalmanFilter(config2.getApplyKalmanFilter()); + } return merger; } diff --git a/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationContract.java b/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationContract.java index bd552956..cb9b4cc5 100644 --- a/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationContract.java +++ b/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationContract.java @@ -35,5 +35,6 @@ public static abstract class ConfigurationEntry implements BaseColumns { public static final String COLUMN_NAME_HEADERS = "http_headers"; public static final String COLUMN_NAME_MAX_LOCATIONS = "max_locations"; public static final String COLUMN_NAME_TEMPLATE = "template"; + public static final String COLUMN_NAME_APPLY_KALMAN_FILTER = "applyKalmanFilter"; } } diff --git a/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationDAO.java b/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationDAO.java index ff04df1a..09c90d86 100644 --- a/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationDAO.java +++ b/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationDAO.java @@ -56,7 +56,8 @@ public Config retrieveConfiguration() throws JSONException { ConfigurationEntry.COLUMN_NAME_SYNC_THRESHOLD, ConfigurationEntry.COLUMN_NAME_HEADERS, ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS, - ConfigurationEntry.COLUMN_NAME_TEMPLATE + ConfigurationEntry.COLUMN_NAME_TEMPLATE, + ConfigurationEntry.COLUMN_NAME_APPLY_KALMAN_FILTER }; String whereClause = null; @@ -123,7 +124,7 @@ private Config hydrate(Cursor c) throws JSONException { config.setHttpHeaders(new JSONObject(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_HEADERS)))); config.setMaxLocations(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS))); config.setTemplate(LocationTemplateFactory.fromJSONString(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_TEMPLATE)))); - + config.setApplyKalmanFilter( (c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_APPLY_KALMAN_FILTER)) == 1) ? true : false ); return config; } @@ -154,6 +155,7 @@ private ContentValues getContentValues(Config config) throws NullPointerExceptio values.put(ConfigurationEntry.COLUMN_NAME_HEADERS, new JSONObject(config.getHttpHeaders()).toString()); values.put(ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS, config.getMaxLocations()); values.put(ConfigurationEntry.COLUMN_NAME_TEMPLATE, config.hasTemplate() ? config.getTemplate().toString() : null); + values.put(ConfigurationEntry.COLUMN_NAME_APPLY_KALMAN_FILTER, (config.getApplyKalmanFilter() == true) ? 1 : 0); return values; } diff --git a/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteOpenHelper.java b/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteOpenHelper.java index b5735b7b..6144d4d7 100644 --- a/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteOpenHelper.java +++ b/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteOpenHelper.java @@ -70,7 +70,8 @@ public class SQLiteOpenHelper extends android.database.sqlite.SQLiteOpenHelper { ConfigurationEntry.COLUMN_NAME_SYNC_THRESHOLD + INTEGER_TYPE + COMMA_SEP + ConfigurationEntry.COLUMN_NAME_HEADERS + TEXT_TYPE + COMMA_SEP + ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS + INTEGER_TYPE + COMMA_SEP + - ConfigurationEntry.COLUMN_NAME_TEMPLATE + TEXT_TYPE + + ConfigurationEntry.COLUMN_NAME_TEMPLATE + TEXT_TYPE + COMMA_SEP + + ConfigurationEntry.COLUMN_NAME_APPLY_KALMAN_FILTER + INTEGER_TYPE + " )"; private static final String SQL_DROP_CONFIG_TABLE = diff --git a/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java b/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java index bfb21998..86d8a1bc 100644 --- a/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java +++ b/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java @@ -18,18 +18,31 @@ import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; -import com.marianhello.bgloc.Config; import com.marianhello.bgloc.data.BackgroundActivity; +import com.marianhello.bgloc.Config; +import com.marianhello.bgloc.data.DAOFactory; +import com.marianhello.bgloc.data.ConfigurationDAO; +import org.json.JSONException; import java.util.ArrayList; public class ActivityRecognitionLocationProvider extends AbstractLocationProvider implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { + private Tracker1D mLatitudeTracker, mLongitudeTracker, mAltitudeTracker; + private boolean mPredicted; + private static final double DEG_TO_METER = 111225.0; + private static final double METER_TO_DEG = 1.0 / DEG_TO_METER; + private static final double TIME_STEP = 1.0; + private static final double COORDINATE_NOISE = 4.0 * METER_TO_DEG; + private static final double ALTITUDE_NOISE = 10.0; + private static final String TAG = ActivityRecognitionLocationProvider.class.getSimpleName(); private static final String P_NAME = " com.marianhello.bgloc"; private static final String DETECTED_ACTIVITY_UPDATE = P_NAME + ".DETECTED_ACTIVITY_UPDATE"; + private ConfigurationDAO configDAO; + private Config config; private GoogleApiClient googleApiClient; private PendingIntent detectedActivitiesPI; @@ -41,13 +54,19 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvide public ActivityRecognitionLocationProvider(Context context) { super(context); + configDAO = DAOFactory.createConfigurationDAO(context); + config = null; + try { + config = configDAO.retrieveConfiguration(); + } catch (JSONException e) { + logger.error("Error retrieving config: {}", e.getMessage()); + } PROVIDER_ID = Config.ACTIVITY_PROVIDER; } @Override public void onCreate() { super.onCreate(); - Intent detectedActivitiesIntent = new Intent(DETECTED_ACTIVITY_UPDATE); detectedActivitiesPI = PendingIntent.getBroadcast(mContext, 9002, detectedActivitiesIntent, PendingIntent.FLAG_UPDATE_CURRENT); registerReceiver(detectedActivitiesReceiver, new IntentFilter(DETECTED_ACTIVITY_UPDATE)); @@ -85,17 +104,106 @@ public boolean isStarted() { @Override public void onLocationChanged(Location location) { logger.debug("Location change: {}", location.toString()); + Location currentLocation = location; + if(config.getApplyKalmanFilter()) { + currentLocation = applyKalmanFilter(location); + } if (lastActivity.getType() == DetectedActivity.STILL) { - handleStationary(location); + handleStationary(currentLocation); stopTracking(); return; } - showDebugToast("acy:" + location.getAccuracy() + ",v:" + location.getSpeed()); + showDebugToast("acy:" + currentLocation.getAccuracy() + ",v:" + currentLocation.getSpeed()); + + lastLocation = currentLocation; + handleLocation(currentLocation); + } + + private Location applyKalmanFilter(Location location) { + final double accuracy = location.getAccuracy(); + double position, noise; + + // Latitude + position = location.getLatitude(); + noise = accuracy * METER_TO_DEG; + if (mLatitudeTracker == null) { + mLatitudeTracker = new Tracker1D(TIME_STEP, COORDINATE_NOISE); + mLatitudeTracker.setState(position, 0.0, noise); + } + + if (!mPredicted) + mLatitudeTracker.predict(0.0); + + mLatitudeTracker.update(position, noise); + + // Longitude + position = location.getLongitude(); + noise = accuracy * Math.cos(Math.toRadians(location.getLatitude())) * METER_TO_DEG ; + + if (mLongitudeTracker == null) { + + mLongitudeTracker = new Tracker1D(TIME_STEP, COORDINATE_NOISE); + mLongitudeTracker.setState(position, 0.0, noise); + } + + if (!mPredicted) + mLongitudeTracker.predict(0.0); + + mLongitudeTracker.update(position, noise); + + // Altitude + if (location.hasAltitude()) { + + position = location.getAltitude(); + noise = accuracy; + + if (mAltitudeTracker == null) { + + mAltitudeTracker = new Tracker1D(TIME_STEP, ALTITUDE_NOISE); + mAltitudeTracker.setState(position, 0.0, noise); + } + + if (!mPredicted) + mAltitudeTracker.predict(0.0); + + mAltitudeTracker.update(position, noise); + } + + // Reset predicted flag + mPredicted = false; + + // Latitude + mLatitudeTracker.predict(0.0); + location.setLatitude(mLatitudeTracker.getPosition()); + + // Longitude + mLongitudeTracker.predict(0.0); + location.setLongitude(mLongitudeTracker.getPosition()); + + // Altitude + if (lastLocation != null && lastLocation.hasAltitude()) { + mAltitudeTracker.predict(0.0); + location.setAltitude(mAltitudeTracker.getPosition()); + } + + // Speed + if (lastLocation != null && lastLocation.hasSpeed()) + location.setSpeed(lastLocation.getSpeed()); + + // Bearing + if (lastLocation != null && lastLocation.hasBearing()) + location.setBearing(lastLocation.getBearing()); + + // Accuracy (always has) + location.setAccuracy((float) (mLatitudeTracker.getAccuracy() * DEG_TO_METER)); + + // Set times + location.setTime(System.currentTimeMillis()); - lastLocation = location; - handleLocation(location); + logger.debug("Location after applying kalman filter: {}", location.toString()); + return location; } public void startTracking() { @@ -262,4 +370,4 @@ public void onDestroy() { unregisterReceiver(detectedActivitiesReceiver); super.onDestroy(); } -} +} \ No newline at end of file diff --git a/src/main/java/com/marianhello/bgloc/provider/Tracker1D.java b/src/main/java/com/marianhello/bgloc/provider/Tracker1D.java new file mode 100644 index 00000000..947c7a6f --- /dev/null +++ b/src/main/java/com/marianhello/bgloc/provider/Tracker1D.java @@ -0,0 +1,158 @@ +package com.marianhello.bgloc.provider; + + +/** + * Kalman filter tracking in one dimension. + */ +class Tracker1D { + + // Settings + + /** + * Time step + */ + private final double mt, mt2, mt2d2, mt3d2, mt4d4; + + /** + * Process noise covariance + */ + private final double mQa, mQb, mQc, mQd; + + /** + * Estimated state + */ + private double mXa, mXb; + + /** + * Estimated covariance + */ + private double mPa, mPb, mPc, mPd; + + /** + * Creates a tracker. + * + * @param timeStep Delta time between predictions. Usefull to calculate speed. + * @param processNoise Standard deviation to calculate noise covariance from. + */ + public Tracker1D(double timeStep, double processNoise) { + + // Lookup time step + mt = timeStep; + mt2 = mt * mt; + mt2d2 = mt2 / 2.0; + mt3d2 = mt2 * mt / 2.0; + mt4d4 = mt2 * mt2 / 4.0; + + // Process noise covariance + double n2 = processNoise * processNoise; + mQa = n2 * mt4d4; + mQb = n2 * mt3d2; + mQc = mQb; + mQd = n2 * mt2; + + // Estimated covariance + mPa = mQa; + mPb = mQb; + mPc = mQc; + mPd = mQd; + } + + /** + * Reset the filter to the given state. + *

+ * Should be called after creation, unless position and velocity are assumed to be both zero. + * + * @param position + * @param velocity + * @param noise + */ + public void setState(double position, double velocity, double noise) { + + // State vector + mXa = position; + mXb = velocity; + + // Covariance + double n2 = noise * noise; + mPa = n2 * mt4d4; + mPb = n2 * mt3d2; + mPc = mPb; + mPd = n2 * mt2; + } + + /** + * Update (correct) with the given measurement. + * + * @param position + * @param noise + */ + public void update(double position, double noise) { + + double r = noise * noise; + + // y = z - H . x + double y = position - mXa; + + // S = H.P.H' + R + double s = mPa + r; + double si = 1.0 / s; + + // K = P.H'.S^(-1) + double Ka = mPa * si; + double Kb = mPc * si; + + // x = x + K.y + mXa = mXa + Ka * y; + mXb = mXb + Kb * y; + + // P = P - K.(H.P) + double Pa = mPa - Ka * mPa; + double Pb = mPb - Ka * mPb; + double Pc = mPc - Kb * mPa; + double Pd = mPd - Kb * mPb; + + mPa = Pa; + mPb = Pb; + mPc = Pc; + mPd = Pd; + } + + /** + * Predict state. + * + * @param acceleration Should be 0 unless there's some sort of control input (a gas pedal, for instance). + */ + public void predict(double acceleration) { + + // x = F.x + G.u + mXa = mXa + mXb * mt + acceleration * mt2d2; + mXb = mXb + acceleration * mt; + + // P = F.P.F' + Q + double Pdt = mPd * mt; + double FPFtb = mPb + Pdt; + double FPFta = mPa + mt * (mPc + FPFtb); + double FPFtc = mPc + Pdt; + double FPFtd = mPd; + + mPa = FPFta + mQa; + mPb = FPFtb + mQb; + mPc = FPFtc + mQc; + mPd = FPFtd + mQd; + } + + /** + * @return Estimated position. + */ + public double getPosition() { return mXa; } + + /** + * @return Estimated velocity. + */ + public double getVelocity() { return mXb; } + + /** + * @return Accuracy + */ + public double getAccuracy() { return Math.sqrt(mPd / mt2); } +} \ No newline at end of file From bf92845968d8d3d49e51e3cac47e938d51624f24 Mon Sep 17 00:00:00 2001 From: Grishma Date: Thu, 8 Nov 2018 18:37:03 +0530 Subject: [PATCH 2/4] added kalman filter to all the providers --- .../provider/AbstractLocationProvider.java | 98 ++++++++++++++++ .../ActivityRecognitionLocationProvider.java | 109 +----------------- .../bgloc/provider/RawLocationProvider.java | 9 +- .../bgloc/DistanceFilterLocationProvider.java | 23 ++-- 4 files changed, 122 insertions(+), 117 deletions(-) diff --git a/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java b/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java index 8b6494ae..b54f7f01 100644 --- a/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java +++ b/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java @@ -41,6 +41,15 @@ public abstract class AbstractLocationProvider implements LocationProvider { private ProviderDelegate mDelegate; + private Tracker1D mLatitudeTracker, mLongitudeTracker, mAltitudeTracker; + private boolean mPredicted; + private static final double DEG_TO_METER = 111225.0; + private static final double METER_TO_DEG = 1.0 / DEG_TO_METER; + private static final double TIME_STEP = 1.0; + private static final double COORDINATE_NOISE = 4.0 * METER_TO_DEG; + private static final double ALTITUDE_NOISE = 10.0; + + protected AbstractLocationProvider(Context context) { mContext = context; logger = LoggerManager.getLogger(getClass()); @@ -169,4 +178,93 @@ protected void playDebugTone (int name) { toneGenerator.startTone(name, duration); } + + /** + * Apply Kalman filter to location as recorder by provider + * @param location + */ + protected Location applyKalmanFilter(Location location) { + final double accuracy = location.getAccuracy(); + double position, noise; + + // Latitude + position = location.getLatitude(); + noise = accuracy * METER_TO_DEG; + if (mLatitudeTracker == null) { + mLatitudeTracker = new Tracker1D(TIME_STEP, COORDINATE_NOISE); + mLatitudeTracker.setState(position, 0.0, noise); + } + + if (!mPredicted) + mLatitudeTracker.predict(0.0); + + mLatitudeTracker.update(position, noise); + + // Longitude + position = location.getLongitude(); + noise = accuracy * Math.cos(Math.toRadians(location.getLatitude())) * METER_TO_DEG ; + + if (mLongitudeTracker == null) { + + mLongitudeTracker = new Tracker1D(TIME_STEP, COORDINATE_NOISE); + mLongitudeTracker.setState(position, 0.0, noise); + } + + if (!mPredicted) + mLongitudeTracker.predict(0.0); + + mLongitudeTracker.update(position, noise); + + // Altitude + if (location.hasAltitude()) { + + position = location.getAltitude(); + noise = accuracy; + + if (mAltitudeTracker == null) { + + mAltitudeTracker = new Tracker1D(TIME_STEP, ALTITUDE_NOISE); + mAltitudeTracker.setState(position, 0.0, noise); + } + + if (!mPredicted) + mAltitudeTracker.predict(0.0); + + mAltitudeTracker.update(position, noise); + } + + // Reset predicted flag + mPredicted = false; + + // Latitude + mLatitudeTracker.predict(0.0); + location.setLatitude(mLatitudeTracker.getPosition()); + + // Longitude + mLongitudeTracker.predict(0.0); + location.setLongitude(mLongitudeTracker.getPosition()); + + // Altitude + if (lastLocation != null && lastLocation.hasAltitude()) { + mAltitudeTracker.predict(0.0); + location.setAltitude(mAltitudeTracker.getPosition()); + } + + // Speed + if (lastLocation != null && lastLocation.hasSpeed()) + location.setSpeed(lastLocation.getSpeed()); + + // Bearing + if (lastLocation != null && lastLocation.hasBearing()) + location.setBearing(lastLocation.getBearing()); + + // Accuracy (always has) + location.setAccuracy((float) (mLatitudeTracker.getAccuracy() * DEG_TO_METER)); + + // Set times + location.setTime(System.currentTimeMillis()); + + logger.debug("Location after applying kalman filter: {}", location.toString()); + return location; + } } diff --git a/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java b/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java index 86d8a1bc..96687672 100644 --- a/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java +++ b/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java @@ -18,10 +18,9 @@ import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; -import com.marianhello.bgloc.data.BackgroundActivity; import com.marianhello.bgloc.Config; -import com.marianhello.bgloc.data.DAOFactory; -import com.marianhello.bgloc.data.ConfigurationDAO; +import com.marianhello.bgloc.data.BackgroundActivity; + import org.json.JSONException; import java.util.ArrayList; @@ -29,20 +28,10 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvider implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { - private Tracker1D mLatitudeTracker, mLongitudeTracker, mAltitudeTracker; - private boolean mPredicted; - private static final double DEG_TO_METER = 111225.0; - private static final double METER_TO_DEG = 1.0 / DEG_TO_METER; - private static final double TIME_STEP = 1.0; - private static final double COORDINATE_NOISE = 4.0 * METER_TO_DEG; - private static final double ALTITUDE_NOISE = 10.0; - private static final String TAG = ActivityRecognitionLocationProvider.class.getSimpleName(); private static final String P_NAME = " com.marianhello.bgloc"; private static final String DETECTED_ACTIVITY_UPDATE = P_NAME + ".DETECTED_ACTIVITY_UPDATE"; - private ConfigurationDAO configDAO; - private Config config; private GoogleApiClient googleApiClient; private PendingIntent detectedActivitiesPI; @@ -54,13 +43,6 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvide public ActivityRecognitionLocationProvider(Context context) { super(context); - configDAO = DAOFactory.createConfigurationDAO(context); - config = null; - try { - config = configDAO.retrieveConfiguration(); - } catch (JSONException e) { - logger.error("Error retrieving config: {}", e.getMessage()); - } PROVIDER_ID = Config.ACTIVITY_PROVIDER; } @@ -105,7 +87,7 @@ public boolean isStarted() { public void onLocationChanged(Location location) { logger.debug("Location change: {}", location.toString()); Location currentLocation = location; - if(config.getApplyKalmanFilter()) { + if(mConfig.getApplyKalmanFilter()) { currentLocation = applyKalmanFilter(location); } @@ -121,91 +103,6 @@ public void onLocationChanged(Location location) { handleLocation(currentLocation); } - private Location applyKalmanFilter(Location location) { - final double accuracy = location.getAccuracy(); - double position, noise; - - // Latitude - position = location.getLatitude(); - noise = accuracy * METER_TO_DEG; - if (mLatitudeTracker == null) { - mLatitudeTracker = new Tracker1D(TIME_STEP, COORDINATE_NOISE); - mLatitudeTracker.setState(position, 0.0, noise); - } - - if (!mPredicted) - mLatitudeTracker.predict(0.0); - - mLatitudeTracker.update(position, noise); - - // Longitude - position = location.getLongitude(); - noise = accuracy * Math.cos(Math.toRadians(location.getLatitude())) * METER_TO_DEG ; - - if (mLongitudeTracker == null) { - - mLongitudeTracker = new Tracker1D(TIME_STEP, COORDINATE_NOISE); - mLongitudeTracker.setState(position, 0.0, noise); - } - - if (!mPredicted) - mLongitudeTracker.predict(0.0); - - mLongitudeTracker.update(position, noise); - - // Altitude - if (location.hasAltitude()) { - - position = location.getAltitude(); - noise = accuracy; - - if (mAltitudeTracker == null) { - - mAltitudeTracker = new Tracker1D(TIME_STEP, ALTITUDE_NOISE); - mAltitudeTracker.setState(position, 0.0, noise); - } - - if (!mPredicted) - mAltitudeTracker.predict(0.0); - - mAltitudeTracker.update(position, noise); - } - - // Reset predicted flag - mPredicted = false; - - // Latitude - mLatitudeTracker.predict(0.0); - location.setLatitude(mLatitudeTracker.getPosition()); - - // Longitude - mLongitudeTracker.predict(0.0); - location.setLongitude(mLongitudeTracker.getPosition()); - - // Altitude - if (lastLocation != null && lastLocation.hasAltitude()) { - mAltitudeTracker.predict(0.0); - location.setAltitude(mAltitudeTracker.getPosition()); - } - - // Speed - if (lastLocation != null && lastLocation.hasSpeed()) - location.setSpeed(lastLocation.getSpeed()); - - // Bearing - if (lastLocation != null && lastLocation.hasBearing()) - location.setBearing(lastLocation.getBearing()); - - // Accuracy (always has) - location.setAccuracy((float) (mLatitudeTracker.getAccuracy() * DEG_TO_METER)); - - // Set times - location.setTime(System.currentTimeMillis()); - - logger.debug("Location after applying kalman filter: {}", location.toString()); - return location; - } - public void startTracking() { if (isTracking) { return; } diff --git a/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java b/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java index fe781d36..96203d21 100644 --- a/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java +++ b/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java @@ -87,8 +87,13 @@ public boolean isStarted() { public void onLocationChanged(Location location) { logger.debug("Location change: {}", location.toString()); - showDebugToast("acy:" + location.getAccuracy() + ",v:" + location.getSpeed()); - handleLocation(location); + Location currentLocation = location; + if(mConfig.getApplyKalmanFilter()) { + currentLocation = applyKalmanFilter(location); + } + + showDebugToast("acy:" + currentLocation.getAccuracy() + ",v:" + currentLocation.getSpeed()); + handleLocation(currentLocation); } @Override diff --git a/src/main/java/com/tenforwardconsulting/bgloc/DistanceFilterLocationProvider.java b/src/main/java/com/tenforwardconsulting/bgloc/DistanceFilterLocationProvider.java index 7426d8a6..cf65f9f6 100644 --- a/src/main/java/com/tenforwardconsulting/bgloc/DistanceFilterLocationProvider.java +++ b/src/main/java/com/tenforwardconsulting/bgloc/DistanceFilterLocationProvider.java @@ -284,16 +284,21 @@ public Location getLastBestLocation() { public void onLocationChanged(Location location) { logger.debug("Location change: {} isMoving={}", location.toString(), isMoving); + Location currentLocation = location; + if(mConfig.getApplyKalmanFilter()) { + currentLocation = applyKalmanFilter(location); + } + if (!isMoving && !isAcquiringStationaryLocation && stationaryLocation==null) { // Perhaps our GPS signal was interupted, re-acquire a stationaryLocation now. setPace(false); } - showDebugToast( "mv:" + isMoving + ",acy:" + location.getAccuracy() + ",v:" + location.getSpeed() + ",df:" + scaledDistanceFilter); + showDebugToast( "mv:" + isMoving + ",acy:" + currentLocation.getAccuracy() + ",v:" + currentLocation.getSpeed() + ",df:" + scaledDistanceFilter); if (isAcquiringStationaryLocation) { - if (stationaryLocation == null || stationaryLocation.getAccuracy() > location.getAccuracy()) { - stationaryLocation = location; + if (stationaryLocation == null || stationaryLocation.getAccuracy() > currentLocation.getAccuracy()) { + stationaryLocation = currentLocation; } if (++locationAcquisitionAttempts == MAX_STATIONARY_ACQUISITION_ATTEMPTS) { isAcquiringStationaryLocation = false; @@ -310,7 +315,7 @@ public void onLocationChanged(Location location) { // Got enough samples, assume we're confident in reported speed now. Play "woohoo" sound. playDebugTone(Tone.DOODLY_DOO); isAcquiringSpeed = false; - scaledDistanceFilter = calculateDistanceFilter(location.getSpeed()); + scaledDistanceFilter = calculateDistanceFilter(currentLocation.getSpeed()); setPace(true); } else { playDebugTone(Tone.BEEP); @@ -320,25 +325,25 @@ public void onLocationChanged(Location location) { playDebugTone(Tone.BEEP); // Only reset stationaryAlarm when accurate speed is detected, prevents spurious locations from resetting when stopped. - if ( (location.getSpeed() >= 1) && (location.getAccuracy() <= mConfig.getStationaryRadius()) ) { + if ( (currentLocation.getSpeed() >= 1) && (currentLocation.getAccuracy() <= mConfig.getStationaryRadius()) ) { resetStationaryAlarm(); } // Calculate latest distanceFilter, if it changed by 5 m/s, we'll reconfigure our pace. - Integer newDistanceFilter = calculateDistanceFilter(location.getSpeed()); + Integer newDistanceFilter = calculateDistanceFilter(currentLocation.getSpeed()); if (newDistanceFilter != scaledDistanceFilter.intValue()) { logger.info("Updating distanceFilter: new={} old={}", newDistanceFilter, scaledDistanceFilter); scaledDistanceFilter = newDistanceFilter; setPace(true); } - if (lastLocation != null && location.distanceTo(lastLocation) < mConfig.getDistanceFilter()) { + if (lastLocation != null && currentLocation.distanceTo(lastLocation) < mConfig.getDistanceFilter()) { return; } } else if (stationaryLocation != null) { return; } // Go ahead and cache, push to server - lastLocation = location; - handleLocation(location); + lastLocation = currentLocation; + handleLocation(currentLocation); } public void resetStationaryAlarm() { From 212c5b9407b00c3b0b2c9ef1b19d5cbcc502246c Mon Sep 17 00:00:00 2001 From: Grishma Date: Thu, 8 Nov 2018 18:39:38 +0530 Subject: [PATCH 3/4] changes --- .../bgloc/provider/ActivityRecognitionLocationProvider.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java b/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java index 96687672..04a1953d 100644 --- a/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java +++ b/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java @@ -21,8 +21,6 @@ import com.marianhello.bgloc.Config; import com.marianhello.bgloc.data.BackgroundActivity; - -import org.json.JSONException; import java.util.ArrayList; public class ActivityRecognitionLocationProvider extends AbstractLocationProvider implements GoogleApiClient.ConnectionCallbacks, From b6f7ae8199efd58883403a59b3743491c14f2d8e Mon Sep 17 00:00:00 2001 From: Grishma Date: Fri, 9 Nov 2018 17:32:22 +0530 Subject: [PATCH 4/4] modified package for filters --- .../bgloc/provider => kalmanFilters}/Tracker1D.java | 2 +- .../marianhello/bgloc/provider/AbstractLocationProvider.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename src/main/java/com/{marianhello/bgloc/provider => kalmanFilters}/Tracker1D.java (98%) diff --git a/src/main/java/com/marianhello/bgloc/provider/Tracker1D.java b/src/main/java/com/kalmanFilters/Tracker1D.java similarity index 98% rename from src/main/java/com/marianhello/bgloc/provider/Tracker1D.java rename to src/main/java/com/kalmanFilters/Tracker1D.java index 947c7a6f..26bb37ba 100644 --- a/src/main/java/com/marianhello/bgloc/provider/Tracker1D.java +++ b/src/main/java/com/kalmanFilters/Tracker1D.java @@ -1,4 +1,4 @@ -package com.marianhello.bgloc.provider; +package com.kalmanFilters; /** diff --git a/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java b/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java index b54f7f01..fed45c99 100644 --- a/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java +++ b/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java @@ -26,6 +26,7 @@ import com.marianhello.bgloc.data.BackgroundLocation; import com.marianhello.logging.LoggerManager; import com.marianhello.utils.Tone; +import com.kalmanFilters.Tracker1D; /** * AbstractLocationProvider