I am seeking opinions as to whether anyone is interested in a SOTA layer file for OsmAnd.
OsmAnd is a full-featured mapping program for Android. It uses the free OSM data to draw maps on your screen, and also provide search and navigation functions. The OSM data is downloaded to your Android device and rendered locally, i.e. once you have the data you don’t need an internet connection to draw maps or navigate.
I have been curious about how to make my own POI layer file for OsmAnd to overlay on top of everything else. The documentation is a bit sparse, but I finally got something working.
Step 1) Make an OSM XML file containing POI information. It looks a bit like this:
<?xml version='1.0' encoding='UTF-8'?>
Step 2) Process this file with OsmAnd Map Creator (using the Build POI Index option only) and create an .obf file.
Step 3) Copy the .obf file to the OsmAnd directory on your phone.
If you download the summits.csv file (containing all summit information) the first step can be done with a small Python script I wrote. The second step can be manual or automated.
Is anyone using OsmAnd who would like a layer file? I will deal with the first six requests (please tell me Association and Region). If there are a huge number then I’ll have to automate it. If there is a small number I’ll just keep it to myself.
My solution is simple, needs no programming: OruxMaps can display map overlays in KMZ format. From the SOTAmaps website I download summit lists in KMZ format and can use them immediately in OruxMaps. Summits appear as waypoints. All summit details are visible in the waypoint properties.
I didn’t know that. It took me longer to figure out how to export the KML data from SOTAmaps website than to transfer it to my phone. Hit the “draw KML overlay”, select the downloaded file and pazooooow… the summits appear on the map.
I used Oruxmaps extensively in Germany and France last week to do general navigation never mind summit location. This makes it just so much more useful. Markus, thanks for this as it lets me use SOTAmaps for planning and Oruxmaps for navigation.
You could of course generate a personalized layer, for example using QGIS as outlined in this posting:
Locus maps will also happily import kml. The fact that I have a SOTA list permanently installed on my maps can make my wife nervous any time we are actually trying to get somewhere in case I spot a nearby summit!
From what I read GPX might suit OsmAnd better. No problem exporting from QGIS or indeed using gpsvisualizer.com
I think OsmAnd only imports GPX and displays them as waypoints, which is no good.
The OsmAnd “favourites” are stored internally as GPX, so it should be possible to add summits to that file, but I didn’t try it yet. It might clutter the favourites file, or be too tedious to merge in with existing favourites.
The Python script is on my github too, if anyone wants to play.
What’s wrong with GPX? I have uploaded onto my smarthphone’s Osmand HA SOTA summits as waypoints. Here is a schreenshot.
I am happy with it.
73 viktor HA5LV
Nothing wrong with that, but my POI layer shows the SOTA ref, summit name, and number of points. It also has a note of the number of activations and the last activation. The summits are searchable and routable (and, as you probably know, OsmAnd will plan a walking route if there are hiking paths in the OSM database)
Thanks. I took a look, but I prefer to add more fields into the name. Right now I make the ‘name’ field from the SOTA ref + summit name + [points], so it’s immediately visible on the map.
The ‘note’ field contains the total number of activations and the last activation (callsign + date).
I like your idea of including the SOTA summit page url. I might do that.
Andrew did a good job!
I have improved a little his sotagpx.py
Now it skips lines of summitslists.csv with format errors and outdated summits
You can convert more than one area at once.
call it like: sotagpx.py FL/VO,HB,DL/BW
Import the favorites.gpx as tracks into osmand!
Thanks to Andrew!
Andreas
Screenshots:
#!/usr/bin/env python3
#Python program to extract country-specific SOTA peaks from "summitslist.csv"
#and write out a GPX file, "favourites.gpx". This can be copied directly
#to the OsmAnd file directory on an Android phone. OsmAnd will import and
#merge the peaks with existing favourites so that SOTA peaks can be viewed
#on the OsmAnd screen. Import it as Track
#import selected summits: sotoagpx.py FL/VO,HB,DM/BW
#field-list:
#0: SummitCode
#1: AssociationName
#2: RegionName
#3: SummitName
#4: AltM
#5: AltFt
#6: GridRef1
#7: GridRef2
#8: Longitude
#9: Latitude
#10: Points
#11: BonusPoints
#12: ValidFrom
#13: ValidTo
#14: ActivationCount
#15: ActivationDate
#16: ActivationCall
import argparse
import sys
from datetime import date
parser = argparse.ArgumentParser()
parser.add_argument('region',
nargs='?',
help='SOTA region to extract, e.g. G/ or G/CE')
args = parser.parse_args()
if args.region is None:
print("Region must be specified.")
sys.exit()
keys = args.region.split(',') # First part of SOTA ref. to match (can be as long as you like)
print("Extracting '%s'."%keys)
id = 2 # Internal counter
#Colours for each point level. Gradient from green to red.
colours = {'1':'00FF00', '2':'65FF00', '4':'CCFF00', '6':'FFCC00', '8':'FF6600', '10':'FF0000'}
e = open ('errors.txt','w',encoding='utf-8')
with open('favourites.gpx', 'w', encoding='utf-8') as o:
o.write('<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n')
o.write('<gpx version="1.1" creator="sotagpx.py" xmlns="http://www.topografix.com/GPX/1/1"\n')
o.write('xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n')
o.write('xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">\n')
with open("summitslist.csv", encoding='utf-8') as f:
line=f.readline()
line=f.readline() #skip header
for line in f:
for key in keys: #select all keys
if line[:len(key)]== key:
fields = line.split(',')
# Name is "SOTA ref. Name [Points]"
name = fields[0] + ' ' + fields[3] + ' [' + fields[10] + ']'
if len(fields)!=18: #error in datafields: ignore
error=' # of fields:'+ str(len(fields))+' line:'+ str(id)+' contents: '+line
e.write(error)
else:
if int(fields[13].split('/')[2])>date.today().year: #only activated summits
id += 1
activations = fields[14] + ' activation' + ('.' if int(fields[14])==1 else 's.')
if int(fields[14]) > 0:
activations += '\nLast ' + fields[16] + ' (' + fields[15] + ').'
# Activations go in 'desc', with URL.
o.write(' <wpt lat="%s" lon="%s">\n'%( fields[9],fields[8]))
o.write(' <ele>%s</ele>\n'%(fields[4]))
o.write(' <name>%s</name>\n'%(name))
o.write(' <desc>%s\nhttp://www.sota.org.uk/Summit/%s</desc>\n'%(activations,fields[0]))
category=fields[0].split('-')[0]
o.write(' <type>SOTA %s</type>\n'%category) # SOTA + Association + Region
o.write(' <extensions>\n')
o.write(' <color>#%s</color>\n'%colours[fields[10]])
o.write(' </extensions>\n')
o.write(' </wpt>\n')
o.write("</gpx>\n")
e.close()
print("%s POIs extracted."%abs(id))