Thursday, May 3, 2012

Creating a bike map for Garmin devices based on OSM data

The end result: a cycle map in Basecamp
Update September 2012: A while ago, Henning suggested minor modifications to the commands in steps 2 and 6 that should improve performance.

I don't think I've written a plug for OpenStreetMap (OSM) on this blog yet, but in case you didn't know: OSM is an awesome project, and I'm a regular contributor to and user of their database.

In preparation for my ride to Toronto I wanted to create a bike map to put on my Garmin GPS. For many regions in Europe pre-made cycling maps for Garmin are available but you have to DIY. I had created a OSM-based cycling map before but it only covered an area of 200km around Montreal. Creating that map had not been without problems, and unfortunately in the meantime I forgot a lot of the steps necessary. Consequently, this time I'm going to document the process for myself and others. I've tried to keep the instructions as dummy-friendly as possible, not requiring any deep understanding of the processes and programs involved. Feel free to ask questions in the comments and I'll try to answer them.

Before we get started, I should send out props to OSM-contributor and bike tourer Henning Scholland/aighes. If you live in Europe you don't have to create your owns maps but just download the ones he created. He has also been very helpful in guiding me through the process of generating my first map. Now let's make a map.

Step 1: Download data

First you have to download the data of the desired region. In the ideal case somebody will already have prepared an extract for that region. If that's the case you can move to step 3. In Canada, however, it is tricky: on the one hand, you probably won't want a map of all Canada (I heard Canada is big and cycling in the Northern Territories is kinda lonesome); on the other hand you probably want to include some parts of the US. In order to achieve that you will have to create your own extract, either from the "planet," i.e. the entirety of all OSM data, or from the North America extract which has a more manageable download size of about 5GB.

Step 2: Determine the bounding box and extract data

Once you have downloaded the several gigabytes of data you will use the tool osmosis to extract the chunk of data that you want. That chunk is called the "bounding box", and it is basically a rectangle, defined by the coordinates of its four corners. 

Install and run Osmosis: Download Osmosis and extract it into a folder. Open the command line and navigate to that folder. Run Osmosis as follows:

osmosis --read-pbf file="c:\Users\Harald\Downloads\america_north.osm.pbf" --bounding-box left=-81.0131836 top=47.2195681 right=-69.8730469 bottom=42.5368920 cascadingRelations --write-pbf file=Northeast.osm

The read-pbf option tells osmosis what kind of input file it is dealing with. The file parameter is the map data file you downloaded in step 1. The easiest way for entering the correct  bounding box values is by using the export function on the slippy map: zoom to the desired area, click "Export," and copy the four coordinates you need (if you don't have quite the bounding box you want you can click "Select area manually" and then draw a rectangle). What cascadingRelations does I don't really know but it's probably good to include it. write-xml determines the output format and shouldn't be changed. The final file then determines where to the output will be written.

Extracting the bounding box for a large region can take a while and create big files (in my case it was 8GB for an area of 520 by 880 km).

Step 3: Split the tiles

For reasons that don't need to concern you the bounding box extract will now have to be split up into tiles before the actual map making begins. For that download the tool splitter and extract it to a folder.  Install and run splitter with the following parameters:

C:\Users\Harald\Desktop\splitter-r200\java -Xmx1500m -jar splitter.jar c:\Users\Harald\Desktop\osmosis-0.40.1\bin\Northeast.osm

Depending on how big your extract is and how much memory your machine has you will have to adjust the memory allocation with the Xmx parameter. Stated simply: you want to allocate as much memory as possible. If you try to allocate too much you'll get an error message and can adjust the value down. My system has 4GB RAM and I couldn't assign 2000M but 1500M worked. If you don't have enough memory assigned the splitting process will fail. Once again, the splitting will take a while (in my case about 10 minutes). The end result will be a whole bunch of .pbf files, a file called template.args, and one file called areas.list.

Step 4: Download boundaries

In order to have a functioning address search on your Garmin, you will need to integrate administrative boundaries while making the map (i.e. the boundaries of countries, states/provinces, municipalities). Download the file from here and unzip into the same directory as your tiles. (Please note that searching for addresses doesn't work all that well in Canada because of a lack of boundary data.)

Step 5: Download map style

If you want to use the style of the aighes's RadReiseKarte (bike touring map), download from his homepage and extract the contents of the data directory into the folder containing your map data. You should now install mkgmap. After the installation you can do a quick test of the style file: run mkgmap as follows (depending on where you put your files you have to modify the path to the style folder):

java -jar mkgmap.jar --style-file=data/style_rrk -- list-styles

This should produce an output of
The following styles are available:
style_rrk            1: No summary available

Step 6: Create the map with mkgmap

Now run the following, very long command from the directory containing your map data and the style directory:

java -Xmx1500m -jar mkgmap.jar --max-jobs=4 --read-config=data\style_rrk\options --code-page=1252 --mapname=66000000 --overview-mapname=66000000 --family-name="Cyclemap Northeast" --series-name="Cyclemap Northeast April 2012" --description="Cyclemap April 2012" --family-id=6600 --output-dir=maps\ 

Unless you know what you're doing (I certainly didn't when I was doing this myself) I don't recommend changing anything except for the series name and family name parameters and the path to the desired output directory. Once again, you'll have to wait a while until mkgmap finishes.

Step 7: Install map into Mapsource/Basecamp

Mkgmap can create IMG files which you can copy directly onto your Garmin device. In general, however, it's easier to install the map in Mapsource/Basecamp first. This requires you to download the NSIS installation system. Start the program, select the output-dir defined in the previous step, and voila: you have an installer for your new map.

This is what the map will look like in Basecamp at a higher zoom level (I couldn't get a good pic of the map on my Garmin Etrex).


  1. I didn't get a chance to try your version yet, but when I recently got a new GPS I was searching around and found what looks like all those steps already done automatically and online. I was able to just select the tiles I want, download it as one file, and load it onto my new etrex 20. The OSM data even included my driveway (cause I added it!) and other trails that I've been working on adding. I also played around with the new garmin custom maps and was able to load satellite imagery on it. Check it out:

    1. This looks very nice. The main reason for compiling my own map was that in Montreal you need a map not neatly confined by administrative boundaries. So you need a little bit of QC, ON, NY, VT each and no pre-made map offered that. Well, I guess there now is an easy fix to this. Thanks a lot for the link!

    2. Quick question: is the map searchable? "Mine" is.

    3. It's still not perfect in that you have to select tiles of various sizes instead of just selecting where you need. Fortunately that need basically disappeared with the etrex 20 which has 2gb internal memory and I added a 4gb card to it - a HUGE upgrade from my Legend with only 24mb of storage!

    4. I tried to search by address with no luck. I read some workaround to that but haven't tried it yet. I could search by towns without issue though. The important detail was that it is routable.

    5. Okay, that seems to indicate that searching does work, but the data in the region you tested does not include proper address data. This is an issue when proper administrative boundaries haven't been added to the map (they can be difficult to obtain). I'm downloading a map right now and will see how it goes.

    6. So I've downloaded a map and played around with a bit (only in Basecamp, not on the Garmin). I couldn't get the address search to work either. The map also has a couple of problems, like "flooding" near large bodies of water that haven't been downloaded completely. In Basecamp I also don't like the visual style that much: fonts are too small and labels sometimes placed badly.

      I think I'll stick with my custom generated map for now but it's great to see that an easy alternative exists.

  2. Did you try using a TYP file too? I have no idea what exactly that does, but it says "Maps can be rendered more appealing when a TYP file is used." There's also the OpenFietsMap, which I have no tried. They looked fine to me (a huge improvement over the 1999 Metroguide maps I had), though one oddity was that the background on filled in areas like swaps wanted to refresh often. I've only tried it on the etrex 20 and not the Legend C though.

    1. Ah, I didn't notice that option. In that case the stylistic issues are easily solvable. I did use the openfietsmap. If you send me the desired bounding box I'm happy to generate a map for you and you can compare.