forked from upstream-mirrors/OpenTracks
SENSORPOINT and TRACKPOINT require a distance to be stored.
TrackRecording and TrackStatisticsUpdater. Part of #500 Fixes #1074.
This commit is contained in:
+73
-46
@@ -38,7 +38,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.content.data.Distance;
|
import de.dennisguse.opentracks.content.data.Distance;
|
||||||
@@ -129,21 +128,21 @@ public class ExportImportTest {
|
|||||||
|
|
||||||
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:02Z"), ZoneId.of("CET")));
|
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:02Z"), ZoneId.of("CET")));
|
||||||
trackId = service.startNewTrack();
|
trackId = service.startNewTrack();
|
||||||
service.stopUpdateRecordingData();
|
|
||||||
|
|
||||||
Distance sensorDistance = Distance.of(10); // recording distance interval
|
Distance sensorDistance = Distance.of(10); // recording distance interval
|
||||||
|
|
||||||
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
|
|
||||||
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:03Z"), 3, 14, 10, 15, 10, 1);
|
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:03Z"), 3, 14, 10, 15, 10, 1);
|
||||||
service.insertMarker("Marker 1", "Marker 1 category", "Marker 1 desc", null);
|
service.insertMarker("Marker 1", "Marker 1 category", "Marker 1 desc", null);
|
||||||
|
|
||||||
// A sensor-only TrackPoint
|
// A sensor-only TrackPoint
|
||||||
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
|
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:04Z"), ZoneId.of("CET")));
|
||||||
mockAltitudeChange(trackPointCreator, 1);
|
mockAltitudeChange(trackPointCreator, 1);
|
||||||
sendSensor(trackPointCreator, Instant.parse("2020-02-02T02:02:04Z"));
|
|
||||||
|
|
||||||
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
|
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
|
||||||
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:05Z"), 3, 14.002, 10, 15, 10, 0);
|
|
||||||
|
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:05Z"), ZoneId.of("CET")));
|
||||||
|
mockBLESensorData(trackPointCreator, 5f, Distance.of(2), 66f, 3f, 50f); // Distance will be added to next TrackPoint
|
||||||
|
|
||||||
|
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:05Z"), 3, 14.001, 10, 15, 10, 0);
|
||||||
service.insertMarker("Marker 2", "Marker 2 category", "Marker 2 desc", null);
|
service.insertMarker("Marker 2", "Marker 2 category", "Marker 2 desc", null);
|
||||||
|
|
||||||
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:06Z"), ZoneId.of("CET")));
|
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:06Z"), ZoneId.of("CET")));
|
||||||
@@ -152,16 +151,11 @@ public class ExportImportTest {
|
|||||||
|
|
||||||
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:20Z"), ZoneId.of("CET")));
|
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:20Z"), ZoneId.of("CET")));
|
||||||
service.resumeCurrentTrack();
|
service.resumeCurrentTrack();
|
||||||
service.stopUpdateRecordingData();
|
|
||||||
|
|
||||||
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:21Z"), ZoneId.of("CET")));
|
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:21Z"), 3, 14.002, 10, 15, 10, 0);
|
||||||
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
|
|
||||||
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:21Z"), 3, 14.003, 10, 15, 10, 0);
|
|
||||||
|
|
||||||
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
|
|
||||||
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:22Z"), 3, 16, 10, 15, 10, 0);
|
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:22Z"), 3, 16, 10, 15, 10, 0);
|
||||||
|
|
||||||
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
|
|
||||||
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:23Z"), 3, 16.001, 10, 15, 10, 0);
|
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:23Z"), 3, 16.001, 10, 15, 10, 0);
|
||||||
|
|
||||||
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:24Z"), ZoneId.of("CET")));
|
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:24Z"), ZoneId.of("CET")));
|
||||||
@@ -213,7 +207,8 @@ public class ExportImportTest {
|
|||||||
// 2. trackpoints
|
// 2. trackpoints
|
||||||
TrackPointAssert a = new TrackPointAssert()
|
TrackPointAssert a = new TrackPointAssert()
|
||||||
.noAccuracy();
|
.noAccuracy();
|
||||||
a.assertEquals(trackPoints, TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId));
|
List<TrackPoint> actual = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId);
|
||||||
|
a.assertEquals(trackPoints, actual);
|
||||||
|
|
||||||
// 3. trackstatistics
|
// 3. trackstatistics
|
||||||
TrackStatistics importedTrackStatistics = importedTrack.getTrackStatistics();
|
TrackStatistics importedTrackStatistics = importedTrack.getTrackStatistics();
|
||||||
@@ -226,24 +221,24 @@ public class ExportImportTest {
|
|||||||
TrackStatistics originalTrackStatistics = track.getTrackStatistics();
|
TrackStatistics originalTrackStatistics = track.getTrackStatistics();
|
||||||
|
|
||||||
assertEquals(originalTrackStatistics.getTotalTime(), importedTrackStatistics.getTotalTime());
|
assertEquals(originalTrackStatistics.getTotalTime(), importedTrackStatistics.getTotalTime());
|
||||||
assertEquals(Duration.ofSeconds(8), importedTrackStatistics.getTotalTime());
|
assertEquals(Duration.ofSeconds(7), importedTrackStatistics.getTotalTime());
|
||||||
|
|
||||||
assertEquals(originalTrackStatistics.getMovingTime(), importedTrackStatistics.getMovingTime());
|
assertEquals(originalTrackStatistics.getMovingTime(), importedTrackStatistics.getMovingTime());
|
||||||
assertEquals(Duration.ofSeconds(4), importedTrackStatistics.getMovingTime());
|
assertEquals(Duration.ofSeconds(3), importedTrackStatistics.getMovingTime());
|
||||||
|
|
||||||
// Distance
|
// Distance
|
||||||
assertEquals(originalTrackStatistics.getTotalDistance(), importedTrackStatistics.getTotalDistance());
|
assertEquals(originalTrackStatistics.getTotalDistance(), importedTrackStatistics.getTotalDistance());
|
||||||
assertEquals(Distance.of(60), importedTrackStatistics.getTotalDistance());
|
assertEquals(123.16, importedTrackStatistics.getTotalDistance().toM(), 0.01);
|
||||||
|
|
||||||
// Speed
|
// Speed
|
||||||
assertEquals(originalTrackStatistics.getMaxSpeed(), importedTrackStatistics.getMaxSpeed());
|
assertEquals(originalTrackStatistics.getMaxSpeed(), importedTrackStatistics.getMaxSpeed());
|
||||||
assertEquals(Speed.of(15), importedTrackStatistics.getMaxSpeed());
|
assertEquals(41.05, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||||
|
|
||||||
assertEquals(originalTrackStatistics.getAverageSpeed(), importedTrackStatistics.getAverageSpeed());
|
assertEquals(originalTrackStatistics.getAverageSpeed(), importedTrackStatistics.getAverageSpeed());
|
||||||
assertEquals(Speed.of(7.5), importedTrackStatistics.getAverageSpeed());
|
assertEquals(17.59, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
|
||||||
|
|
||||||
assertEquals(originalTrackStatistics.getAverageMovingSpeed(), importedTrackStatistics.getAverageMovingSpeed());
|
assertEquals(originalTrackStatistics.getAverageMovingSpeed(), importedTrackStatistics.getAverageMovingSpeed());
|
||||||
assertEquals(Speed.of(15), importedTrackStatistics.getAverageMovingSpeed());
|
assertEquals(41.05, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||||
|
|
||||||
// Altitude
|
// Altitude
|
||||||
assertEquals(originalTrackStatistics.getMinAltitude(), importedTrackStatistics.getMinAltitude(), 0.01);
|
assertEquals(originalTrackStatistics.getMinAltitude(), importedTrackStatistics.getMinAltitude(), 0.01);
|
||||||
@@ -322,17 +317,52 @@ public class ExportImportTest {
|
|||||||
// 2. trackpoints
|
// 2. trackpoints
|
||||||
// The GPX exporter does not support exporting TrackPoints without lat/lng.
|
// The GPX exporter does not support exporting TrackPoints without lat/lng.
|
||||||
// Therefore, the track segmentation is changes.
|
// Therefore, the track segmentation is changes.
|
||||||
List<TrackPoint> trackPointsWithCoordinates = trackPoints.stream().filter(it -> TrackPoint.Type.SEGMENT_START_AUTOMATIC.equals(it.getType()) || TrackPoint.Type.TRACKPOINT.equals(it.getType())).collect(Collectors.toList());
|
|
||||||
trackPointsWithCoordinates.get(0).setType(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
|
|
||||||
trackPointsWithCoordinates.get(1).setSensorDistance(Distance.of(20));
|
|
||||||
trackPointsWithCoordinates.get(1).setAltitudeGain(1f);
|
|
||||||
trackPointsWithCoordinates.get(1).setAltitudeLoss(1f);
|
|
||||||
trackPointsWithCoordinates.get(2).setType(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
|
|
||||||
|
|
||||||
TrackPointAssert a = new TrackPointAssert()
|
TrackPointAssert a = new TrackPointAssert()
|
||||||
.setDelta(0.05)
|
.setDelta(0.05)
|
||||||
.noAccuracy(); // speed is not fully
|
.noAccuracy(); // speed is not fully
|
||||||
a.assertEquals(trackPointsWithCoordinates, TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId));
|
List<TrackPoint> actual = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId);
|
||||||
|
a.assertEquals(List.of(
|
||||||
|
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC, Instant.parse("2020-02-02T02:02:03Z"))
|
||||||
|
.setLatitude(3)
|
||||||
|
.setLongitude(14)
|
||||||
|
.setAltitude(10)
|
||||||
|
.setSpeed(Speed.of(15))
|
||||||
|
.setAltitudeLoss(1f)
|
||||||
|
.setAltitudeGain(1f),
|
||||||
|
new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.parse("2020-02-02T02:02:05Z"))
|
||||||
|
.setLatitude(3)
|
||||||
|
.setLongitude(14.001)
|
||||||
|
.setAltitude(10)
|
||||||
|
.setSpeed(Speed.of(5))
|
||||||
|
.setAltitudeLoss(1f)
|
||||||
|
.setAltitudeGain(1f)
|
||||||
|
.setSensorDistance(Distance.of(12))
|
||||||
|
.setHeartRate_bpm(66f)
|
||||||
|
.setPower(50f)
|
||||||
|
.setCadence_rpm(3f),
|
||||||
|
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC, Instant.parse("2020-02-02T02:02:21Z"))
|
||||||
|
.setLatitude(3)
|
||||||
|
.setLongitude(14.002)
|
||||||
|
.setAltitude(10)
|
||||||
|
.setAltitudeLoss(0f)
|
||||||
|
.setAltitudeGain(0f)
|
||||||
|
.setSpeed(Speed.of(15)),
|
||||||
|
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC, Instant.parse("2020-02-02T02:02:22Z"))
|
||||||
|
.setLatitude(3)
|
||||||
|
.setLongitude(16)
|
||||||
|
.setAltitude(10)
|
||||||
|
.setAltitudeLoss(0f)
|
||||||
|
.setAltitudeGain(0f)
|
||||||
|
.setSpeed(Speed.of(15)),
|
||||||
|
new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.parse("2020-02-02T02:02:23Z"))
|
||||||
|
.setLatitude(3)
|
||||||
|
.setLongitude(16.001)
|
||||||
|
.setAltitude(10)
|
||||||
|
.setAltitudeLoss(0f)
|
||||||
|
.setAltitudeGain(0f)
|
||||||
|
.setSpeed(Speed.of(15))
|
||||||
|
), actual);
|
||||||
|
|
||||||
// 3. trackstatistics
|
// 3. trackstatistics
|
||||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||||
@@ -343,16 +373,16 @@ public class ExportImportTest {
|
|||||||
assertEquals(Instant.parse("2020-02-02T02:02:03Z"), importedTrackStatistics.getStartTime());
|
assertEquals(Instant.parse("2020-02-02T02:02:03Z"), importedTrackStatistics.getStartTime());
|
||||||
assertEquals(Instant.parse("2020-02-02T02:02:23Z"), importedTrackStatistics.getStopTime());
|
assertEquals(Instant.parse("2020-02-02T02:02:23Z"), importedTrackStatistics.getStopTime());
|
||||||
|
|
||||||
assertEquals(Duration.ofSeconds(4), importedTrackStatistics.getTotalTime());
|
assertEquals(Duration.ofSeconds(3), importedTrackStatistics.getTotalTime());
|
||||||
assertEquals(Duration.ofSeconds(4), importedTrackStatistics.getMovingTime());
|
assertEquals(Duration.ofSeconds(3), importedTrackStatistics.getMovingTime());
|
||||||
|
|
||||||
// Distance
|
// Distance
|
||||||
assertEquals(Distance.of(60), importedTrackStatistics.getTotalDistance());
|
assertEquals(123.16, importedTrackStatistics.getTotalDistance().toM(), 0.01);
|
||||||
|
|
||||||
// Speed
|
// Speed
|
||||||
assertEquals(Speed.of(15), importedTrackStatistics.getMaxSpeed());
|
assertEquals(41.05, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||||
assertEquals(Speed.of(15), importedTrackStatistics.getAverageSpeed());
|
assertEquals(41.05, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
|
||||||
assertEquals(Speed.of(15), importedTrackStatistics.getAverageMovingSpeed());
|
assertEquals(41.05, importedTrackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
|
||||||
|
|
||||||
// Altitude
|
// Altitude
|
||||||
assertEquals(10, importedTrackStatistics.getMinAltitude(), 0.01);
|
assertEquals(10, importedTrackStatistics.getMinAltitude(), 0.01);
|
||||||
@@ -424,19 +454,21 @@ public class ExportImportTest {
|
|||||||
Mockito.when(cadence.getValue()).thenReturn(cyclingCadence);
|
Mockito.when(cadence.getValue()).thenReturn(cyclingCadence);
|
||||||
sensorDataSet.set(cadence);
|
sensorDataSet.set(cadence);
|
||||||
|
|
||||||
SensorDataCycling.DistanceSpeed.Data distanceSpeedData = Mockito.mock(SensorDataCycling.DistanceSpeed.Data.class);
|
if (distance != null && speed != null) {
|
||||||
Mockito.when(distanceSpeedData.getDistanceOverall()).thenReturn(distance);
|
SensorDataCycling.DistanceSpeed.Data distanceSpeedData = Mockito.mock(SensorDataCycling.DistanceSpeed.Data.class);
|
||||||
Mockito.when(distanceSpeedData.getSpeed()).thenReturn(Speed.of(speed));
|
Mockito.when(distanceSpeedData.getDistanceOverall()).thenReturn(distance);
|
||||||
SensorDataCycling.DistanceSpeed distanceSpeed = Mockito.mock(SensorDataCycling.DistanceSpeed.class);
|
Mockito.when(distanceSpeedData.getSpeed()).thenReturn(Speed.of(speed));
|
||||||
Mockito.when(distanceSpeed.hasValue()).thenReturn(true);
|
SensorDataCycling.DistanceSpeed distanceSpeed = Mockito.mock(SensorDataCycling.DistanceSpeed.class);
|
||||||
Mockito.when(distanceSpeed.getValue()).thenReturn(distanceSpeedData);
|
Mockito.when(distanceSpeed.hasValue()).thenReturn(true);
|
||||||
|
Mockito.when(distanceSpeed.getValue()).thenReturn(distanceSpeedData);
|
||||||
sensorDataSet.set(distanceSpeed);
|
sensorDataSet.set(distanceSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
sensorDataSet.fillTrackPoint(trackPoint);
|
sensorDataSet.fillTrackPoint(trackPoint);
|
||||||
return sensorDataSet;
|
return sensorDataSet;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
trackPointCreator.onChange(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) {
|
private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) {
|
||||||
@@ -445,11 +477,6 @@ public class ExportImportTest {
|
|||||||
altitudeSumManager.setAltitudeLoss_m(altitudeGain);
|
altitudeSumManager.setAltitudeLoss_m(altitudeGain);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendSensor(TrackPointCreator trackPointCreator, Instant time) {
|
|
||||||
trackPointCreator.setClock(Clock.fixed(time, ZoneId.of("CET")));
|
|
||||||
trackPointCreator.onNewTrackPointWithoutGPS();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendLocation(TrackPointCreator trackPointCreator, Instant time, double latitude, double longitude, float accuracy, float speed, float altitude, float altitudeGain) {
|
private void sendLocation(TrackPointCreator trackPointCreator, Instant time, double latitude, double longitude, float accuracy, float speed, float altitude, float altitudeGain) {
|
||||||
Location location = new Location("mock");
|
Location location = new Location("mock");
|
||||||
location.setLatitude(latitude);
|
location.setLatitude(latitude);
|
||||||
|
|||||||
+4
-1
@@ -62,6 +62,7 @@ import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
|||||||
import de.dennisguse.opentracks.io.file.importer.TrackPointAssert;
|
import de.dennisguse.opentracks.io.file.importer.TrackPointAssert;
|
||||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||||
import de.dennisguse.opentracks.services.sensors.AltitudeSumManager;
|
import de.dennisguse.opentracks.services.sensors.AltitudeSumManager;
|
||||||
|
import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
|
||||||
@@ -465,8 +466,10 @@ public class TrackRecordingServiceTest {
|
|||||||
// Reset service (if some previous test failed)
|
// Reset service (if some previous test failed)
|
||||||
TrackRecordingService service = ((TrackRecordingService.Binder) mServiceRule.bindService(new Intent(context, TrackRecordingService.class)))
|
TrackRecordingService service = ((TrackRecordingService.Binder) mServiceRule.bindService(new Intent(context, TrackRecordingService.class)))
|
||||||
.getService();
|
.getService();
|
||||||
service.endCurrentTrack();
|
|
||||||
|
service.getTrackPointCreator().setRemoteSensorManager(new BluetoothRemoteSensorManager(context, service.getTrackPointCreator()));
|
||||||
service.getTrackPointCreator().setClock(Clock.systemUTC());
|
service.getTrackPointCreator().setClock(Clock.systemUTC());
|
||||||
|
service.endCurrentTrack();
|
||||||
service.sharedPreferenceChangeListener.onSharedPreferenceChanged(null, null);
|
service.sharedPreferenceChangeListener.onSharedPreferenceChanged(null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-25
@@ -382,7 +382,6 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
), trackPoints);
|
), trackPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated // Will be superseded when fixing #500
|
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testOnLocationChangedAsync_idle_withSensorDistance() {
|
public void testOnLocationChangedAsync_idle_withSensorDistance() {
|
||||||
@@ -407,23 +406,25 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
// when
|
// when
|
||||||
altitudeSumManager.addAltitudeGain_m(6f);
|
altitudeSumManager.addAltitudeGain_m(6f);
|
||||||
altitudeSumManager.addAltitudeLoss_m(6f);
|
altitudeSumManager.addAltitudeLoss_m(6f);
|
||||||
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(0)));
|
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(0))); //Should be ignored
|
||||||
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(2)));
|
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(2))); //TODO Should be ignored; distance will be added to TrackPoint
|
||||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 15);
|
||||||
|
|
||||||
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(12)));
|
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(12)));
|
||||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 2, 15);
|
|
||||||
|
|
||||||
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(13)));
|
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(13))); //Should be ignored
|
||||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 3, 15);
|
|
||||||
altitudeSumManager.addAltitudeGain_m(6f);
|
altitudeSumManager.addAltitudeGain_m(6f);
|
||||||
altitudeSumManager.addAltitudeLoss_m(6f);
|
altitudeSumManager.addAltitudeLoss_m(6f);
|
||||||
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(14)));
|
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(14))); //Should be ignored
|
||||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 15); //Should be ignored
|
||||||
|
|
||||||
altitudeSumManager.addAltitudeGain_m(6f);
|
altitudeSumManager.addAltitudeGain_m(6f);
|
||||||
altitudeSumManager.addAltitudeLoss_m(6f);
|
altitudeSumManager.addAltitudeLoss_m(6f);
|
||||||
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(16)));
|
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(16)));
|
||||||
|
|
||||||
|
altitudeSumManager.addAltitudeGain_m(7f);
|
||||||
|
altitudeSumManager.addAltitudeLoss_m(7f);
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@@ -434,34 +435,31 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
.ignoreTime();
|
.ignoreTime();
|
||||||
a.assertEquals(List.of(
|
a.assertEquals(List.of(
|
||||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, null),
|
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, null),
|
||||||
|
new TrackPoint(TrackPoint.Type.SENSORPOINT, null) // TODO Should be ignored; is stored as it assumed to be first in current segment.
|
||||||
|
.setAltitudeGain(6f)
|
||||||
|
.setAltitudeLoss(6f)
|
||||||
|
.setSpeed(Speed.of(5))
|
||||||
|
.setSensorDistance(Distance.of(2)),
|
||||||
new TrackPoint(TrackPoint.Type.TRACKPOINT, null)
|
new TrackPoint(TrackPoint.Type.TRACKPOINT, null)
|
||||||
.setLatitude(45)
|
.setLatitude(45)
|
||||||
.setLongitude(35)
|
.setLongitude(35)
|
||||||
.setHorizontalAccuracy(Distance.of(1))
|
.setHorizontalAccuracy(Distance.of(1))
|
||||||
.setSpeed(Speed.of(5))
|
.setSpeed(Speed.of(5))
|
||||||
.setAltitudeGain(6f)
|
.setSensorDistance(Distance.of(0)),
|
||||||
.setAltitudeLoss(6f)
|
new TrackPoint(TrackPoint.Type.SENSORPOINT, null)
|
||||||
.setSensorDistance(Distance.of(2)),
|
|
||||||
new TrackPoint(TrackPoint.Type.TRACKPOINT, null)
|
|
||||||
.setLatitude(45)
|
|
||||||
.setLongitude(35)
|
|
||||||
.setHorizontalAccuracy(Distance.of(2))
|
|
||||||
.setSpeed(Speed.of(5))
|
.setSpeed(Speed.of(5))
|
||||||
.setSensorDistance(Distance.of(10)),
|
.setSensorDistance(Distance.of(10)),
|
||||||
new TrackPoint(TrackPoint.Type.TRACKPOINT, null)
|
new TrackPoint(TrackPoint.Type.SENSORPOINT, null)
|
||||||
.setLatitude(45)
|
|
||||||
.setLongitude(35)
|
|
||||||
.setHorizontalAccuracy(Distance.of(4))
|
|
||||||
.setSpeed(Speed.of(5))
|
.setSpeed(Speed.of(5))
|
||||||
.setAltitudeGain(6f)
|
.setAltitudeGain(12f)
|
||||||
.setAltitudeLoss(6f)
|
.setAltitudeLoss(12f)
|
||||||
.setSensorDistance(Distance.of(2)),
|
.setSensorDistance(Distance.of(4)),
|
||||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, null)
|
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, null)
|
||||||
.setSensorDistance(Distance.of(11))
|
.setSensorDistance(Distance.of(11))
|
||||||
.setSpeed(Speed.of(5))
|
.setSpeed(Speed.of(5))
|
||||||
.setAltitudeGain(6f)
|
.setAltitudeGain(7f)
|
||||||
.setAltitudeLoss(6f)
|
.setAltitudeLoss(7f)
|
||||||
.setSensorDistance(Distance.of(2))
|
.setSensorDistance(Distance.of(0))
|
||||||
), trackPoints);
|
), trackPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,5 +59,12 @@ public abstract class Altitude {
|
|||||||
return new EGM2008(altitude_m);
|
return new EGM2008(altitude_m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Altitude{" +
|
||||||
|
"altitude_m=" + altitude_m + this.getClass().getSimpleName() +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class TrackPoint {
|
|||||||
|
|
||||||
SEGMENT_START_AUTOMATIC(-1), //Start of a segment due to too much distance from previous TrackPoint
|
SEGMENT_START_AUTOMATIC(-1), //Start of a segment due to too much distance from previous TrackPoint
|
||||||
TRACKPOINT(0), //Just GPS data and may contain BLE sensor data
|
TRACKPOINT(0), //Just GPS data and may contain BLE sensor data
|
||||||
SENSORPOINT(2), //Just BLE sensor data
|
SENSORPOINT(2), //Just BLE sensor data; required to have speed and sensorDistance
|
||||||
|
|
||||||
SEGMENT_END_MANUAL(1); //End of a segment
|
SEGMENT_END_MANUAL(1); //End of a segment
|
||||||
|
|
||||||
@@ -109,13 +109,7 @@ public class TrackPoint {
|
|||||||
public TrackPoint(@NonNull Type type, @NonNull Location location, @NonNull Instant time) {
|
public TrackPoint(@NonNull Type type, @NonNull Location location, @NonNull Instant time) {
|
||||||
this(type, time);
|
this(type, time);
|
||||||
|
|
||||||
this.latitude = location.getLatitude();
|
setLocation(location);
|
||||||
this.longitude = location.getLongitude();
|
|
||||||
this.altitude = location.hasAltitude() ? Altitude.WGS84.of(location.getAltitude()) : null;
|
|
||||||
this.speed = location.hasSpeed() ? Speed.of(location.getSpeed()) : null;
|
|
||||||
this.horizontalAccuracy = location.hasAccuracy() ? Distance.of(location.getAccuracy()) : null;
|
|
||||||
|
|
||||||
//TODO Should we copy the bearing?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -152,6 +146,10 @@ public class TrackPoint {
|
|||||||
return type == Type.SEGMENT_END_MANUAL;
|
return type == Type.SEGMENT_END_MANUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean wasCreatedManually() {
|
||||||
|
return hasLocation() || hasSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* May be null if the track was not loaded from the database.
|
* May be null if the track was not loaded from the database.
|
||||||
*/
|
*/
|
||||||
@@ -211,6 +209,17 @@ public class TrackPoint {
|
|||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TrackPoint setLocation(@NonNull Location location) {
|
||||||
|
this.latitude = location.getLatitude();
|
||||||
|
this.longitude = location.getLongitude();
|
||||||
|
this.altitude = location.hasAltitude() ? Altitude.WGS84.of(location.getAltitude()) : null;
|
||||||
|
this.speed = location.hasSpeed() ? Speed.of(location.getSpeed()) : null;
|
||||||
|
this.horizontalAccuracy = location.hasAccuracy() ? Distance.of(location.getAccuracy()) : null;
|
||||||
|
|
||||||
|
//TODO Should we copy the bearing?
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasAltitudeGain() {
|
public boolean hasAltitudeGain() {
|
||||||
return altitudeGain_m != null;
|
return altitudeGain_m != null;
|
||||||
}
|
}
|
||||||
@@ -310,13 +319,13 @@ public class TrackPoint {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@NonNull
|
||||||
public Distance distanceToPrevious(@Nullable TrackPoint previous) {
|
public Distance distanceToPrevious(@NonNull TrackPoint previous) {
|
||||||
if (hasSensorDistance()) {
|
if (hasSensorDistance()) {
|
||||||
return getSensorDistance();
|
return getSensorDistance();
|
||||||
}
|
}
|
||||||
if (previous == null || !(hasLocation() && previous.hasLocation())) {
|
if (!hasLocation() || hasLocation() != previous.hasLocation()) {
|
||||||
return null;
|
throw new RuntimeException("Cannot compute distance.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Distance.of(getLocation().distanceTo(previous.getLocation()));
|
return Distance.of(getLocation().distanceTo(previous.getLocation()));
|
||||||
@@ -411,7 +420,7 @@ public class TrackPoint {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
String result = "time=" + getTime() + " (type=" + getType() + ")";
|
String result = "time=" + getTime() + " (type=" + getType() + ")";
|
||||||
if (hasLocation()) {
|
if (hasLocation()) {
|
||||||
result += ": lat=" + getLatitude() + " lng=" + getLongitude();
|
result += ": lat=" + getLatitude() + " lng=" + getLongitude() + " alt=" + getAltitude();
|
||||||
}
|
}
|
||||||
if (hasHorizontalAccuracy()) {
|
if (hasHorizontalAccuracy()) {
|
||||||
result += " acc=" + getHorizontalAccuracy();
|
result += " acc=" + getHorizontalAccuracy();
|
||||||
@@ -419,6 +428,12 @@ public class TrackPoint {
|
|||||||
if (hasSensorDistance()) {
|
if (hasSensorDistance()) {
|
||||||
result += " distance=" + getSensorDistance();
|
result += " distance=" + getSensorDistance();
|
||||||
}
|
}
|
||||||
|
if (hasAltitudeGain()) {
|
||||||
|
result += " altitudeGain= " + getAltitudeGain();
|
||||||
|
}
|
||||||
|
if (hasAltitudeLoss()) {
|
||||||
|
result += " altitudeLoss= " + getAltitudeLoss();
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,23 +306,10 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
|||||||
Instant time = whenList.get(i);
|
Instant time = whenList.get(i);
|
||||||
Location location = locationList.get(i);
|
Location location = locationList.get(i);
|
||||||
|
|
||||||
TrackPoint trackPoint;
|
TrackPoint trackPoint = new TrackPoint(TrackPoint.Type.SENSORPOINT, time);
|
||||||
if (i == 0) {
|
if (location != null) {
|
||||||
//first
|
trackPoint.setType(TrackPoint.Type.TRACKPOINT);
|
||||||
if (location == null) {
|
trackPoint.setLocation(location);
|
||||||
trackPoint = TrackPoint.createSegmentStartManualWithTime(time);
|
|
||||||
} else {
|
|
||||||
trackPoint = new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC, location, time);
|
|
||||||
}
|
|
||||||
} else if (i == locationList.size() - 1 && location == null) {
|
|
||||||
//last
|
|
||||||
trackPoint = TrackPoint.createSegmentEndWithTime(time);
|
|
||||||
} else {
|
|
||||||
if (location == null) {
|
|
||||||
trackPoint = new TrackPoint(TrackPoint.Type.SENSORPOINT, time);
|
|
||||||
} else {
|
|
||||||
trackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, location, time);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < sensorSpeedList.size() && sensorSpeedList.get(i) != null) {
|
if (i < sensorSpeedList.size() && sensorSpeedList.get(i) != null) {
|
||||||
@@ -347,6 +334,21 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
|||||||
trackPoint.setAltitudeLoss(altitudeLossList.get(i));
|
trackPoint.setAltitudeLoss(altitudeLossList.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update TrackPoint type for START / STOP.
|
||||||
|
TrackPoint.Type type = trackPoint.getType();
|
||||||
|
if (i == 0) {
|
||||||
|
//first
|
||||||
|
if (!trackPoint.wasCreatedManually()) {
|
||||||
|
type = TrackPoint.Type.SEGMENT_START_MANUAL;
|
||||||
|
} else {
|
||||||
|
type = TrackPoint.Type.SEGMENT_START_AUTOMATIC;
|
||||||
|
}
|
||||||
|
} else if (i == locationList.size() - 1 && !trackPoint.wasCreatedManually()) {
|
||||||
|
//last
|
||||||
|
type = TrackPoint.Type.SEGMENT_END_MANUAL;
|
||||||
|
}
|
||||||
|
trackPoint.setType(type);
|
||||||
|
|
||||||
trackImporter.addTrackPoint(trackPoint);
|
trackImporter.addTrackPoint(trackPoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,8 +198,8 @@ public class TrackImporter {
|
|||||||
TrackPoint previous = trackPoints.get(i - 1);
|
TrackPoint previous = trackPoints.get(i - 1);
|
||||||
TrackPoint current = trackPoints.get(i);
|
TrackPoint current = trackPoints.get(i);
|
||||||
|
|
||||||
Distance distanceToPrevious = current.distanceToPrevious(previous);
|
if (current.hasSensorDistance() || (previous.hasLocation() && current.hasLocation())) {
|
||||||
if (distanceToPrevious != null) {
|
Distance distanceToPrevious = current.distanceToPrevious(previous);
|
||||||
if (!current.hasSpeed()) {
|
if (!current.hasSpeed()) {
|
||||||
Duration timeDifference = Duration.between(previous.getTime(), current.getTime());
|
Duration timeDifference = Duration.between(previous.getTime(), current.getTime());
|
||||||
current.setSpeed(Speed.of(distanceToPrevious, timeDifference));
|
current.setSpeed(Speed.of(distanceToPrevious, timeDifference));
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ class TrackRecordingManager {
|
|||||||
private Track.Id trackId;
|
private Track.Id trackId;
|
||||||
private TrackStatisticsUpdater trackStatisticsUpdater;
|
private TrackStatisticsUpdater trackStatisticsUpdater;
|
||||||
|
|
||||||
//TDOO use lastStoredTrackPoint?
|
|
||||||
private boolean currentSegmentHasTrackPoint;
|
|
||||||
private TrackPoint lastTrackPoint;
|
private TrackPoint lastTrackPoint;
|
||||||
private TrackPoint lastStoredTrackPoint;
|
private TrackPoint lastStoredTrackPoint;
|
||||||
private TrackPoint lastStoredTrackPointWithLocation;
|
private TrackPoint lastStoredTrackPointWithLocation;
|
||||||
@@ -68,8 +66,6 @@ class TrackRecordingManager {
|
|||||||
track.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime()));
|
track.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime()));
|
||||||
contentProviderUtils.updateTrack(track);
|
contentProviderUtils.updateTrack(track);
|
||||||
|
|
||||||
currentSegmentHasTrackPoint = false;
|
|
||||||
|
|
||||||
return trackId;
|
return trackId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +81,6 @@ class TrackRecordingManager {
|
|||||||
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getTrackStatistics());
|
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getTrackStatistics());
|
||||||
insertTrackPoint(trackId, segmentStartTrackPoint);
|
insertTrackPoint(trackId, segmentStartTrackPoint);
|
||||||
|
|
||||||
currentSegmentHasTrackPoint = false;
|
|
||||||
lastTrackPoint = null;
|
lastTrackPoint = null;
|
||||||
lastStoredTrackPoint = null;
|
lastStoredTrackPoint = null;
|
||||||
lastStoredTrackPointWithLocation = null;
|
lastStoredTrackPointWithLocation = null;
|
||||||
@@ -94,7 +89,6 @@ class TrackRecordingManager {
|
|||||||
void pause(TrackPointCreator trackPointCreator) {
|
void pause(TrackPointCreator trackPointCreator) {
|
||||||
insertTrackPoint(trackId, trackPointCreator.createSegmentEnd());
|
insertTrackPoint(trackId, trackPointCreator.createSegmentEnd());
|
||||||
|
|
||||||
currentSegmentHasTrackPoint = false;
|
|
||||||
lastTrackPoint = null;
|
lastTrackPoint = null;
|
||||||
lastStoredTrackPoint = null;
|
lastStoredTrackPoint = null;
|
||||||
lastStoredTrackPointWithLocation = null;
|
lastStoredTrackPointWithLocation = null;
|
||||||
@@ -107,7 +101,6 @@ class TrackRecordingManager {
|
|||||||
trackId = null;
|
trackId = null;
|
||||||
trackStatisticsUpdater = null;
|
trackStatisticsUpdater = null;
|
||||||
|
|
||||||
currentSegmentHasTrackPoint = false;
|
|
||||||
lastTrackPoint = null;
|
lastTrackPoint = null;
|
||||||
lastStoredTrackPoint = null;
|
lastStoredTrackPoint = null;
|
||||||
lastStoredTrackPointWithLocation = null;
|
lastStoredTrackPointWithLocation = null;
|
||||||
@@ -161,44 +154,43 @@ class TrackRecordingManager {
|
|||||||
/**
|
/**
|
||||||
* @return TrackPoint was stored?
|
* @return TrackPoint was stored?
|
||||||
*/
|
*/
|
||||||
boolean onNewTrackPoint(TrackPoint trackPoint) {
|
boolean onNewTrackPoint(@NonNull TrackPoint trackPoint) {
|
||||||
//Storing trackPoint
|
//Storing trackPoint
|
||||||
|
|
||||||
// Always insert the first segment location
|
// Always insert the first segment location
|
||||||
if (!currentSegmentHasTrackPoint) {
|
if (lastStoredTrackPoint == null) {
|
||||||
insertTrackPoint(trackId, trackPoint);
|
insertTrackPoint(trackId, trackPoint);
|
||||||
currentSegmentHasTrackPoint = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Distance distanceToLastStoredTrackPoint = trackPoint.distanceToPrevious(lastStoredTrackPoint);
|
if (trackPoint.hasLocation() && lastStoredTrackPointWithLocation == null) {
|
||||||
if (distanceToLastStoredTrackPoint != null) {
|
insertTrackPoint(trackId, trackPoint);
|
||||||
if (distanceToLastStoredTrackPoint.greaterThan(maxRecordingDistance)) {
|
return true;
|
||||||
trackPoint.setType(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
|
|
||||||
insertTrackPoint(trackId, trackPoint);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (distanceToLastStoredTrackPoint.greaterOrEqualThan(recordingDistanceInterval) && trackPoint.isMoving()) {
|
|
||||||
insertTrackPoint(trackId, trackPoint);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trackPoint.hasLocation()) {
|
|
||||||
if (lastStoredTrackPointWithLocation == null) {
|
|
||||||
insertTrackPoint(trackId, trackPoint);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Distance distanceToLastStoredTrackPointWithLocation = trackPoint.distanceToPrevious(lastStoredTrackPointWithLocation);
|
|
||||||
if (distanceToLastStoredTrackPointWithLocation != null && distanceToLastStoredTrackPointWithLocation.greaterOrEqualThan(recordingDistanceInterval)) {
|
|
||||||
insertTrackPoint(trackId, trackPoint);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastStoredTrackPoint != null && trackPoint.isMoving() != lastStoredTrackPoint.isMoving()) {
|
if (!trackPoint.hasLocation() && !trackPoint.hasSensorDistance()) {
|
||||||
|
Log.d(TAG, "Ignoring TrackPoint as it has no distance.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TrackPoint distanceTo = lastStoredTrackPoint;
|
||||||
|
if (trackPoint.hasLocation() && !lastStoredTrackPoint.hasLocation()) {
|
||||||
|
distanceTo = lastStoredTrackPointWithLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
Distance distanceToLastStoredTrackPoint = trackPoint.distanceToPrevious(distanceTo);
|
||||||
|
if (distanceToLastStoredTrackPoint.greaterThan(maxRecordingDistance)) {
|
||||||
|
trackPoint.setType(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
|
||||||
|
insertTrackPoint(trackId, trackPoint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distanceToLastStoredTrackPoint.greaterOrEqualThan(recordingDistanceInterval)
|
||||||
|
&& trackPoint.isMoving()) {
|
||||||
|
insertTrackPoint(trackId, trackPoint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trackPoint.isMoving() != lastStoredTrackPoint.isMoving()) {
|
||||||
// Moving from non-moving to moving or vice versa; required to compute moving time correctly.
|
// Moving from non-moving to moving or vice versa; required to compute moving time correctly.
|
||||||
insertTrackPoint(trackId, trackPoint);
|
insertTrackPoint(trackId, trackPoint);
|
||||||
return true;
|
return true;
|
||||||
@@ -206,6 +198,7 @@ class TrackRecordingManager {
|
|||||||
|
|
||||||
Log.d(TAG, "Not recording TrackPoint");
|
Log.d(TAG, "Not recording TrackPoint");
|
||||||
lastTrackPoint = trackPoint;
|
lastTrackPoint = trackPoint;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +206,7 @@ class TrackRecordingManager {
|
|||||||
return trackStatisticsUpdater.getTrackStatistics();
|
return trackStatisticsUpdater.getTrackStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO Should be only be called from onNewTrackPoint().
|
||||||
private void insertTrackPoint(@NonNull Track.Id trackId, @NonNull TrackPoint trackPoint) {
|
private void insertTrackPoint(@NonNull Track.Id trackId, @NonNull TrackPoint trackPoint) {
|
||||||
if (lastTrackPoint != null) {
|
if (lastTrackPoint != null) {
|
||||||
if (lastStoredTrackPoint != null && lastTrackPoint.getTime().equals(lastStoredTrackPoint.getTime())) {
|
if (lastStoredTrackPoint != null && lastTrackPoint.getTime().equals(lastStoredTrackPoint.getTime())) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import java.time.Instant;
|
|||||||
import de.dennisguse.opentracks.content.data.Altitude;
|
import de.dennisguse.opentracks.content.data.Altitude;
|
||||||
import de.dennisguse.opentracks.content.data.Distance;
|
import de.dennisguse.opentracks.content.data.Distance;
|
||||||
import de.dennisguse.opentracks.content.data.Speed;
|
import de.dennisguse.opentracks.content.data.Speed;
|
||||||
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Statistical data about a {@link de.dennisguse.opentracks.content.data.Track}.
|
* Statistical data about a {@link de.dennisguse.opentracks.content.data.Track}.
|
||||||
@@ -161,6 +162,7 @@ public class TrackStatistics {
|
|||||||
|
|
||||||
public void setStopTime(Instant stopTime) {
|
public void setStopTime(Instant stopTime) {
|
||||||
if (stopTime.isBefore(startTime)) {
|
if (stopTime.isBefore(startTime)) {
|
||||||
|
// Time must be monotonically increasing, but we might have events at the same point in time (BLE and GPS)
|
||||||
throw new RuntimeException("stopTime cannot be less than startTime: " + startTime + " " + stopTime);
|
throw new RuntimeException("stopTime cannot be less than startTime: " + startTime + " " + stopTime);
|
||||||
}
|
}
|
||||||
this.stopTime = stopTime;
|
this.stopTime = stopTime;
|
||||||
@@ -199,8 +201,15 @@ public class TrackStatistics {
|
|||||||
this.movingTime = movingTime;
|
this.movingTime = movingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addMovingTime(TrackPoint trackPoint, TrackPoint lastTrackPoint) {
|
||||||
|
addMovingTime(Duration.between(lastTrackPoint.getTime(), trackPoint.getTime()));
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||||
public void addMovingTime(Duration time) {
|
public void addMovingTime(Duration time) {
|
||||||
|
if (time.isNegative()) {
|
||||||
|
throw new RuntimeException("Moving time cannot be negative");
|
||||||
|
}
|
||||||
movingTime = movingTime.plus(time);
|
movingTime = movingTime.plus(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,23 +148,19 @@ public class TrackStatisticsUpdater {
|
|||||||
if (trackPoint.hasSensorDistance()) {
|
if (trackPoint.hasSensorDistance()) {
|
||||||
// Sensor-based distance/speed
|
// Sensor-based distance/speed
|
||||||
currentSegment.addTotalDistance(trackPoint.getSensorDistance());
|
currentSegment.addTotalDistance(trackPoint.getSensorDistance());
|
||||||
} else if (lastTrackPoint != null && trackPoint.isMoving()) {
|
} else if (lastTrackPoint != null
|
||||||
|
&& lastTrackPoint.hasLocation()
|
||||||
|
&& trackPoint.hasLocation() && trackPoint.isMoving()) {
|
||||||
// GPS-based distance/speed
|
// GPS-based distance/speed
|
||||||
// Assumption: we ignore TrackPoints that are not moving as those are likely imprecise GPS measurements
|
// Assumption: we ignore TrackPoints that are not moving as those are likely imprecise GPS measurements
|
||||||
Distance movingDistance = trackPoint.distanceToPrevious(lastTrackPoint);
|
Distance movingDistance = trackPoint.distanceToPrevious(lastTrackPoint);
|
||||||
if (movingDistance != null) {
|
currentSegment.addTotalDistance(movingDistance);
|
||||||
currentSegment.addTotalDistance(movingDistance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Update moving time
|
// Update moving time
|
||||||
if (trackPoint.isMoving() && lastTrackPoint != null && lastTrackPoint.isMoving()) {
|
if (trackPoint.isMoving() && lastTrackPoint != null && lastTrackPoint.isMoving()) {
|
||||||
Duration movingTime = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime());
|
currentSegment.addMovingTime(trackPoint, lastTrackPoint);
|
||||||
if (movingTime.isNegative()) {
|
|
||||||
throw new RuntimeException("Moving time cannot be negative");
|
|
||||||
}
|
|
||||||
currentSegment.addMovingTime(movingTime);
|
|
||||||
|
|
||||||
// Update max speed
|
// Update max speed
|
||||||
updateSpeed(trackPoint, lastTrackPoint);
|
updateSpeed(trackPoint, lastTrackPoint);
|
||||||
|
|||||||
Reference in New Issue
Block a user