Implement elevation gain via barometer.

This commit is contained in:
Dennis Guse
2020-03-30 20:03:04 +02:00
parent 01ee1a1e49
commit 8a14bc46f6
15 changed files with 480 additions and 36 deletions
@@ -49,6 +49,7 @@ import de.dennisguse.opentracks.content.sensor.SensorDataSet;
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
import de.dennisguse.opentracks.services.handlers.HandlerServer;
import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager;
import de.dennisguse.opentracks.services.sensors.ElevationSumManager;
import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTaskFactory;
import de.dennisguse.opentracks.services.tasks.PeriodicTaskExecutor;
import de.dennisguse.opentracks.stats.TrackStatistics;
@@ -115,6 +116,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
// The following variables are set when recording:
private WakeLock wakeLock;
private BluetoothRemoteSensorManager remoteSensorManager;
private ElevationSumManager elevationSumManager;
private TrackStatisticsUpdater trackStatisticsUpdater;
private TrackPoint lastTrackPoint;
@@ -174,6 +176,11 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
remoteSensorManager = null;
}
if (elevationSumManager != null) {
elevationSumManager.stop(this);
elevationSumManager = null;
}
// Reverse order from onCreate
showNotification(false); //TODO Why?
@@ -371,6 +378,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
// Update instance variables
remoteSensorManager = new BluetoothRemoteSensorManager(this);
remoteSensorManager.start();
elevationSumManager = new ElevationSumManager();
elevationSumManager.start(this);
lastTrackPoint = null;
isIdle = false;
@@ -456,6 +467,11 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
remoteSensorManager.stop();
remoteSensorManager = null;
}
if (elevationSumManager != null) {
elevationSumManager.stop(this);
elevationSumManager = null;
}
lastTrackPoint = null;
handlerServer.stop(this);
@@ -533,6 +549,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
//TODO Figure out how to avoid loading the lastValidTrackPoint from the database
TrackPoint lastValidTrackPoint = getLastValidTrackPointInCurrentSegment(track.getId());
if (elevationSumManager != null) {
trackPoint.setElevationGain(elevationSumManager.getElevationGain_m());
}
//Storing trackPoint
// Always insert the first segment location
@@ -556,15 +576,19 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
insertTrackPoint(track, TrackPoint.createPause());
insertTrackPoint(track, trackPoint);
isIdle = false;
elevationSumManager.reset();
isIdle = false;
lastTrackPoint = trackPoint;
return;
}
if (trackPoint.hasSensorData() || distanceToLastTrackLocation >= recordingDistanceInterval) {
insertTrackPointIfNewer(track, lastTrackPoint);
insertTrackPoint(track, trackPoint);
elevationSumManager.reset();
isIdle = false;
lastTrackPoint = trackPoint;
@@ -573,7 +597,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
if (!isIdle && !TrackPointUtils.isMoving(trackPoint)) {
insertTrackPointIfNewer(track, lastTrackPoint);
insertTrackPoint(track, trackPoint);
elevationSumManager.reset();
isIdle = true;
lastTrackPoint = trackPoint;
@@ -582,7 +609,10 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
if (isIdle && TrackPointUtils.isMoving(trackPoint)) {
insertTrackPointIfNewer(track, lastTrackPoint);
insertTrackPoint(track, trackPoint);
elevationSumManager.reset();
isIdle = false;
lastTrackPoint = trackPoint;
@@ -672,6 +702,17 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
}
}
/**
* Returns the relative elevation gain (since last trackpoint).
*/
Float getElevationGain_m() {
if (elevationSumManager == null || !elevationSumManager.isConnected()) {
return null;
}
return elevationSumManager.getElevationGain_m();
}
private void showNotification(boolean isGpsStarted) {
if (isRecording()) {
Intent intent = IntentUtils.newIntent(this, TrackRecordingActivity.class)
@@ -99,6 +99,11 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco
return trackRecordingService.getSensorDataSet();
}
@Override
public Float getElevationGain_m() {
return trackRecordingService.getElevationGain_m();
}
@VisibleForTesting
@Override
public void setRemoteSensorManager(BluetoothRemoteSensorManager remoteSensorManager) {
@@ -65,12 +65,19 @@ public interface TrackRecordingServiceInterface {
Marker.Id insertMarker(String name, String category, String description, String photoUrl);
/**
* Gets the current sensor data. Returns null if there is no data.
* Gets the current sensor data.
*
* @return SensorDataSet object.
* @return SensorDataSet object or null.
*/
SensorDataSet getSensorData();
/**
* Gets the current elevation gain.
*
* @return elevation gain in m or null.
*/
Float getElevationGain_m();
@VisibleForTesting
void setRemoteSensorManager(BluetoothRemoteSensorManager remoteSensorManager);
@@ -0,0 +1,102 @@
package de.dennisguse.opentracks.services.sensors;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import de.dennisguse.opentracks.util.PressureSensorUtils;
import de.dennisguse.opentracks.util.UnitConversions;
/**
* Estimates the elevation gain and elevation loss using the device's pressure sensor (i.e., barometer).
*/
public class ElevationSumManager implements SensorEventListener {
private static final String TAG = ElevationSumManager.class.getSimpleName();
private static final int SAMPLING_RATE = 3 * (int) UnitConversions.ONE_SECOND_US;
private boolean isConnected = false;
private float lastUsedPressureValue_hPa;
private float elevationGain_m;
private float elevationLoss_m;
public void start(Context context) {
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
Sensor pressureSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
if (pressureSensor == null) {
Log.w(TAG, "No pressure sensor available.");
isConnected = false;
}
isConnected = sensorManager.registerListener(this, pressureSensor, SAMPLING_RATE);
lastUsedPressureValue_hPa = Float.NaN;
reset();
}
public void stop(Context context) {
Log.d(TAG, "Stop");
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
sensorManager.unregisterListener(this);
isConnected = false;
reset();
}
public boolean isConnected() {
return isConnected;
}
public float getElevationGain_m() {
return elevationGain_m;
}
public float getElevationLoss_m() {
return elevationLoss_m;
}
public void reset() {
Log.d(TAG, "Reset");
elevationGain_m = 0;
elevationLoss_m = 0;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
Log.w(TAG, "Sensor accuracy changes are (currently) ignored.");
}
@Override
public void onSensorChanged(SensorEvent event) {
onSensorValueChanged(event.values[0]);
}
@VisibleForTesting
void onSensorValueChanged(float value_hPa) {
if (Float.isNaN(lastUsedPressureValue_hPa)) {
lastUsedPressureValue_hPa = value_hPa;
return;
}
PressureSensorUtils.ElevationChange elevationChange = PressureSensorUtils.computeChanges_m(lastUsedPressureValue_hPa, value_hPa);
if (elevationChange != null) {
if (elevationChange.getElevationChange_m() > 0) {
elevationGain_m += elevationChange.getElevationChange_m();
} else {
elevationLoss_m += elevationChange.getElevationChange_m();
}
lastUsedPressureValue_hPa = elevationChange.getCurrentSensorValue_hPa();
}
Log.v(TAG, "elevation gain: " + elevationGain_m);
}
}