Skip to content

Instantly share code, notes, and snippets.

@oldnapalm
Last active May 9, 2023 22:50
Show Gist options
  • Select an option

  • Save oldnapalm/89ad17d0768f86197f85ed6a1cfae0ae to your computer and use it in GitHub Desktop.

Select an option

Save oldnapalm/89ad17d0768f86197f85ed6a1cfae0ae to your computer and use it in GitHub Desktop.
Create a GTBikeV course from a FIT file
import os
import sys
import argparse
import fitdecode
import json
import math
import folium
parser = argparse.ArgumentParser()
parser.add_argument('--input', '-i', type=str, required=True)
parser.add_argument('--output', '-o', type=str, required=False, default='1000-1.0.json')
parser.add_argument('--name', '-n', type=str, required=False, default='fit2json.py course')
parser.add_argument('--step', '-s', type=int, required=False, default=10)
parser.add_argument('--non-routed', dest='routed', action='store_false')
args = parser.parse_args()
def point(c):
p = {'X': c[0], 'Y': c[1], 'Z': c[2]}
if not args.routed:
p['Routed'] = 'False'
return p
def deg_to_rad(deg):
return deg * math.pi / 180
def distance(orig, dest):
lat_orig = deg_to_rad(orig[0])
lat_dest = deg_to_rad(dest[0])
diff_lat = lat_dest - lat_orig
diff_long = deg_to_rad(dest[1]) - deg_to_rad(orig[1])
a = math.sin(diff_lat / 2) * math.sin(diff_lat / 2) + math.cos(lat_orig) * math.cos(lat_dest) * math.sin(diff_long / 2) * math.sin(diff_long / 2)
return 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) * 6378137
def bearing(orig, dest):
lat_orig = deg_to_rad(orig[0])
lat_dest = deg_to_rad(dest[0])
diff_long = deg_to_rad(dest[1]) - deg_to_rad(orig[1])
y = math.sin(diff_long) * math.cos(lat_dest)
x = math.cos(lat_orig) * math.sin(lat_dest) - math.sin(lat_orig) * math.cos(lat_dest) * math.cos(diff_long)
return math.atan2(y, x) + math.pi / 2
initial_gps_point = (-19.10637, -169.871)
slope_scale = 0.5
coords = []
if os.path.isfile(args.input):
with fitdecode.FitReader(args.input) as fit:
for i, frame in enumerate(fit):
if frame.frame_type == fitdecode.FIT_FRAME_DATA and frame.name == 'record':
if i > 0 and i % args.step != 0:
continue
lat = frame.get_value('position_lat') / 11930465
long = frame.get_value('position_long') / 11930465
d = distance((lat, long), initial_gps_point)
b = -1 * bearing((lat, long), initial_gps_point)
lat = round(d * math.cos(b), 2)
long = round(d * math.sin(b), 2)
if coords and distance((lat,long), coords[-1]) < 1000000:
continue
coords.append((lat, long, round(frame.get_value('altitude') / slope_scale, 2)))
else:
print('File %s not found.' % args.input)
sys.exit()
data = {}
data['Name'] = args.name
data['WayPointConfig'] = {'Color': '00000000', 'Radius': 0.0}
data['StartPoint'] = point(coords[0])
data['Props'] = []
data['WayPointList'] = []
for c in coords[1:]:
data['WayPointList'].append(point(c))
with open(args.output, 'w') as f:
json.dump(data, f, indent=2)
m = folium.Map(location=[-50, 50], min_zoom=3, max_zoom=7, zoom_start=4, crs='Simple', tiles=None)
satellite = folium.TileLayer(min_zoom=3, max_zoom=7, zoom_start=4, tiles='https://cdn.mapgenie.io/images/tiles/gta5/los-santos/satellite/{z}/{x}/{y}.png', attr='<a href="https://mapgenie.io/">Map Genie</a>')
satellite.layer_name = "Satellite"
satellite.add_to(m)
atlas = folium.TileLayer(min_zoom=3, max_zoom=7, zoom_start=4, tiles='https://cdn.mapgenie.io/images/tiles/gta5/los-santos/atlas/{z}/{x}/{y}.png', attr='<a href="https://mapgenie.io/">Map Genie</a>')
atlas.layer_name = "Atlas"
atlas.add_to(m)
road = folium.TileLayer(min_zoom=3, max_zoom=7, zoom_start=4, tiles='https://cdn.mapgenie.io/images/tiles/gta5/los-santos/road/{z}/{x}/{y}.png', attr='<a href="https://mapgenie.io/">Map Genie</a>')
road.layer_name = "Road"
road.add_to(m)
folium.map.LayerControl().add_to(m)
for i, c in enumerate(coords):
folium.Marker(location=[c[1] * 0.00691 - 58, c[0] * 0.00691 + 39.4], popup='%s %s %s' % (i, c[0], c[1])).add_to(m)
m.save('%s.html' % os.path.splitext(args.output)[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment