Barometer: use sensor aggregator.

Part of #1424.
This commit is contained in:
Dennis Guse
2023-11-15 21:28:20 +01:00
parent 5c7731bb1f
commit 8d5a7e7e8b
13 changed files with 235 additions and 245 deletions
@@ -0,0 +1,3 @@
package de.dennisguse.opentracks.data.models;
public record AltitudeGainLoss(float gain_m, float loss_m) {}
@@ -1,108 +0,0 @@
package de.dennisguse.opentracks.sensors;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.driver.BarometerInternal;
/**
* Estimates the altitude gain and altitude loss using the device's pressure sensor (i.e., barometer).
*/
public class AltitudeSumManager implements SensorConnector {
private static final String TAG = AltitudeSumManager.class.getSimpleName();
private final BarometerInternal driver;
private AtmosphericPressure lastAcceptedSensorValue;
private AtmosphericPressure lastSeenSensorValue;
private Float altitudeGain_m;
private Float altitudeLoss_m;
public AltitudeSumManager() {
driver = new BarometerInternal();
}
@VisibleForTesting
public AltitudeSumManager(BarometerInternal mock) {
this.driver = mock;
}
public void start(Context context, Handler handler) {
driver.connect(context, handler, this);
lastAcceptedSensorValue = null;
reset();
}
public void stop(Context context) {
Log.d(TAG, "Stop");
driver.disconnect(context);
reset();
}
public void fill(@NonNull TrackPoint trackPoint) {
trackPoint.setAltitudeGain(altitudeGain_m);
trackPoint.setAltitudeLoss(altitudeLoss_m);
}
@Nullable
public Float getAltitudeGain_m() {
return driver.isConnected() ? altitudeGain_m : null;
}
@VisibleForTesting
public void setAltitudeGain_m(float altitudeGain_m) {
this.altitudeGain_m = altitudeGain_m;
}
@Nullable
public Float getAltitudeLoss_m() {
return driver.isConnected() ? altitudeLoss_m : null;
}
@VisibleForTesting
public void setAltitudeLoss_m(float altitudeLoss_m) {
this.altitudeLoss_m = altitudeLoss_m;
}
public void reset() {
Log.d(TAG, "Reset");
altitudeGain_m = null;
altitudeLoss_m = null;
}
public void onSensorValueChanged(AtmosphericPressure currentSensorValue) {
if (lastAcceptedSensorValue == null) {
lastAcceptedSensorValue = currentSensorValue;
lastSeenSensorValue = currentSensorValue;
return;
}
altitudeGain_m = altitudeGain_m != null ? altitudeGain_m : 0;
altitudeLoss_m = altitudeLoss_m != null ? altitudeLoss_m : 0;
PressureSensorUtils.AltitudeChange altitudeChange = PressureSensorUtils.computeChangesWithSmoothing_m(lastAcceptedSensorValue, lastSeenSensorValue, currentSensorValue);
if (altitudeChange != null) {
altitudeGain_m += altitudeChange.getAltitudeGain_m();
altitudeLoss_m += altitudeChange.getAltitudeLoss_m();
lastAcceptedSensorValue = altitudeChange.currentSensorValue();
}
lastSeenSensorValue = currentSensorValue;
Log.v(TAG, "altitude gain: " + altitudeGain_m + ", altitude loss: " + altitudeLoss_m);
}
}
@@ -0,0 +1,46 @@
package de.dennisguse.opentracks.sensors;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
import de.dennisguse.opentracks.sensors.driver.BarometerInternal;
import de.dennisguse.opentracks.sensors.sensorData.AggregatorBarometer;
import de.dennisguse.opentracks.sensors.sensorData.Raw;
/**
* Estimates the altitude gain and altitude loss using the device's pressure sensor (i.e., barometer).
*/
public class GainManager implements SensorConnector {
private static final String TAG = GainManager.class.getSimpleName();
private final BarometerInternal driver;
private final SensorManager.SensorDataChangedObserver listener;
public GainManager(SensorManager.SensorDataChangedObserver listener) {
this.listener = listener;
driver = new BarometerInternal();
}
public void start(Context context, Handler handler) {
driver.connect(context, handler, this);
if (driver.isConnected()) {
listener.onConnect(new AggregatorBarometer("internal"));
}
}
public void stop(Context context) {
Log.d(TAG, "Stop");
driver.disconnect(context);
listener.onDisconnect(new AggregatorBarometer("internal"));
}
public void onSensorValueChanged(AtmosphericPressure currentSensorValue) {
listener.onChange(new Raw<>(currentSensorValue));
}
}
@@ -48,7 +48,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
private BluetoothRemoteSensorManager bluetoothSensorManager;
private AltitudeSumManager altitudeSumManager;
private GainManager altitudeSumManager;
private GPSManager gpsManager;
@@ -58,7 +58,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
public void start(Context context, Handler handler) {
gpsManager = new GPSManager(observer); //TODO Pass listener
altitudeSumManager = new AltitudeSumManager();
altitudeSumManager = new GainManager(listener);
bluetoothSensorManager = new BluetoothRemoteSensorManager(context, handler, listener);
onSharedPreferenceChanged(null, null);
@@ -82,7 +82,6 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
}
public SensorDataSet fill(TrackPoint trackPoint) {
altitudeSumManager.fill(trackPoint);
sensorDataSet.fillTrackPoint(trackPoint);
return new SensorDataSet(sensorDataSet);
}
@@ -93,7 +92,6 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
return;
}
sensorDataSet.reset();
altitudeSumManager.reset();
}
@Deprecated
@@ -108,13 +106,13 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
@Deprecated
@VisibleForTesting
public AltitudeSumManager getAltitudeSumManager() {
public GainManager getAltitudeSumManager() {
return altitudeSumManager;
}
@Deprecated
@VisibleForTesting
public void setAltitudeSumManager(AltitudeSumManager altitudeSumManager) {
public void setAltitudeSumManager(GainManager altitudeSumManager) {
this.altitudeSumManager = altitudeSumManager;
}
@@ -11,7 +11,7 @@ import android.util.Log;
import java.util.concurrent.TimeUnit;
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
import de.dennisguse.opentracks.sensors.AltitudeSumManager;
import de.dennisguse.opentracks.sensors.GainManager;
public class BarometerInternal {
@@ -19,7 +19,7 @@ public class BarometerInternal {
private static final int SAMPLING_PERIOD = (int) TimeUnit.SECONDS.toMicros(5);
private AltitudeSumManager observer;
private GainManager observer;
private final SensorEventListener listener = new SensorEventListener() {
@Override
@@ -38,14 +38,13 @@ public class BarometerInternal {
}
};
public void connect(Context context, Handler handler, AltitudeSumManager observer) {
public void connect(Context context, Handler handler, GainManager observer) {
this.observer = observer;
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.");
this.observer = null;
return;
}
if (sensorManager.registerListener(listener, pressureSensor, SAMPLING_PERIOD, handler)) {
@@ -0,0 +1,46 @@
package de.dennisguse.opentracks.sensors.sensorData;
import androidx.annotation.NonNull;
import de.dennisguse.opentracks.data.models.Altitude;
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
import de.dennisguse.opentracks.sensors.PressureSensorUtils;
public class AggregatorBarometer extends Aggregator<AtmosphericPressure, AltitudeGainLoss> {
private AtmosphericPressure lastAcceptedSensorValue;
public AggregatorBarometer(String sensorAddress) {
super(sensorAddress);
}
@Override
protected void computeValue(Raw<AtmosphericPressure> current) {
if (previous == null) {
lastAcceptedSensorValue = current.value();
value = getNoneValue();
return;
}
PressureSensorUtils.AltitudeChange altitudeChange = PressureSensorUtils.computeChangesWithSmoothing_m(lastAcceptedSensorValue, previous.value(), current.value());
if (altitudeChange != null) {
value = new AltitudeGainLoss(value.gain_m() + altitudeChange.getAltitudeGain_m(), value.loss_m() + altitudeChange.getAltitudeLoss_m());
lastAcceptedSensorValue = altitudeChange.currentSensorValue();
}
}
@NonNull
@Override
protected AltitudeGainLoss getNoneValue() {
return new AltitudeGainLoss(0f, 0f);
}
@Override
public void reset() {
value = getNoneValue();
}
public record Data(Altitude gain, Altitude loss) {}
}
@@ -1,11 +1,13 @@
package de.dennisguse.opentracks.sensors.sensorData;
import android.util.Log;
import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
import de.dennisguse.opentracks.data.models.Cadence;
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Power;
@@ -36,6 +38,9 @@ public final class SensorDataSet {
@VisibleForTesting
public AggregatorRunning runningDistanceSpeedCadence;
@VisibleForTesting
public AggregatorBarometer barometer;
public SensorDataSet() {
}
@@ -45,6 +50,7 @@ public final class SensorDataSet {
this.cyclingDistanceSpeed = toCopy.cyclingDistanceSpeed;
this.cyclingPower = toCopy.cyclingPower;
this.runningDistanceSpeedCadence = toCopy.runningDistanceSpeedCadence;
this.barometer = toCopy.barometer;
}
public Pair<HeartRate, String> getHeartRate() {
@@ -113,8 +119,12 @@ public final class SensorDataSet {
this.cyclingPower.add((Raw<Power>) data);
return;
}
if (value instanceof AtmosphericPressure) {
this.barometer.add((Raw<AtmosphericPressure>) data);
return;
}
throw new UnsupportedOperationException(data.getClass().getCanonicalName());
throw new UnsupportedOperationException(data.getClass().getCanonicalName() + " " + data.value().getClass().getCanonicalName());
}
public void remove(@NonNull Aggregator<?, ?> type) {
@@ -122,11 +132,13 @@ public final class SensorDataSet {
}
public void clear() {
Log.i(TAG, "Removing all aggregators");
this.heartRate = null;
this.cyclingCadence = null;
this.cyclingDistanceSpeed = null;
this.cyclingPower = null;
this.runningDistanceSpeedCadence = null;
this.barometer = null;
}
public void fillTrackPoint(TrackPoint trackPoint) {
@@ -153,17 +165,27 @@ public final class SensorDataSet {
if (runningDistanceSpeedCadence != null && runningDistanceSpeedCadence.hasValue()) {
trackPoint.setSensorDistance(runningDistanceSpeedCadence.getValue().distance());
}
if (barometer != null && barometer.hasValue()) {
trackPoint.setAltitudeGain(barometer.getValue().gain_m());
trackPoint.setAltitudeLoss(barometer.getValue().loss_m());
}
}
public void reset() {
Log.i(TAG, "Resetting data");
if (heartRate != null) heartRate.reset();
if (cyclingCadence != null) cyclingCadence.reset();
if (cyclingDistanceSpeed != null) cyclingDistanceSpeed.reset();
if (cyclingPower != null) cyclingPower.reset();
if (runningDistanceSpeedCadence != null) runningDistanceSpeedCadence.reset();
if (barometer != null) barometer.reset();
}
private void set(@NonNull Aggregator<?, ?> type, @Nullable Aggregator<?, ?> sensorData) {
Log.i(TAG, "Setting aggregator " + type.getClass().getCanonicalName());
if (type instanceof AggregatorHeartRate) {
heartRate = (AggregatorHeartRate) sensorData;
return;
@@ -184,6 +206,10 @@ public final class SensorDataSet {
runningDistanceSpeedCadence = (AggregatorRunning) sensorData;
return;
}
if (type instanceof AggregatorBarometer) {
barometer = (AggregatorBarometer) sensorData;
return;
}
throw new UnsupportedOperationException(type.getClass().getCanonicalName());
}
@@ -34,7 +34,7 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
@NonNull
private Clock clock = new MonotonicClock();
private SensorManager sensorManager;
private final SensorManager sensorManager;
public TrackPointCreator(Callback service) {
this.service = service;
@@ -64,7 +64,7 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
return sensorManager.fill(trackPoint);
}
public synchronized void stop() {
public void stop() {
sensorManager.stop(context);
this.context = null;
}
@@ -139,11 +139,6 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
return sensorManager;
}
@VisibleForTesting
public void setSensorManager(SensorManager sensorManager) {
this.sensorManager = sensorManager;
}
@VisibleForTesting
public void setClock(@NonNull String time) {
this.clock = Clock.fixed(Instant.parse(time), ZoneId.of("CET"));