I have figured out how to get mkgmap to produce fully customized, routable Garmin-compatible IMG files for my nüvi GPS navigator. Here’s the story, with the helpful hints so you can produce custom IMG files to your own specifications, too.
Background
I first got serious about mapping in OSM in 2014, during a diplomatic posting to New Delhi. I had a Garmin nüvi GPS navigator, but Garmin provided no maps for India. A search of the OSM wiki revealed Lambertus’ website that provided ready-to-use, downloadable IMG files, which proved a godsend. Fast forward to 2015 and my diplomatic posting to Turkmenistan. That story is told in a recording of my 2019 banquet speech to the North American Cartographic Society. People in Turkmenistan and elsewhere relied on Lambertus’ IMG files to navigate in countries for which Garmin provides no maps. Alas, a couple of years ago Lambertus’ website went defunct. I tried bbbike’s IMG downloads, but they leave out numerous POIs I know are either useful or necessary for both diplomats and local residents in Central Asia.
I decided to study mkgmap so as to generate custom IMG files. As an aside, when I mentioned this to a longtime OSMer friend, the response was, “Good luck with that.”
The documentation
The documentation on mkgmap is a bit sparse, and it is not really comprehensive. The base documentation found at https://www.mkgmap.org.uk/doc/index.html is enough to get you started, but is written by computer experts for other computer experts. It is inaccessible in places to those of us who majored in political science or economics.
Andy Townsend’s instructions at /mapper/SomeoneElse/diary/38613 proved very helpful in shedding light on how things work.
Then I stumbled across ligfietser’s style sheets at https://github.com/ligfietser/mkgmap-style-sheets. This shed even more light on how to get rendering to work the way I wanted it to.
Phase I - getting it to route
Curiously, although IMG files are intended for use in GPS navigators for the purpose of navigation, mkgmap does not make them routable by default. I didn’t know that, and it took some trial and error before I realized the –route parameter is needed to make the IMG file routable.
Phase II – including desired POIs
Superficially, the rendering rules included in mkgmap’s style sheets are straightforward. As is usually the case, however, the devil is in the details. Knowledge of the tagging scheme of the countries included in the IMG file is crucial to amending the sample style sheets. That said, I had difficulty getting mkgmap to include as POIs areas, such as school yards, factories, corporate offices, and hospital grounds, that were not stored in OSM as nodes. The mkgmap program deals with this via a parameter, –add-pois-to-areas, which creates a node for each area way it encounters. I added that parameter, but still could not get POIs to appear in the IMG file. I had to dig into the sample “points” style sheet, discover that it was set up to delete such POIs, and comment out lines that deleted desired POIs that had been converted from ways (“mkgmap:area2poi=true”).
Phase III - routing across tiles
Large volumes of data are run through the splitter program to chop the dataset up into chunks small enough for mkgmap to handle. Then mkgmap generates tiles from these chunks and fits them together into a single IMG file named gmapsupp.img. Fine and dandy, but if you want to drive from Ashgabat to Tashkent, you cannot simply enter Tashkent as your destination. Hmm. That’s a problem. I searched the internet for a solution and for a couple of weeks found only references along the lines of, “Yes, that’s a problem, we don’t know what causes it.” Then I stumbled across this rather obscure guide to generating bicycle maps for Garmin GPSes, https://openmtbmap.org/about-2/archive/render-maps-mkgmap/, which includes the line,
–overlap=4000 - In order for mkgmap to stitch the tiles together there needs to be an overlap. 1000 is default, with 4000 one can avoid some errors.
I added that parameter to splitter, reran the programs, and tested routing in “GPS Simulator” mode. The GPS quickly generated routes from Ashgabat to Urgench and to Tashkent. Clearly, the default =1000 is insufficient to ensure routing across tiles, and setting it =4000 fixed it. Curiously, although the GPS navigator itself now routes across tiles, BaseCamp still cannot.
The Java command line scripts
Here are the splitter and mkgmap command lines I have settled on for generating maps for Central Asia:
java.exe -Xmx4000m -jar splitter\splitter.jar –output-dir=split –description=Central_Asia –overlap=4000 –keep-complete=true –mapid=12340001
java.exe -Xmx4096m -jar mkgmap\mkgmap.jar –copyright-message=”Copyright OpenStreetMap and contributors” –output-dir=map –route –index –split-name-index –location-autofill=is_in,nearest –preserve-element-order –style-file=.\tstan –add-pois-to-areas –link-pois-to-ways –nearby-poi-rules-config=.\tstan\duppoi –unicode –housenumbers –road-name-pois –process-exits –process-destination –split-name-index –add-boundary-nodes-at-admin-boundaries=2 –poi-address –bounds=bounds-latest.zip –precomp-sea=sea-latest.zip –generate-sea –country-name=”Central_Asia” –family-id=1234 –family-name=Central_Asia –series-name=Central_Asia –area-name=Central_Asia –gmapi –gmapsupp -c split\template.args split*.osm.pbf
I have also uploaded them to a Github repository (link below).
The style sheets
You can spend endless time tinkering with style sheets to get what you want rendered the way you want it. Or not the way you want it. I spent about three days trying to figure out how to get the style sheets to do what I wanted them to do (regex is not my best friend).
End result
The end result is that I can now generate IMG files for Garmin GPS navigators that route, that include what I think is important for my colleagues working abroad (i.e., what they need), and that route across the entire breadth of the map. The results can be seen in a Github repository at https://github.com/allanmustard/mkgmap
Feel free to download and use the command scripts and style sheets, modify them, play with them. If you discover something I haven’t, please comment below!