forked from upstream-mirrors/OpenTracks
Bugfix: Cadence/Speed computation incorrectly truncated time to long instead of float.
This commit is contained in:
+27
-1
@@ -12,7 +12,7 @@ import de.dennisguse.opentracks.util.UintUtils;
|
|||||||
public class SensorDataCyclingTest {
|
public class SensorDataCyclingTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void compute_cadence() {
|
public void compute_cadence_1() {
|
||||||
// given
|
// given
|
||||||
SensorDataCycling.Cadence previous = new SensorDataCycling.Cadence("sensorAddress", "sensorName", 1, 1024); // 1s
|
SensorDataCycling.Cadence previous = new SensorDataCycling.Cadence("sensorAddress", "sensorName", 1, 1024); // 1s
|
||||||
SensorDataCycling.Cadence current = new SensorDataCycling.Cadence("sensorAddress", "sensorName", 2, 2048); // 2s
|
SensorDataCycling.Cadence current = new SensorDataCycling.Cadence("sensorAddress", "sensorName", 2, 2048); // 2s
|
||||||
@@ -24,6 +24,19 @@ public class SensorDataCyclingTest {
|
|||||||
Assert.assertEquals(60, current.getCadence_rpm(), 0.01);
|
Assert.assertEquals(60, current.getCadence_rpm(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compute_cadence_2() {
|
||||||
|
// given
|
||||||
|
SensorDataCycling.Cadence previous = new SensorDataCycling.Cadence("sensorAddress", "sensorName", 1, 6184);
|
||||||
|
SensorDataCycling.Cadence current = new SensorDataCycling.Cadence("sensorAddress", "sensorName", 2, 8016);
|
||||||
|
|
||||||
|
// when
|
||||||
|
current.compute(previous);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(33.53, current.getCadence_rpm(), 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void compute_cadence_sameCount() {
|
public void compute_cadence_sameCount() {
|
||||||
// given
|
// given
|
||||||
@@ -77,6 +90,19 @@ public class SensorDataCyclingTest {
|
|||||||
Assert.assertEquals(60, current.getCadence_rpm(), 0.01);
|
Assert.assertEquals(60, current.getCadence_rpm(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compute_speed() {
|
||||||
|
// given
|
||||||
|
SensorDataCycling.Speed previous = new SensorDataCycling.Speed("sensorAddress", "sensorName", 1, 6184);
|
||||||
|
SensorDataCycling.Speed current = new SensorDataCycling.Speed("sensorAddress", "sensorName", 2, 8016);
|
||||||
|
|
||||||
|
// when
|
||||||
|
current.compute(previous, 2150);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(1.20, current.getSpeed_mps(), 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void compute_speed_rollOverCount() {
|
public void compute_speed_rollOverCount() {
|
||||||
// given
|
// given
|
||||||
|
|||||||
@@ -64,13 +64,13 @@ public final class SensorDataCycling {
|
|||||||
|
|
||||||
public void compute(Cadence previous) {
|
public void compute(Cadence previous) {
|
||||||
if (hasData() && previous != null && previous.hasData()) {
|
if (hasData() && previous != null && previous.hasData()) {
|
||||||
long timeDiff_ms = UintUtils.diff(crankRevolutionsTime, previous.crankRevolutionsTime, UintUtils.UINT16_MAX) / 1024 * UnitConversions.S_TO_MS;
|
float timeDiff_ms = UintUtils.diff(crankRevolutionsTime, previous.crankRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * UnitConversions.S_TO_MS;
|
||||||
if (timeDiff_ms <= 0) {
|
if (timeDiff_ms <= 0) {
|
||||||
Log.e(TAG, "Timestamps difference is invalid: cannot compute cadence.");
|
Log.e(TAG, "Timestamps difference is invalid: cannot compute cadence.");
|
||||||
cadence_rpm = INVALID_VALUE_FLOAT;
|
cadence_rpm = INVALID_VALUE_FLOAT;
|
||||||
} else {
|
} else {
|
||||||
long crankDiff = UintUtils.diff(crankRevolutionsCount, previous.crankRevolutionsCount, UintUtils.UINT32_MAX);
|
long crankDiff = UintUtils.diff(crankRevolutionsCount, previous.crankRevolutionsCount, UintUtils.UINT32_MAX);
|
||||||
float cadence_ms = crankDiff / (float) timeDiff_ms;
|
float cadence_ms = crankDiff / timeDiff_ms;
|
||||||
cadence_rpm = (float) (cadence_ms / UnitConversions.MS_TO_S / UnitConversions.S_TO_MIN);
|
cadence_rpm = (float) (cadence_ms / UnitConversions.MS_TO_S / UnitConversions.S_TO_MIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ public final class SensorDataCycling {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "cadence=" + getCadence_rpm() + "_" + getCrankRevolutionsTime();
|
return "cadence=" + getCadence_rpm() + " time=" + getCrankRevolutionsTime() + " count=" + getCrankRevolutionsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -125,7 +125,7 @@ public final class SensorDataCycling {
|
|||||||
|
|
||||||
public void compute(Speed previous, int wheel_circumference_mm) {
|
public void compute(Speed previous, int wheel_circumference_mm) {
|
||||||
if (hasData() && previous != null && previous.hasData()) {
|
if (hasData() && previous != null && previous.hasData()) {
|
||||||
long timeDiff_ms = UintUtils.diff(wheelRevolutionsTime, previous.wheelRevolutionsTime, UintUtils.UINT16_MAX) / 1024 * UnitConversions.S_TO_MS;
|
float timeDiff_ms = UintUtils.diff(wheelRevolutionsTime, previous.wheelRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * UnitConversions.S_TO_MS;
|
||||||
if (timeDiff_ms <= 0) {
|
if (timeDiff_ms <= 0) {
|
||||||
Log.e(TAG, "Timestamps difference is invalid: cannot compute cadence.");
|
Log.e(TAG, "Timestamps difference is invalid: cannot compute cadence.");
|
||||||
speed_mps = INVALID_VALUE_FLOAT;
|
speed_mps = INVALID_VALUE_FLOAT;
|
||||||
@@ -140,7 +140,7 @@ public final class SensorDataCycling {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "speed=" + getSpeed_mps() + "_" + getWheelRevolutionsTime();
|
return "speed=" + getSpeed_mps() + " time=" + getWheelRevolutionsTime() + " count=" + getWheelRevolutionsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+12
-7
@@ -32,11 +32,11 @@ import de.dennisguse.opentracks.util.UnitConversions;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Bluetooth LE sensor manager: manages connections to Bluetooth LE sensors.
|
* Bluetooth LE sensor manager: manages connections to Bluetooth LE sensors.
|
||||||
*
|
* <p>
|
||||||
* Note: should only be instantiated once.
|
* Note: should only be instantiated once.
|
||||||
*
|
* <p>
|
||||||
* TODO: listen for Bluetooth enabled/disabled events.
|
* TODO: listen for Bluetooth enabled/disabled events.
|
||||||
*
|
* <p>
|
||||||
* TODO: In case, a cycling (Cadence and Speed) sensor reports both values, testing is required.
|
* TODO: In case, a cycling (Cadence and Speed) sensor reports both values, testing is required.
|
||||||
* We establish two GATT separate GATT connections (as if two different sensors were used).
|
* We establish two GATT separate GATT connections (as if two different sensors were used).
|
||||||
* However, it is not clear if this is allowed.
|
* However, it is not clear if this is allowed.
|
||||||
@@ -151,18 +151,23 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
|
|||||||
@Override
|
@Override
|
||||||
public synchronized void onChanged(SensorData sensorData) {
|
public synchronized void onChanged(SensorData sensorData) {
|
||||||
if (sensorData instanceof SensorDataCycling.Cadence) {
|
if (sensorData instanceof SensorDataCycling.Cadence) {
|
||||||
if (sensorData.equals(sensorDataSet.getCyclingCadence())) {
|
SensorDataCycling.Cadence previous = sensorDataSet.getCyclingCadence();
|
||||||
|
Log.d(TAG, "previous " + previous + "; current" + sensorData);
|
||||||
|
|
||||||
|
if (sensorData.equals(previous)) {
|
||||||
Log.d(TAG, "onChanged: cadence data repeated.");
|
Log.d(TAG, "onChanged: cadence data repeated.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
((SensorDataCycling.Cadence) sensorData).compute(sensorDataSet.getCyclingCadence());
|
((SensorDataCycling.Cadence) sensorData).compute(previous);
|
||||||
}
|
}
|
||||||
if (sensorData instanceof SensorDataCycling.Speed) {
|
if (sensorData instanceof SensorDataCycling.Speed) {
|
||||||
if (sensorData.equals(sensorDataSet.getCyclingSpeed())) {
|
SensorDataCycling.Speed previous = sensorDataSet.getCyclingSpeed();
|
||||||
|
Log.d(TAG, "previous " + previous + "; current" + sensorData);
|
||||||
|
if (sensorData.equals(previous)) {
|
||||||
Log.d(TAG, "onChanged: speed data repeated.");
|
Log.d(TAG, "onChanged: speed data repeated.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
((SensorDataCycling.Speed) sensorData).compute(sensorDataSet.getCyclingSpeed(), PreferencesUtils.getWheelCircumference(context));
|
((SensorDataCycling.Speed) sensorData).compute(previous, PreferencesUtils.getWheelCircumference(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
sensorDataSet.set(sensorData);
|
sensorDataSet.set(sensorData);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class UintUtils {
|
|||||||
if (a < 0 || b < 0) {
|
if (a < 0 || b < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (a > UINT_MAX && b > UINT_MAX) {
|
if (a > UINT_MAX || b > UINT_MAX) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user