Replace high/low accuracy with omit rests option.

I have been feeling that the high/low accuracy switch is a bit
misleading because while it can help us choose waypoints that
are sufficiently far apart from each other, the accuracy of any
individual waypoint isn't inherently better than normal. However,
the option to omit or keep rests allows the user to keep the raw
data or postprocess it in their own way; or accept the default
different-enough detection.
This commit is contained in:
voussoir 2022-04-02 21:45:25 -07:00
parent 981e8806b1
commit 3741d0baf5
No known key found for this signature in database
GPG key ID: 5F7554F8C26DACCB
7 changed files with 41 additions and 35 deletions

View file

@ -56,7 +56,7 @@ object Keys {
const val PREF_TRACKING_STATE: String = "prefTrackingState" const val PREF_TRACKING_STATE: String = "prefTrackingState"
const val PREF_USE_IMPERIAL_UNITS: String = "prefUseImperialUnits" const val PREF_USE_IMPERIAL_UNITS: String = "prefUseImperialUnits"
const val PREF_GPS_ONLY: String = "prefGpsOnly" const val PREF_GPS_ONLY: String = "prefGpsOnly"
const val PREF_RECORDING_ACCURACY_HIGH: String = "prefRecordingAccuracyHigh" const val PREF_OMIT_RESTS: String = "prefOmitRests"
const val PREF_ALTITUDE_SMOOTHING_VALUE: String = "prefAltitudeSmoothingValue" const val PREF_ALTITUDE_SMOOTHING_VALUE: String = "prefAltitudeSmoothingValue"
const val PREF_LOCATION_ACCURACY_THRESHOLD: String = "prefLocationAccuracyThreshold" const val PREF_LOCATION_ACCURACY_THRESHOLD: String = "prefLocationAccuracyThreshold"
const val PREF_LOCATION_AGE_THRESHOLD: String = "prefLocationAgeThreshold" const val PREF_LOCATION_AGE_THRESHOLD: String = "prefLocationAgeThreshold"

View file

@ -65,6 +65,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
// set up "Restrict to GPS" preference // set up "Restrict to GPS" preference
val preferenceGpsOnly: SwitchPreferenceCompat = SwitchPreferenceCompat(activity as Context) val preferenceGpsOnly: SwitchPreferenceCompat = SwitchPreferenceCompat(activity as Context)
preferenceGpsOnly.isSingleLineTitle = false
preferenceGpsOnly.title = getString(R.string.pref_gps_only_title) preferenceGpsOnly.title = getString(R.string.pref_gps_only_title)
preferenceGpsOnly.setIcon(R.drawable.ic_gps_24dp) preferenceGpsOnly.setIcon(R.drawable.ic_gps_24dp)
preferenceGpsOnly.key = Keys.PREF_GPS_ONLY preferenceGpsOnly.key = Keys.PREF_GPS_ONLY
@ -74,6 +75,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
// set up "Use Imperial Measurements" preference // set up "Use Imperial Measurements" preference
val preferenceImperialMeasurementUnits: SwitchPreferenceCompat = SwitchPreferenceCompat(activity as Context) val preferenceImperialMeasurementUnits: SwitchPreferenceCompat = SwitchPreferenceCompat(activity as Context)
preferenceImperialMeasurementUnits.isSingleLineTitle = false
preferenceImperialMeasurementUnits.title = getString(R.string.pref_imperial_measurement_units_title) preferenceImperialMeasurementUnits.title = getString(R.string.pref_imperial_measurement_units_title)
preferenceImperialMeasurementUnits.setIcon(R.drawable.ic_square_foot_24px) preferenceImperialMeasurementUnits.setIcon(R.drawable.ic_square_foot_24px)
preferenceImperialMeasurementUnits.key = Keys.PREF_USE_IMPERIAL_UNITS preferenceImperialMeasurementUnits.key = Keys.PREF_USE_IMPERIAL_UNITS
@ -110,13 +112,15 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
} }
// set up "Recording Accuracy" preference // set up "Recording Accuracy" preference
val preferenceRecordingAccuracy: SwitchPreferenceCompat = SwitchPreferenceCompat(activity as Context) val DEFAULT_OMIT_RESTS = true
preferenceRecordingAccuracy.title = getString(R.string.pref_recording_accuracy_title) val preferenceOmitRests: SwitchPreferenceCompat = SwitchPreferenceCompat(activity as Context)
preferenceRecordingAccuracy.setIcon(R.drawable.ic_timeline_24dp) preferenceOmitRests.isSingleLineTitle = false
preferenceRecordingAccuracy.key = Keys.PREF_RECORDING_ACCURACY_HIGH preferenceOmitRests.title = getString(R.string.pref_omit_rests_title)
preferenceRecordingAccuracy.summaryOn = getString(R.string.pref_recording_accuracy_summary_high) preferenceOmitRests.setIcon(R.drawable.ic_timeline_24dp)
preferenceRecordingAccuracy.summaryOff = getString(R.string.pref_recording_accuracy_summary_default) preferenceOmitRests.key = Keys.PREF_OMIT_RESTS
preferenceRecordingAccuracy.setDefaultValue(false) preferenceOmitRests.summaryOn = getString(R.string.pref_omit_rests_on)
preferenceOmitRests.summaryOff = getString(R.string.pref_omit_rests_off)
preferenceOmitRests.setDefaultValue(DEFAULT_OMIT_RESTS)
// set up "Altitude Smoothing" preference // set up "Altitude Smoothing" preference
// val preferenceAltitudeSmoothingValue: SeekBarPreference = SeekBarPreference(activity as Context) // val preferenceAltitudeSmoothingValue: SeekBarPreference = SeekBarPreference(activity as Context)
@ -136,8 +140,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
preferenceResetAdvanced.setIcon(R.drawable.ic_undo_24dp) preferenceResetAdvanced.setIcon(R.drawable.ic_undo_24dp)
preferenceResetAdvanced.summary = getString(R.string.pref_reset_advanced_summary) preferenceResetAdvanced.summary = getString(R.string.pref_reset_advanced_summary)
preferenceResetAdvanced.setOnPreferenceClickListener{ preferenceResetAdvanced.setOnPreferenceClickListener{
// reset "Recording Accuracy" preference preferenceOmitRests.isChecked = DEFAULT_OMIT_RESTS
preferenceRecordingAccuracy.isChecked = false
// preferenceAltitudeSmoothingValue.value = Keys.DEFAULT_ALTITUDE_SMOOTHING_VALUE // preferenceAltitudeSmoothingValue.value = Keys.DEFAULT_ALTITUDE_SMOOTHING_VALUE
return@setOnPreferenceClickListener true return@setOnPreferenceClickListener true
} }
@ -168,7 +171,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
val preferenceCategoryAdvanced: PreferenceCategory = PreferenceCategory(activity as Context) val preferenceCategoryAdvanced: PreferenceCategory = PreferenceCategory(activity as Context)
preferenceCategoryAdvanced.title = getString(R.string.pref_advanced_title) preferenceCategoryAdvanced.title = getString(R.string.pref_advanced_title)
preferenceCategoryAdvanced.contains(preferenceRecordingAccuracy) preferenceCategoryAdvanced.contains(preferenceOmitRests)
// preferenceCategoryAdvanced.contains(preferenceAltitudeSmoothingValue) // preferenceCategoryAdvanced.contains(preferenceAltitudeSmoothingValue)
preferenceCategoryAdvanced.contains(preferenceResetAdvanced) preferenceCategoryAdvanced.contains(preferenceResetAdvanced)
@ -184,7 +187,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
screen.addPreference(preferenceCategoryMaintenance) screen.addPreference(preferenceCategoryMaintenance)
screen.addPreference(preferenceDeleteNonStarred) screen.addPreference(preferenceDeleteNonStarred)
screen.addPreference(preferenceCategoryAdvanced) screen.addPreference(preferenceCategoryAdvanced)
screen.addPreference(preferenceRecordingAccuracy) screen.addPreference(preferenceOmitRests)
// screen.addPreference(preferenceAltitudeSmoothingValue) // screen.addPreference(preferenceAltitudeSmoothingValue)
screen.addPreference(preferenceResetAdvanced) screen.addPreference(preferenceResetAdvanced)
screen.addPreference(preferenceCategoryAbout) screen.addPreference(preferenceCategoryAbout)

View file

@ -57,7 +57,7 @@ class TrackerService: Service(), SensorEventListener {
var networkProviderActive: Boolean = false var networkProviderActive: Boolean = false
var useImperial: Boolean = false var useImperial: Boolean = false
var gpsOnly: Boolean = false var gpsOnly: Boolean = false
var accuracyMultiplier: Int = 1 var omitRests: Boolean = true
var currentBestLocation: Location = LocationHelper.getDefaultLocation() var currentBestLocation: Location = LocationHelper.getDefaultLocation()
var lastSave: Date = Keys.DEFAULT_DATE var lastSave: Date = Keys.DEFAULT_DATE
var stepCountOffset: Float = 0f var stepCountOffset: Float = 0f
@ -81,7 +81,7 @@ class TrackerService: Service(), SensorEventListener {
super.onCreate() super.onCreate()
gpsOnly = PreferencesHelper.loadGpsOnly() gpsOnly = PreferencesHelper.loadGpsOnly()
useImperial = PreferencesHelper.loadUseImperialUnits() useImperial = PreferencesHelper.loadUseImperialUnits()
accuracyMultiplier = PreferencesHelper.loadAccuracyMultiplier() omitRests = PreferencesHelper.loadOmitRests()
locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager
@ -438,8 +438,8 @@ class TrackerService: Service(), SensorEventListener {
useImperial = PreferencesHelper.loadUseImperialUnits() useImperial = PreferencesHelper.loadUseImperialUnits()
} }
// preference "Recording Accuracy" // preference "Recording Accuracy"
Keys.PREF_RECORDING_ACCURACY_HIGH -> { Keys.PREF_OMIT_RESTS -> {
accuracyMultiplier = PreferencesHelper.loadAccuracyMultiplier() omitRests = PreferencesHelper.loadOmitRests()
} }
} }
} }
@ -463,7 +463,7 @@ class TrackerService: Service(), SensorEventListener {
private val periodicTrackUpdate: Runnable = object : Runnable { private val periodicTrackUpdate: Runnable = object : Runnable {
override fun run() { override fun run() {
// add waypoint to track - step count is continuously updated in onSensorChanged // add waypoint to track - step count is continuously updated in onSensorChanged
val result: Pair<Boolean, Track> = TrackHelper.addWayPointToTrack(track, currentBestLocation, accuracyMultiplier, resumed) val result: Pair<Boolean, Track> = TrackHelper.addWayPointToTrack(track, currentBestLocation, omitRests, resumed)
// get results // get results
val successfullyAdded: Boolean = result.first val successfullyAdded: Boolean = result.first
track = result.second track = result.second

View file

@ -178,10 +178,17 @@ object LocationHelper {
/* Checks if given location is different enough compared to previous location */ /* Checks if given location is different enough compared to previous location */
fun isDifferentEnough(previousLocation: Location?, location: Location, accuracyMultiplier: Int): Boolean { fun isDifferentEnough(previousLocation: Location?, location: Location, omitRests: Boolean): Boolean {
// check if previous location is (not) available // check if previous location is (not) available
if (previousLocation == null) return true if (previousLocation == null)
{
return true
}
if (! omitRests)
{
return true
}
// location.accuracy is given as 1 standard deviation, with a 68% chance // location.accuracy is given as 1 standard deviation, with a 68% chance
// that the true position is within a circle of this radius. // that the true position is within a circle of this radius.
// These formulas determine if the difference between the last point and // These formulas determine if the difference between the last point and
@ -194,7 +201,7 @@ object LocationHelper {
// With 1*accuracyDelta we have 68% confidence that the points are // With 1*accuracyDelta we have 68% confidence that the points are
// different. We can multiply this number to increase confidence but // different. We can multiply this number to increase confidence but
// decrease point recording frequency if needed. // decrease point recording frequency if needed.
return distance > accuracyDelta * accuracyMultiplier return distance > accuracyDelta
} }

View file

@ -101,16 +101,10 @@ object PreferencesHelper {
// return sharedPreferences.getBoolean(Keys.PREF_RECORDING_ACCURACY_HIGH, false) // return sharedPreferences.getBoolean(Keys.PREF_RECORDING_ACCURACY_HIGH, false)
// } // }
fun loadOmitRests(): Boolean {
/* Loads current accuracy multiplier */ return sharedPreferences.getBoolean(Keys.PREF_OMIT_RESTS, true)
fun loadAccuracyMultiplier(): Int {
// load current setting
val recordingAccuracyHigh: Boolean = sharedPreferences.getBoolean(Keys.PREF_RECORDING_ACCURACY_HIGH, false)
// return multiplier based on state
return if (recordingAccuracyHigh) 2 else 1
} }
// /* Load altitude smoothing value */ // /* Load altitude smoothing value */
// fun loadAltitudeSmoothingValue(): Int { // fun loadAltitudeSmoothingValue(): Int {
// // load current setting // // load current setting

View file

@ -41,7 +41,7 @@ object TrackHelper {
private val TAG: String = LogHelper.makeLogTag(TrackHelper::class.java) private val TAG: String = LogHelper.makeLogTag(TrackHelper::class.java)
/* Adds given locatiom as waypoint to track */ /* Adds given locatiom as waypoint to track */
fun addWayPointToTrack(track: Track, location: Location, accuracyMultiplier: Int, resumed: Boolean): Pair<Boolean, Track> { fun addWayPointToTrack(track: Track, location: Location, omitRests: Boolean, resumed: Boolean): Pair<Boolean, Track> {
// Step 1: Get previous location // Step 1: Get previous location
val previousLocation: Location? val previousLocation: Location?
var numberOfWayPoints: Int = track.wayPoints.size var numberOfWayPoints: Int = track.wayPoints.size
@ -68,9 +68,11 @@ object TrackHelper {
track.recordingStop = now track.recordingStop = now
// Step 3: Add waypoint, ifrecent and accurate and different enough // Step 3: Add waypoint, ifrecent and accurate and different enough
val shouldBeAdded: Boolean = (LocationHelper.isRecentEnough(location) && val shouldBeAdded: Boolean = (
LocationHelper.isRecentEnough(location) &&
LocationHelper.isAccurateEnough(location, Keys.DEFAULT_THRESHOLD_LOCATION_ACCURACY) && LocationHelper.isAccurateEnough(location, Keys.DEFAULT_THRESHOLD_LOCATION_ACCURACY) &&
LocationHelper.isDifferentEnough(previousLocation, location, accuracyMultiplier)) LocationHelper.isDifferentEnough(previousLocation, location, omitRests)
)
if (shouldBeAdded) { if (shouldBeAdded) {
// Step 3.1: Update distance (do not update if resumed -> we do not want to add values calculated during a recording pause) // Step 3.1: Update distance (do not update if resumed -> we do not want to add values calculated during a recording pause)
if (!resumed) { if (!resumed) {

View file

@ -96,9 +96,9 @@
<string name="pref_imperial_measurement_units_summary_metric">Currently using metric units (Kilometer, Meter).</string> <string name="pref_imperial_measurement_units_summary_metric">Currently using metric units (Kilometer, Meter).</string>
<string name="pref_imperial_measurement_units_summary_imperial">Currently using imperial units (Miles, Feet).</string> <string name="pref_imperial_measurement_units_summary_imperial">Currently using imperial units (Miles, Feet).</string>
<string name="pref_imperial_measurement_units_title">Use Imperial Measurements</string> <string name="pref_imperial_measurement_units_title">Use Imperial Measurements</string>
<string name="pref_recording_accuracy_summary_high">Waypoints have higher accuracy but are less frequent.</string> <string name="pref_omit_rests_on">Waypoints will not be recorded if they are too close to the previous waypoint.</string>
<string name="pref_recording_accuracy_summary_default">Waypoints have lower accuracy but are more frequent.</string> <string name="pref_omit_rests_off">All waypoints will be recorded, even while standing still.</string>
<string name="pref_recording_accuracy_title">Recording Accuracy</string> <string name="pref_omit_rests_title">Omit points during rests</string>
<string name="pref_report_issue_summary">Report bugs and suggest improvements on GitHub.</string> <string name="pref_report_issue_summary">Report bugs and suggest improvements on GitHub.</string>
<string name="pref_report_issue_title">Report Issue</string> <string name="pref_report_issue_title">Report Issue</string>
<string name="pref_reset_advanced_summary">Reset advanced settings to defaults.</string> <string name="pref_reset_advanced_summary">Reset advanced settings to defaults.</string>