Skip to content

Instantly share code, notes, and snippets.

@Intyre
Last active September 22, 2024 12:50
Show Gist options
  • Save Intyre/f08b62d7ebefed41d8e80f35e24c2426 to your computer and use it in GitHub Desktop.
Save Intyre/f08b62d7ebefed41d8e80f35e24c2426 to your computer and use it in GitHub Desktop.
Wahoo create maps

Wahoo map creation

Tools

  • Java
    • set JAVACMD_OPTIONS="-Xmx2g" or other memory size when osmosis starts to complain.
  • osmium for filtering and splitting .pbf files
  • osmosis for splitting .pbf and creating .map files
  • osmfilter for filtering pois and ways
  • osmconvert for converting .pbf and .o5m files
  • Cruiser app to view .map files on PC

mapsforge-map-writer plugin

Download the mapsforge-map-writer plugin, click on "file_download" and select "jar-with-dependecies.jar". Put the .jar in one of these directories. Create it when it doesn't exist.

  • Linux/macOS ~/.openstreetmap/osmosis/plugins
  • Windows C:\Documents and Settings\(Username)\Application Data\Openstreetmap\Osmosis\Plugins

Create maps

Download the .osm.pbf file for your region. By clicking on the "Sub Region" name you can get smaller files.

Filter poi and way tags

Without this step I was running out of memory when creating .map files. Only data with those tags are saved to a file, it makes it smaller and now osmosis works without running out of memory. Those tags come from original .map files that I found, maybe there are more?

Command osmfilter

osmconvert <your.osm.pbf> -o=<your.o5m>

osmfilter <your.o5m> \
  --keep="access= admin_level= aerialway= \
  aeroway= barrier= boundary= bridge= highway= \
  natural= oneway= place= railway= tracktype= \
  tunnel= waterway=" \
  -o=<filtered-your.o5m>

osmconvert <your.o5m> -o=<filtered-your.osm.pbf>

Command osmium

osmium tags-filter <your.osm.pbf> \
  access admin_level aerialway aeroway barrier boundary \
  bridge highway natural oneway place railway tracktype \
  tunnel waterway \
  -o <filtered-your.osm.pbf>

Splitting tiles

The device uses Slippy map tilenames to store all map files. Split the big .osm.pbf with osmosis to get all the tile data we need.

Get the X and Y from the tiles you want with this map grid tool, make sure you keep z at 8. OR Get the stable apk url from version.json, download and extract the .apk. It contains assets/maps/mappack-gzip.json. The tile_coordinates are the X and Y.

Convert the X and Y to coordinates with this tool. Do this twice to get bottom, left, top and right. The second time do X+1 and Y+1.

$BOTTOM = lat value of y+1
$LEFT   = lon value of x
$TOP    = lat value of y
$RIGHT  = lon value of x+1

Use $BOTTOM, $LEFT, $TOP, $RIGHT, X and Y in the commands below. Don't type \ at the end of the line in commands, those are just used to make it easier to read.

Command osmosis

osmosis --rb <filtered-your.osm.pbf> \
   --bounding-box bottom=$BOTTOM left=$LEFT top=$TOP right=$RIGHT \
   completeWays=yes completeRelations=yes \
   --wb file=<X-Y.osm.pbf>

Command osmium

osmium extract \
   -b $LEFT,$BOTTOM,$RIGHT,$TOP \
   <filtered-your.osm.pbf>
   -o <X-Y.osm.pbf>

Tiles on country border

Merge splitted files from more countries where borders cross to make a complete .map file.

Command osmconvert
osmconvert <a.osm.pbf> <b.osm.pbf> -o=<c.osm.pbf> 

Create land

Download land-polygons-split-4326.zip and extract it. Two more programs are needed to convert the polygons to osm data.

Command

ogr2ogr -overwrite -progress -skipfailures -spat $LEFT $BOTTOM $RIGHT $TOP X-Y-land.shp land-polygons-split-4326/land_polygons.shp
python3 shape2osm.py -l "$WORK_PATH/land" "$WORK_PATH/land.shp"

Create sea

Sea.osm is a simple file from mapsforge-creator repository. The $BOTTOM $LEFT $TOP $RIGHT values need to be replaced with the current values.

Command

  cp sea.osm <X-Y-sea.osm>
  sed -i "s/\$BOTTOM/$BOTTOM/g" <X-Y-sea.osm>
  sed -i "s/\$LEFT/$LEFT/g" <X-Y-sea.osm>
  sed -i "s/\$TOP/$TOP/g" <X-Y-sea.osm>
  sed -i "s/\$RIGHT/$RIGHT/g" <X-Y-sea.osm>

Merge osm, land and sea

Command osmosis
osmosis --rb <X-Y.osm.pbf> \
  --rx file=<X-Y-land.osm> --s --m \
  --rx <X-Y-sea.osm> --s --m \
  --buffer \
  --wb <merged-X-Y.osm.pbf> omitmetadata=true
Command osmium
osmium merge <X-Y.osm.pbf> <X-Y-land.osm> <X-Y-sea.osm> -o <merged-X-Y.osm.pbf>  

Create map file

The original .map files had one zoom-interval configuration, this resulted in matching output files.

Command osmosis

osmosis --rb <merged-X-Y.osm.pbf> \
  --mw file=<X-Y.map> \
  bbox=$BOTTOM,$LEFT,$TOP,$RIGHT \
  zoom-interval-conf=10,0,17 \
  tag-conf-file=tag-wahoo.xml

tag-conf-file

Changing or removing anything in this file will result in different .map files. Make sure to also change the osmfilter --keep command to filter poi or way tags that got added or remove.

Some documentation about the config file.

Note: Using this config won't give the same result as the original. Wahoo used custom zoom-appear levels. Maybe mapsforge-bolt.xml or mapsforge-roam.xml can be used to get more info about zoom-appear levels.

Ship it!

Compress the generated .map file with lzma. Use lzma on macOS or Linux and 7zip on Windows. Connect the Wahoo device to your PC with usb and copy the file to the correct directory and file name and reboot the device. Like: maps/tiles/8/X/Y.map.lzma.

Links

<?xml version="1.0" encoding="UTF-8"?>
<tag-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" default-zoom-appear="16"
profile-name="default-profile" xmlns="http://mapsforge.org/tag-mapping"
xsi:schemaLocation="http://mapsforge.org/tag-mapping https://raw.githubusercontent.com/mapsforge/mapsforge/master/resources/tag-mapping.xsd">
<!-- ************* POIS *************** -->
<!-- HIGHWAY TAGS -->
<pois>
<osm-tag key="highway" value="mini_roundabout" zoom-appear="17" />
<osm-tag key="highway" value="traffic_signals" zoom-appear="17" />
<osm-tag key="highway" value="turning_circle" zoom-appear="15" />
</pois>
<!-- PLACES TAGS -->
<pois>
<osm-tag key="place" value="city" zoom-appear="6" />
<osm-tag key="place" value="country" zoom-appear="3" />
<osm-tag key="place" value="hamlet" zoom-appear="13" />
<osm-tag key="place" value="suburb" zoom-appear="12" />
<osm-tag key="place" value="town" zoom-appear="9" />
<osm-tag key="place" value="village" zoom-appear="12" />
</pois>
<!-- ************* WAYS *************** -->
<!-- HIGHWAY TAGS -->
<ways>
<osm-tag key="highway" value="bridleway" zoom-appear="13" />
<osm-tag key="highway" value="construction" zoom-appear="13" />
<osm-tag key="highway" value="cycleway" zoom-appear="13" />
<osm-tag key="highway" value="footway" zoom-appear="13" />
<osm-tag key="highway" value="living_street" zoom-appear="13" />
<osm-tag key="highway" value="motorway" zoom-appear="6" />
<osm-tag key="highway" value="motorway_link" zoom-appear="6" />
<osm-tag key="highway" value="path" zoom-appear="14" />
<osm-tag key="highway" value="pedestrian" zoom-appear="14" />
<osm-tag key="highway" value="primary" zoom-appear="8" />
<osm-tag key="highway" value="primary_link" zoom-appear="8" />
<osm-tag key="highway" value="raceway" zoom-appear="12" />
<osm-tag key="highway" value="residential" zoom-appear="12" />
<osm-tag key="highway" value="road" zoom-appear="12" />
<osm-tag key="highway" value="secondary" zoom-appear="12" />
<osm-tag key="highway" value="secondary_link" zoom-appear="12" />
<osm-tag key="highway" value="service" zoom-appear="14" />
<osm-tag key="highway" value="steps" zoom-appear="16" />
<osm-tag key="highway" value="tertiary" zoom-appear="12" />
<osm-tag key="highway" value="tertiary_link" zoom-appear="12" />
<osm-tag key="highway" value="track" zoom-appear="13" />
<osm-tag key="highway" value="trunk" zoom-appear="6" />
<osm-tag key="highway" value="trunk_link" zoom-appear="6" />
<osm-tag key="highway" value="unclassified" zoom-appear="13" />
</ways>
<ways>
<osm-tag key="natural" value="nosea" zoom-appear="0" />
<osm-tag key="natural" value="sea" zoom-appear="0" />
<osm-tag key="natural" value="water" zoom-appear="8" />
</ways>
<ways>
<osm-tag key="oneway" value="yes" equivalent-values="1,true" renderable="false"/>
</ways>
<ways>
<osm-tag key="railway" value="disused" zoom-appear="15"/>
<osm-tag key="railway" value="funicular" zoom-appear="12"/>
<osm-tag key="railway" value="miniature" zoom-appear="14"/>
<osm-tag key="railway" value="light_rail" zoom-appear="12"/>
<osm-tag key="railway" value="monorail" zoom-appear="14"/>
<osm-tag key="railway" value="narrow_gauge" zoom-appear="14"/>
<osm-tag key="railway" value="platform" zoom-appear="14"/>
<osm-tag key="railway" value="preserved" zoom-appear="14"/>
<osm-tag key="railway" value="rail" zoom-appear="10"/>
<osm-tag key="railway" value="subway" zoom-appear="15"/>
<osm-tag key="railway" value="tram" zoom-appear="15"/>
</ways>
<ways>
<osm-tag key="tracktype" value="grade1" renderable="false"/>
<osm-tag key="tracktype" value="grade2" renderable="false"/>
<osm-tag key="tracktype" value="grade3" renderable="false"/>
<osm-tag key="tracktype" value="grade4" renderable="false"/>
<osm-tag key="tracktype" value="grade5" renderable="false"/>
</ways>
<ways>
<osm-tag key="tunnel" value="yes" renderable="false"/>
<osm-tag key="tunnel" value="no" renderable="false"/>
</ways>
<ways>
<osm-tag key="waterway" value="canal" zoom-appear="10"/>
<osm-tag key="waterway" value="dam" zoom-appear="10"/>
<osm-tag key="waterway" value="drain" zoom-appear="13"/>
<osm-tag key="waterway" value="river" zoom-appear="8"/>
<osm-tag key="waterway" value="riverbank" zoom-appear="8"/>
<osm-tag key="waterway" value="stream" zoom-appear="13"/>
</ways>
<ways>
<osm-tag key="access" value="destination" renderable="false"/>
<osm-tag key="access" value="private" renderable="false"/>
</ways>
<ways>
<osm-tag key="aerialway" value="rope_tow" zoom-appear="13"/>
</ways>
<ways>
<osm-tag key="aeroway" value="runway" zoom-appear="10"/>
<osm-tag key="aeroway" value="taxiway" zoom-appear="10"/>
<osm-tag key="aeroway" value="helipad" zoom-appear="17" />
</ways>
<ways>
<osm-tag force-polygon-line="true" key="boundary" value="administrative" zoom-appear="0"/>
</ways>
<ways>
<osm-tag key="bridge" value="yes" renderable="false"/>
</ways>
<ways>
<osm-tag force-polygon-line="true" key="admin_level" value="1" zoom-appear="4">
<zoom-override key="boundary" value="administrative" />
</osm-tag>
<osm-tag force-polygon-line="true" key="admin_level" value="2" zoom-appear="4">
<zoom-override key="boundary" value="administrative" />
</osm-tag>
<osm-tag force-polygon-line="true" key="admin_level" value="3" zoom-appear="4">
<zoom-override key="boundary" value="administrative" />
</osm-tag>
<osm-tag force-polygon-line="true" key="admin_level" value="4" zoom-appear="6">
<zoom-override key="boundary" value="administrative" />
</osm-tag>
<osm-tag force-polygon-line="true" key="admin_level" value="5" zoom-appear="6">
<zoom-override key="boundary" value="administrative" />
</osm-tag>
<osm-tag force-polygon-line="true" key="admin_level" value="6" zoom-appear="6">
<zoom-override key="boundary" value="administrative" />
</osm-tag>
</ways>
<ways>
<osm-tag key="barrier" value="city_wall" zoom-appear="14" />
</ways>
</tag-mapping>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment