Add a way to playback GPX tracks as mock locations
This commit is contained in:
parent
3685c4bf92
commit
7a7cd21376
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@ yarn-error.log*
|
|||||||
.zanata-cache
|
.zanata-cache
|
||||||
po/*.po
|
po/*.po
|
||||||
po/*.pot
|
po/*.pot
|
||||||
|
tests/*.gpx
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.idea
|
.idea
|
||||||
|
@ -141,6 +141,12 @@ python -m server
|
|||||||
|
|
||||||
to spawn the server-side part, listening on `localhost:8081`.
|
to spawn the server-side part, listening on `localhost:8081`.
|
||||||
|
|
||||||
|
### Useful scripts for dev
|
||||||
|
|
||||||
|
You can run `scripts/gps_to_gpx.py` on your GPX trace to create a
|
||||||
|
`src/tools/mock_gpx.json` file ready to be used as a mocking source for the
|
||||||
|
position data (just edit the `src/constants.js` file accordingly).
|
||||||
|
|
||||||
|
|
||||||
## Translating
|
## Translating
|
||||||
|
|
||||||
|
34
scripts/gps_to_js.py
Normal file
34
scripts/gps_to_js.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import gpxpy
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
sys.exit('Usage: %s GPX_FILE' % sys.argv[0])
|
||||||
|
|
||||||
|
with open (sys.argv[1], 'r') as fh:
|
||||||
|
gpx = gpxpy.parse(fh)
|
||||||
|
|
||||||
|
json_out = []
|
||||||
|
for track in gpx.tracks:
|
||||||
|
for segment in track.segments:
|
||||||
|
for point in segment.points:
|
||||||
|
# TODO: Other fields
|
||||||
|
json_out.append({
|
||||||
|
'time': point.time.isoformat(),
|
||||||
|
'coords': {
|
||||||
|
'accuracy': point.horizontal_dilution,
|
||||||
|
'altitudeAccuracy': point.vertical_dilution,
|
||||||
|
'heading': None,
|
||||||
|
'latitude': point.latitude,
|
||||||
|
'longitude': point.longitude
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break
|
||||||
|
break
|
||||||
|
|
||||||
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
with open(os.path.join(script_dir, '../src/tools/mock_gpx.json'), 'w') as fh:
|
||||||
|
json.dump(json_out, fh)
|
@ -113,7 +113,21 @@ export const REPORT_TYPES_ORDER = ['gcum', 'interrupt', 'obstacle', 'pothole', '
|
|||||||
export const MIN_DISTANCE_REPORT_DETAILS = 40; // in meters
|
export const MIN_DISTANCE_REPORT_DETAILS = 40; // in meters
|
||||||
|
|
||||||
export const MOCK_LOCATION = false;
|
export const MOCK_LOCATION = false;
|
||||||
|
export const MOCK_LOCATION_USE_GPX = true;
|
||||||
|
export const MOCK_LOCATION_GPX_PLAYBACK_SPEED = 2.0;
|
||||||
export const MOCK_LOCATION_UPDATE_INTERVAL = 5 * 1000; // in milliseconds
|
export const MOCK_LOCATION_UPDATE_INTERVAL = 5 * 1000; // in milliseconds
|
||||||
|
// Small area in Montrouge
|
||||||
|
export const MOCK_LOCATION_LAT_MIN = 48.81788;
|
||||||
|
export const MOCK_LOCATION_LNG_MIN = 2.31723;
|
||||||
|
export const MOCK_LOCATION_LAT_MAX = 48.81952;
|
||||||
|
export const MOCK_LOCATION_LNG_MAX = 2.32077;
|
||||||
|
// Paris
|
||||||
|
/*
|
||||||
|
export const MOCK_LOCATION_LAT_MIN = 48.854031;
|
||||||
|
export const MOCK_LOCATION_LNG_MIN = 2.281279;
|
||||||
|
export const MOCK_LOCATION_LAT_MAX = 48.886123;
|
||||||
|
export const MOCK_LOCATION_LNG_MAX = 2.392742;
|
||||||
|
*/
|
||||||
|
|
||||||
export const UPDATE_REPORTS_DISTANCE_THRESHOLD = 500; // in meters
|
export const UPDATE_REPORTS_DISTANCE_THRESHOLD = 500; // in meters
|
||||||
|
|
||||||
|
@ -1,4 +1,18 @@
|
|||||||
import { EARTH_RADIUS } from '@/constants';
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import {
|
||||||
|
EARTH_RADIUS,
|
||||||
|
MOCK_LOCATION_GPX_PLAYBACK_SPEED,
|
||||||
|
MOCK_LOCATION_UPDATE_INTERVAL,
|
||||||
|
MOCK_LOCATION_USE_GPX,
|
||||||
|
MOCK_LOCATION_LAT_MIN, MOCK_LOCATION_LAT_MAX,
|
||||||
|
MOCK_LOCATION_LNG_MIN, MOCK_LOCATION_LNG_MAX,
|
||||||
|
} from '@/constants';
|
||||||
|
|
||||||
|
let mockGPX = null;
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
mockGPX = require('@/tools/mock_gpx.json'); // eslint-disable-line global-require
|
||||||
|
}
|
||||||
|
|
||||||
export function distance(latLng1, latLng2) {
|
export function distance(latLng1, latLng2) {
|
||||||
const lat1 = (latLng1[0] * Math.PI) / 180;
|
const lat1 = (latLng1[0] * Math.PI) / 180;
|
||||||
@ -16,21 +30,7 @@ export function distance(latLng1, latLng2) {
|
|||||||
return EARTH_RADIUS * c;
|
return EARTH_RADIUS * c;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockLocation() {
|
export function mockLocationRandom() {
|
||||||
// Over Paris
|
|
||||||
/*
|
|
||||||
const LAT_MIN = 48.854031;
|
|
||||||
const LNG_MIN = 2.281279;
|
|
||||||
const LAT_MAX = 48.886123;
|
|
||||||
const LNG_MAX = 2.392742;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Over small area
|
|
||||||
const LAT_MIN = 48.81788;
|
|
||||||
const LNG_MIN = 2.31723;
|
|
||||||
const LAT_MAX = 48.81952;
|
|
||||||
const LNG_MAX = 2.32077;
|
|
||||||
|
|
||||||
let heading = null;
|
let heading = null;
|
||||||
if (Math.random() > 0.25) {
|
if (Math.random() > 0.25) {
|
||||||
heading = Math.random() * 360;
|
heading = Math.random() * 360;
|
||||||
@ -38,8 +38,14 @@ export function mockLocation() {
|
|||||||
const newLocation = {
|
const newLocation = {
|
||||||
coords: {
|
coords: {
|
||||||
accuracy: 10, // In meters
|
accuracy: 10, // In meters
|
||||||
latitude: (Math.random() * (LAT_MAX - LAT_MIN)) + LAT_MIN,
|
latitude: (
|
||||||
longitude: (Math.random() * (LNG_MAX - LNG_MIN)) + LNG_MIN,
|
(Math.random() * (MOCK_LOCATION_LAT_MAX - MOCK_LOCATION_LAT_MIN))
|
||||||
|
+ MOCK_LOCATION_LAT_MIN
|
||||||
|
),
|
||||||
|
longitude: (
|
||||||
|
(Math.random() * (MOCK_LOCATION_LNG_MAX - MOCK_LOCATION_LNG_MIN))
|
||||||
|
+ MOCK_LOCATION_LNG_MIN
|
||||||
|
),
|
||||||
heading,
|
heading,
|
||||||
},
|
},
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
@ -48,6 +54,32 @@ export function mockLocation() {
|
|||||||
return newLocation;
|
return newLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function mockLocationWithGPX(index, setPosition) {
|
||||||
|
setPosition(mockGPX[index]);
|
||||||
|
if (index < mockGPX.length) {
|
||||||
|
const delay = (
|
||||||
|
moment(mockGPX[index + 1].time).valueOf()
|
||||||
|
- moment(mockGPX[index].time).valueOf()
|
||||||
|
);
|
||||||
|
setTimeout(
|
||||||
|
() => mockLocationWithGPX(index + 1, setPosition),
|
||||||
|
delay / MOCK_LOCATION_GPX_PLAYBACK_SPEED,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mockLocation(setPosition) {
|
||||||
|
if (MOCK_LOCATION_USE_GPX) {
|
||||||
|
mockLocationWithGPX(0, setPosition);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
setPosition(mockLocationRandom());
|
||||||
|
return setInterval(
|
||||||
|
() => setPosition(mockLocationRandom()),
|
||||||
|
MOCK_LOCATION_UPDATE_INTERVAL,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function storageAvailable(type) {
|
export function storageAvailable(type) {
|
||||||
let storage;
|
let storage;
|
||||||
try {
|
try {
|
||||||
|
1
src/tools/mock_gpx.json
Normal file
1
src/tools/mock_gpx.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
@ -166,11 +166,7 @@ export default {
|
|||||||
// Set up a watcher
|
// Set up a watcher
|
||||||
let watchID = null;
|
let watchID = null;
|
||||||
if (constants.MOCK_LOCATION) {
|
if (constants.MOCK_LOCATION) {
|
||||||
setPosition(mockLocation());
|
watchID = mockLocation(setPosition);
|
||||||
watchID = setInterval(
|
|
||||||
() => setPosition(mockLocation()),
|
|
||||||
constants.MOCK_LOCATION_UPDATE_INTERVAL,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
if (!('geolocation' in navigator)) {
|
if (!('geolocation' in navigator)) {
|
||||||
const $t = this.$t.bind(this);
|
const $t = this.$t.bind(this);
|
||||||
|
0
tests/.gitkeep
Normal file
0
tests/.gitkeep
Normal file
Loading…
Reference in New Issue
Block a user