TurboGPS

From OpenStreetMap Wiki
Jump to: navigation, search
Available languages — TurboGPS
· Afrikaans · Alemannisch · aragonés · asturianu · azərbaycanca · Bahasa Indonesia · Bahasa Melayu · Bân-lâm-gú · Basa Jawa · Baso Minangkabau · bosanski · brezhoneg · català · čeština · dansk · Deutsch · eesti · English · español · Esperanto · estremeñu · euskara · français · Frysk · Gaeilge · Gàidhlig · galego · Hausa · hrvatski · Igbo · interlingua · Interlingue · isiXhosa · isiZulu · íslenska · italiano · Kiswahili · Kreyòl ayisyen · kréyòl gwadloupéyen · Kurdî · latviešu · Lëtzebuergesch · lietuvių · magyar · Malagasy · Malti · Nederlands · Nedersaksies · norsk bokmål · norsk nynorsk · occitan · Oromoo · oʻzbekcha/ўзбекча · Plattdüütsch · polski · português · português do Brasil · română · shqip · slovenčina · slovenščina · Soomaaliga · suomi · svenska · Tiếng Việt · Türkçe · Vahcuengh · vèneto · Wolof · Yorùbá · Zazaki · српски / srpski · беларуская · български · қазақша · македонски · монгол · русский · тоҷикӣ · українська · Ελληνικά · Հայերեն · ქართული · नेपाली · मराठी · हिन्दी · অসমীয়া · বাংলা · ਪੰਜਾਬੀ · ગુજરાતી · ଓଡ଼ିଆ · தமிழ் · తెలుగు · ಕನ್ನಡ · മലയാളം · සිංහල · ไทย · မြန်မာဘာသာ · ລາວ · ភាសាខ្មែរ · ⵜⴰⵎⴰⵣⵉⵖⵜ · አማርኛ · 한국어 · 日本語 · 中文(简体)‎ · 吴语 · 粵語 · 中文(繁體)‎ · ייִדיש · עברית · اردو · العربية · پښتو · سنڌي · فارسی · ދިވެހިބަސް
Turbo GPS
Screenshot of Turbo GPS
Authors: Michael Chourdakis
Website: http://www.turboirc.com/tgps/
Version: 2.73 (2012-09-07)
License: free
Platforms: Windows, Windows Mobile, and Android

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

Tgps 01.jpg Tgps 02.jpg Tgps 03.jpg
Tgps 04.jpg Tgps 05.jpg Tgps 06.jpg

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.

Taho.exe export.png

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

Turbogps oms cap1.jpg Turbogps oms cap2.jpg Turbogps oms cap3.jpg

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.

Links