TurboGPS
Turbo GPS | |
---|---|
Author: | Michael Chourdakis |
License: | Proprietary |
Platforms: | Windows, Windows Mobile, and Android |
Status: | Broken |
Version: | 2.73 (2012-09-07) |
Languages: | German, English, and ... |
Website: | http://www.turboirc.com/tgps/ |
TurboGPS is a fast all in one GPS tool. Moving maps custom or online, tracks, way points. |
TurboGPS (turboirc.com/tgps) is a fast all in one GPS tool. Moving maps custom or online, tracks, way points, there is a PC and Windows Mobile Version.
Features
- Moving Map
- Map Format: JPG / Download tool for OpenStreetMap and Google Maps
- Record Tracks and Export in GPX Format
- Way points add/import/export function
- Calibrating Raster Images
- Day, Night and custom View
- Today plugin
- ...and much more check the homepage
Android Version
The Android version of Turbo GPS now supports OpenStreetMap directly without the need of the taho script. The following information is for the WM/PPC version.
In the Android version, use menu->maps->OSM Maps and Turbo GPS will automatically cache to SD card the tiles you will browse to.
Licence & Support
Freeware. Here you can support the project.
Screenshots
Wish List
Please go to the Discussion page.
Get the OSM map
- The taho.pl script has a option to generate directly calibrated maps to use in TurboGPS.
Example: taho.pl -coord="10,47.54,7.58" -coord2="47.48,7.66" -turbogps=yes
For Windows users the faster way would be to use the taho.exe. In the screen you have to choose the filename with the Coordinates.
Both tools you can finde here: Taho
This generated in the /map directory files like this:
7.55859375_47.4874452560027_7.6025390625_47.4577407945593_1024_1024.png
To get these filename you have to select "Koord." not "Nr." as in the picture above!!!
Maps in the Turbo GPS Application even the Cyclemap
Python tile downloader
This program downloads tiles from OSM and saves them ready for use in TGPS. I created it because the various Windows TaHo programs didn't work for me, and I couldn't get the Perl script to work. It prints out usage instructions if invoked without arguments. Needs PyPNG to be installed.
#!/usr/bin/env python
#grabs tiles from OSM and converts to TGPS tiles
#invoke with no arguments for usage help
#needs PyPNG to be installed
try: #just cosmetics.
import png
except ImportError:
print "Error: Couldn't import PyPNG."
print "Please visit http://code.google.com/p/pypng/ to download and install."
exit()
import urllib2
import os
import math
import sys
import re
#copied from http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Python
def deg2num(lat_deg, lon_deg, zoom):
lat_rad = math.radians(lat_deg)
n = 2.0 ** zoom
xtile = int((lon_deg + 180.0) / 360.0 * n)
ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
return(xtile, ytile)
def num2deg(xtile, ytile, zoom):
n = 2.0 ** zoom
lon_deg = xtile / n * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
lat_deg = math.degrees(lat_rad)
return(lat_deg, lon_deg)
#pastes image2 to the right of image1. height needs to be identical for both images
def pasteRight(image1, image2):
if image1 == []:
return image2
else:
image = []
if not len(image1) == len(image2):
return image
else:
for i in range(0,len(image1)):
image.append(image1[i] + image2[i])
return image
#pastes image2 to the bottom of image1. width should probably be identical for both
def pasteBottom(image1, image2):
if image1 == []:
return image2
else:
for i in range(0,len(image2)):
image1.append(image2[i])
return image1
#expects a PyPNG.Reader object, returns list
def generateList(pngdata):
image = []
for line in pngdata[2]:
image.append(line)
return image
#gets the relevant OSM tile. Downloads if tile isn't in store, else, checks it out
def getOSMTile(x, y, zoom, base_url, tilestore):
tilestore_file = str(y) + ".png"
tilestore_path = os.path.join(tilestore, str(x))
touchPath(tilestore_path)
filename = os.path.join(tilestore_path, tilestore_file)
if os.path.exists(filename): #tile is in store
print "\tChecking out " + filename
file = open(filename, 'rb')
pngreader = png.Reader(file)
return generateList(pngreader.asRGBA8())
else: #tile is not in store, download and save
url = base_url + "/" + str(zoom) + "/" + str(x) + "/" + str(y) + ".png"
print "\tDownloading " + url
pngreader = png.Reader(file = urllib2.urlopen(url))
pngdata = generateList(pngreader.asRGBA8())
file = open(filename, 'wb')
pngwriter = png.Writer(256, 256, greyscale = False, bitdepth = 8, compression = 9, alpha = True)
pngwriter.write(file, pngdata)
return pngdata
#comparable to *nix 'touch', but for paths
def touchPath(directory):
try:
os.mkdir(directory)
except OSError:
pass
#gets and saves a map part
def getMapPart(xpos, ypos, num_tiles, outputdir, base_url, mapsize, zoom, tilestore):
t_lat1, t_lon1 = num2deg(xpos, ypos, zoom)
t_lat2, t_lon2 = num2deg(xpos + num_tiles, ypos + num_tiles, zoom)
filename = "{:6f}_{:6f}_{:6f}_{:6f}_{}_{}.png".format(t_lon1, t_lat1, t_lon2, t_lat2, mapsize, mapsize)
if os.path.exists(os.path.join(outputdir, filename)):
print "Skipping existing part {}".format(filename)
return
image = []
for i in range(0,num_tiles):
column = []
for j in range(0,num_tiles):
pngdata = getOSMTile(xpos + i, ypos + j, zoom, base_url, tilestore)
column = pasteBottom(column, pngdata)
image = pasteRight(image, column)
print "Writing " + filename
file = open(os.path.join(outputdir,filename), 'wb')
pngwriter = png.Writer(mapsize, mapsize, greyscale = False, bitdepth = 8, compression = 9, alpha = True)
pngwriter.write(file, image)
file.close()
def main():
try:#this is to catch Ctrl+C
#saves base_url and max_zoom of supported renderers, edit here to add renderer.
#entries are [base_url, max_zoom, descriptive_name]
renderers = {'osma': ["http://tah.openstreetmap.org/Tiles/tile", 17, "Osmarender"], 'mapnik': ["http://tile.openstreetmap.org", 18, "Mapnik"], 'cycle': ["http://andy.sandbox.cloudmade.com/tiles/cycle", 18, "Cyclemap"]}
num_tiles = 2
mapsize = 512
overlap = False
base_url = ""
renderer_name = ""
zoom = 0
outputdir = ""
bb_found = False
for count in range(1, len(sys.argv)):
#renderer:
argument = re.search("^renderer=(osma|mapnik|cycle)(?i)", sys.argv[count])
if argument is not None:
base_url = renderers[argument.group(1)][0]
max_zoom = renderers[argument.group(1)][1]
renderer_name = renderers[argument.group(1)][2]
renderer = argument.group(1)
#coords:
argument = re.search("^bbox=([-0-9.]+),([-0-9.]+),([-0-9.]+),([-0-9.]+)(?i)", sys.argv[count])
if argument is not None:
bb_found = True
lat1 = float(argument.group(1))
lon1 = float(argument.group(2))
lat2 = float(argument.group(3))
lon2 = float(argument.group(4))
#zoom:
argument = re.search("^zoom=(\d+)(?i)", sys.argv[count])
if argument is not None:
zoom = int(argument.group(1))
if zoom > max_zoom:
zoom = max_zoom
elif zoom < 0:
zoom = 0
#mapsize:
argument = re.search("^size=(\d+)(?i)", sys.argv[count])
if argument is not None:
num_tiles = int(argument.group(1))
if num_tiles < 1:
num_tiles = 1
mapsize = 256 * num_tiles
#outputdir:
argument = re.search("^outputdir=([^ ]+)(?i)", sys.argv[count])
if argument is not None:
outputdir = argument.group(1)
touchPath(outputdir)
#overlap:
argument = re.search("^overlap=(\d+)(?i)", sys.argv[count])
if argument is not None:
overlap = True
overlap_by = int(argument.group(1))
#a wrong number of arguments was given, display help
if base_url == "" or not bb_found or outputdir == "" or zoom == 0:
print "Error: Wrong number of arguments. Usage:\n{} renderer=name bbox=lat1,lon1,lat2,lon2 zoom=z outputdir=dir\n\t[size=x] [overlap=y]\n".format(sys.argv[0])
print "\trenderer: Chooses the renderer.\n\t\tName must be one of osma, mapnik or cycle."
print "\tbbox: defines the bounding box of the\n\t\tmap section to download."
print "\tzoom: sets the zoomlevel, range depends on renderer."
print "\toutputdir: directory to write the output."
print "\tsize: created map parts are made of x*x OSM tiles.\n\t\tDefault is 2, range is 1 <= x < infinity."
print "\toverlap: if argument is present, additional overlapping map parts\n\t\twill be downloaded for smoother scrolling."
print "\t\tDepending on size, this could result in many\n\t\t'Skipped existing part'- messages."
print "\t\tThis downloads 8*size/y additional parts per map part,\n\t\tso download time will be considerably longer."
print "\n\tIn addition to the output directory, the directory ./tilestore\n\twill be created. Don't delete that directory\n\tif you plan to create maps of the same area later."
exit()
#setup tilestore
tilestore = "tilestore"
touchPath(tilestore)
tilestore = os.path.join(tilestore, renderer)
touchPath(tilestore)
tilestore = os.path.join(tilestore, str(zoom))
touchPath(tilestore)
#print interpreted parameters
print "About to start downloading {} tiles.".format(renderer_name)
print "Bounding box is {},{} * {},{}\n\tat zoom level {}.".format(lat1, lon1, lat2, lon2, zoom)
print "Map parts are {}*{}px, using {} OSM tiles per part.".format(mapsize, mapsize, num_tiles*num_tiles)
if overlap:
print "Per map part, {} overlapping map parts will be downloaded.".format(len(range(0 + overlap_by, num_tiles + 1, overlap_by)))
print "Output directory is {}".format(outputdir)
print "Starting..."
#this is the fun part
x1, y1 = deg2num(lat1, lon1, zoom)
x2, y2 = deg2num(lat2, lon2, zoom)
for ypos in range(y1, y2, num_tiles):
for xpos in range(x1, x2, num_tiles):
getMapPart(xpos, ypos, num_tiles, outputdir, base_url, mapsize, zoom, tilestore)
if overlap: #get the 8*size/overlap_by additional map parts
for overlap_tile in range(0 + overlap_by, num_tiles + 1, overlap_by):
getMapPart(xpos + overlap_tile, ypos + overlap_tile, num_tiles, outputdir, base_url, mapsize, zoom, tilestore)
getMapPart(xpos, ypos + overlap_tile, num_tiles, outputdir, base_url, mapsize, zoom, tilestore)
getMapPart(xpos + overlap_tile, ypos, num_tiles, outputdir, base_url, mapsize, zoom, tilestore)
getMapPart(xpos - num_tiles / 2, ypos - overlap_tile, num_tiles, outputdir, base_url, mapsize, zoom, tilestore)
getMapPart(xpos, ypos - overlap_tile, num_tiles, outputdir, base_url, mapsize, zoom, tilestore)
getMapPart(xpos - overlap_tile, ypos, num_tiles, outputdir, base_url, mapsize, zoom, tilestore)
getMapPart(xpos + overlap_tile, ypos - overlap_tile, num_tiles, outputdir, base_url, mapsize, zoom, tilestore)
getMapPart(xpos - overlap_tile, ypos + overlap_tile, num_tiles, outputdir, base_url, mapsize, zoom, tilestore)
print "Finished."
except KeyboardInterrupt:
print "Aborted by user. Finished."
if __name__ == "__main__":
main()
Get the tracks
Menu: <Tools><Track Record><Start recording>
Options appear. Try speed 1 Km/h and Turn 10 Degree
At the end: <Tool><Track Record><End recording>
Do not normalise as this seams to corrupt file.
Before Exporting optionally <View> <Tracks> <Edit> <Rename>
To export: <View><Tracks> select the Track and export in GXP Format. press <NO> to save as Track.
Save on external card, if possible.