Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize Location Logging #403

Closed
shrix opened this issue Apr 8, 2020 · 3 comments
Closed

Optimize Location Logging #403

shrix opened this issue Apr 8, 2020 · 3 comments
Labels
High Priority High importance / High value

Comments

@shrix
Copy link

shrix commented Apr 8, 2020

We could optimize location logs in order to save phone's battery consumption, and efficiently log user movements for further analysis. We introduce step-1 as given below, while step-2 could be present in the implementation.

[1] Subscribe to accelerometer sensor events going beyond certain threshold value
[2] Log the location value at that given instance

Thus replacing "periodic wakelocks" being done every 5 minutes - the reason for fast power drain!

Reference for implementing on Android, using the SensorEvent API:

https://developer.android.com/reference/android/hardware/SensorEvent
Could base it on activities performed, using Activity Recognition API:
https://developers.google.com/location-context/activity-recognition

And likewise on the iOS.

@vitorpamplona vitorpamplona added For next release High Priority High importance / High value and removed For next release labels Apr 8, 2020
@JohnPalmer
Copy link

I spent a lot of time a few years ago thinking about how to optimize location logging and the solution I came up with was to (1 set) a minimum accuracy threshold and an optimum accuracy threshold, (2) run the location listener for different lengths of time depending on which threshold is reached and how many previous locations have been missed because the minimum threshold could not be reached. The basic idea is that you turn on the listener and start looking at the locations it returns. If you get a location within the optimal accuracy you use that and switch the listener off. If not, you keep listening for up to a predefined "normal" listening time and if you never hit the optimal accuracy within that time you take the best accuracy that is within the minimal threshold. If no location is within the minimal threshold, then you don't take anything and mark it as a missed location and move on to the next fix time. After a certain number of locations are marked as "missed" in a row, then the next time the listener is run you let it run for the "long" listening time. But if it keeps missing it, you go back to the "normal" time. (This is because the user could be in some place where there is simply no network or GPS signal and you don't want to keep draining the battery with long listening times in that case. I did not use the accelerometer approach you are proposing but I could see combining the two approaches.

All of my code that I am describing is here, and the key part is:

  /**
     * Inner class to listen to LocationManager. <br>
     * Defines LocationListener behavior.
     */
    private class mLocationListener implements LocationListener {

        /**
         * Defines LocationListener behavior upon reception of a location fix
         * update from the LocationManager.
         */
        public void onLocationChanged(Location location) {

            Context context = getApplicationContext();

            // Quick return if given location is null or has an invalid time
            if ((location == null) || (location.getTime() < 0)
                    || ((location.getProvider() == "gps"))) {

                // Log.e(TAG, "garbage fix");
                return;
            } else {
                // Log.e(TAG, "not garbage");
                // Log.e(TAG, "accuracy=" + location.getAccuracy());

                // if the location is within the optimum accuracy (for either
                // normal or long runs),
                // then use it and stop.
                if ((location.getAccuracy() <= Util.OPT_ACCURACY || (Util.missedFixes > 0 && location
                        .getAccuracy() < Util.OPT_ACCURACY_LONGRUNS))) {

                    // Log.e(TAG, "locloop1");

                    useFix(context, location);

                    removeLocationUpdates();

                    // try {
                    // unregisterReceiver(stopReceiver);
                    // } catch (Exception e) {
                    // Log.e(TAG, "exception" + e);
                    // }

                    fixInProgress = false;

                    stopSelf();
                } else {

                    // Log.e(TAG, "locloop2");

                    // if no best location set yet, current location is best
                    if (bestLocation == null) {
                        // Log.e(TAG, "locloop3");

                        bestLocation = location;

                        return;
                        // current and best location are gps, use for new bets
                        // whichever is better
                    } else if (location.getProvider() == "gps"
                            && bestLocation.getProvider() == "gps"
                            && location.getAccuracy() < bestLocation
                            .getAccuracy()) {
                        // Log.e(TAG, "locloop4");

                        bestLocation = location;

                        return;

                        // if current location is gps and best location is
                        // network,
                        // use gps for new best if it is below the minimum gps
                        // accuracy or better than current
                    } else if (location.getProvider() == "gps"
                            && bestLocation.getProvider() == "network"
                            && (location.getAccuracy() <= Util.MIN_GPS_ACCURACY || location
                            .getAccuracy() < bestLocation.getAccuracy())) {
                        // Log.e(TAG, "locloop5");
                        bestLocation = location;

                        return;

                        // if current location is network and best is network,
                        // use
                        // for new best whichever is better
                    } else if (location.getProvider() == "network"
                            && bestLocation.getProvider() == "network"
                            && location.getAccuracy() < location.getAccuracy()) {
                        // Log.e(TAG, "locloop6");

                        bestLocation = location;

                        return;

                        // if current location is network and best is gps, use
                        // current as new best if gps accuracy is above the
                        // minimum threshhold or is better than network
                    } else if (location.getProvider() == "network"
                            && bestLocation.getProvider() == "gps"
                            && (bestLocation.getAccuracy() > Util.MIN_GPS_ACCURACY || location
                            .getAccuracy() < bestLocation.getAccuracy())) {
                        // Log.e(TAG, "locloop7");

                        bestLocation = location;

                        return;
                    } else
                        // if none of these conditions are met, then return and
                        // keep trying
                        // Log.e(TAG, "locloop8");

                        return;
                }
            }
        }

@shrix
Copy link
Author

shrix commented Apr 11, 2020

If user activities were regular in nature, we could have taken the approach of thresholds on the wakelocks itself. Since in our context, the activities of a user could be quite irregular, I introduced an event-based mechanism to optimize on it. Also the sensor we use, is a simple one, and found in almost all of the phones.

The advantage of having thresholds set over these sensor values would help filter the insignificant movements of a user, thus avoiding any false positives. Of course, identifying an optimal threshold value could be tricky, and as you rightly pointed, we may need to analyze the best possible values for the same.

As you might have observed from the Sensor reference (of Android), we could perhaps use the following parameters ...

Event     :  TYPE_ACCELEROMETER
Threshold :  TYPE_SIGNIFICANT_MOTION

Activity Recognition APIs may need to be evaluated, and decide if they provide a better option. Also considering the resources that it may consume, and if it has any restrictions as compared to the one above.

@Patrick-Erichsen
Copy link
Contributor

Closing this issue out as we have taken it into consideration and documented the feedback on this page in Jira.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
High Priority High importance / High value
Projects
None yet
Development

No branches or pull requests

4 participants