Skip to content

Instantly share code, notes, and snippets.

@grigory-rechistov
Last active August 21, 2019 16:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grigory-rechistov/fb7597e9cc7dd26010c3042abcf20b9b to your computer and use it in GitHub Desktop.
Save grigory-rechistov/fb7597e9cc7dd26010c3042abcf20b9b to your computer and use it in GitHub Desktop.
Randomize GPX trajectory in space and time
#!/usr/bin/python
# TODO: port to Python3
# Take an input GPX track and generate a series of identical tracks
# shifted in time and with noise added to individual points' coordinates and
# timestamps.
import xml.etree.ElementTree as ET
from sys import argv
from random import random
from datetime import datetime
from datetime import timedelta
from dateutil import parser as date_parser
from dateutil.rrule import DAILY, rrule, MO, TU, WE, TH, FR
def daterange(start_date, end_date):
# return only working days in the region
# I did not work much on Fridays, so exclude it
return rrule(DAILY, dtstart=start_date, until=end_date, byweekday=(MO,TU,WE,TH)) # FR
def get_noise(percentage = 0.5):
return 1.0 + (random() - 0.5) * percentage / 100.0
# TODO only the last register_namespace takes effect?
ET.register_namespace('', "http://www.topografix.com/GPX/1/1")
ET.register_namespace('', "http://www.topografix.com/GPX/1/0")
ET.register_namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
et = ET.parse(argv[1])
root = et.getroot()
script = open("batch-upload.sh", "w")
script.write("#!/bin/sh\n")
script.write("set -e\n")
# morning track
start_date = datetime(2019, 2, 1, 8, 00, 00)
end_date = datetime(2019, 8, 20, 8, 45, 00)
# evening track
#start_date = datetime(2018, 2, 1, 16, 30, 00)
#end_date = datetime(2019, 8, 20, 16, 45, 00)
for new_date in daterange(start_date, end_date):
global_time_shift = (random() - 0.5) * 3600 # plus minus half hour
first_time = None
for item in root.iter():
if item.tag.find("name") != -1:
item.text = "Commute " + new_date.isoformat()
print "Working with", item.text
if item.tag.find("trkpt") != -1: # tag contains stupid namespace prefix
lat = float(item.attrib['lat'])
lon = float(item.attrib['lon'])
lat *= get_noise(0.0001)
lon *= get_noise(0.0001)
item.attrib['lat'] = str(lat)
item.attrib['lon'] = str(lon)
if item.tag.find("ele") != -1:
ele = float(item.text)
ele *= get_noise(5.0)
item.text = str(ele)
if item.tag.find("time") != -1:
old_time = date_parser.parse(item.text)
if first_time is None:
first_time = old_time
path_delta = old_time - first_time
local_shift = (random() - 0.5) * 0.05
noise_delta = (timedelta(seconds=global_time_shift) +
timedelta(seconds=local_shift))
new_time = new_date + path_delta + noise_delta
item.text = new_time.isoformat()
# Write back to file
newfname = "commute-" + new_date.strftime("%s") + ".gpx"
et.write(newfname)
script.write("~/workspace/stravacli/stravaup.py --no-popup --xml-desc --activity-type ride %s\n" % (newfname))
script.write("sleep 3\n")
script.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment