Openstreetmap, mapnik and gps tracks
01 June 2009

Open street map is a cool project with the aim to make geographic maps freely available to anyone. It can be used online as a slippy map (similar to google maps) or the entire map data can be downloaded in vector format to the local hard drive and used offline and even be uploaded to many gps receivers. The map data is entirely contributed by users - like wikipedia.

Download

To download the map data there are a couple of ways depending on the area of interest.

Applications

There are a many open source applications which can read osm data files and use the map offline. Here only a few.

Mapnik

The setup of mapnik to render openstreetmap data is a bit complicated as it requires the osm map file to be imported into a postgres database for performance reasons. The full procedure is described in the openstreetmap wiki. Once it has been fully installed and configured mapnik provides a python interface to draw images. A programming example is provided in generate_image.py, in which only a bounding box in terms of longitude/latitude coordinates and image resolution need to be adjusted. Very detailed customisation of the final map image can be made by editing the config file osm.xml which contains all the directives on how to render the map.

Mapnik and gps tracks

In order to overlay a gps track onto the map add the following rule to the file osm.html. I'm using mapnik version 0.5.1-6.19 which cannot import gpx files so I need to convert gpx to shape and the programme gpx2shp works for me. Newer versions of mapnik can apparently read gpx files directly. Make sure the gpx file contains tracks and not waypoints or routes for the following to work.
 <!-- User defined gps style -->
 <Style name="gpxlines">
      <Rule>
      <LineSymbolizer>
        <CssParameter name="stroke">#fff</CssParameter>
        <CssParameter name="stroke-width">5</CssParameter>
        <CssParameter name="stroke-linejoin">round</CssParameter>
        <CssParameter name="stroke-linecap">round</CssParameter>
        <CssParameter name="stroke-opacity">0.4</CssParameter>
      </LineSymbolizer>
      <LineSymbolizer>
        <CssParameter name="stroke">blue</CssParameter>
        <CssParameter name="stroke-width">2.5</CssParameter>
        <CssParameter name="stroke-dasharray">4,2</CssParameter>
      </LineSymbolizer>
      </Rule>
   </Style>


 <!-- User defined gps track -->
 <Layer name="gps" status="on" srs="+proj=latlong +datum=WGS84">
    <StyleName>gpxlines</StyleName>
    <Datasource>
      <Parameter name="type">shape</Parameter>
      <Parameter name="file">/path/track_trk</Parameter>
    </Datasource>
 </Layer>
Below two random examples.

map map

Background images like satellite maps can also be added to the map, if the coordinates of the lower left and upper right corner of the image are know. Also the image needs to be in the same projection as the main map. Openstreetmap as well as google map use Mercator projection. Since mapnik requires the coordinates to be in the projection coordinate system of the main map we need to convert longitude/latitude into Mercator x,y coordinates. The following pseudo C code achieves this.
  R_Earth = 6378137.0; 
  deg2rad = M_PI/180.0; 
  x=R_Earth*deg2rad*lon; 
  y=R_Earth*log((1.0+sin(deg2rad*lat))/cos(deg2rad*lat));
With the right coordinates the background image can be added to osm.xml.
 <!-- User defined background map style -->
 <Style name="rastersty">
    <Rule>
        <RasterSymbolizer>
            <CssParameter name="scaling">bilinear</CssParameter>
        </RasterSymbolizer>
    </Rule>
 </Style>

 <!-- User defined background map -->
 <Layer name="bg_cumbria_village" status="on" srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over">
    <StyleName>raster</StyleName>
    <Datasource>
       <Parameter name="type">raster</Parameter>
       <Parameter name="format">tiff</Parameter>
       <Parameter name="file">/path/cumbria_village.tif</Parameter>
       <Parameter name="lox">-364146.003</Parameter>
       <Parameter name="loy">7218407.203</Parameter>
       <Parameter name="hix">-357113.796</Parameter>
       <Parameter name="hiy">7222687.677</Parameter>
   </Datasource>
</Layer>

Uploading osm data onto a garmin gps

There is a simple utility mkgmap which converts osm files into img files readable by garmin gps units. I then upload the file(s) onto my garmin vista c (bought end of 2005) using qlandkarte. Yes, this is an old project but it works. On newer models it can be uploaded using the USB mass storage mode, apparently. For more details see the openstreetmap wiki.

The following generates a garmin map, e.g. a file 63240001.img

        mkgmap file.osm --country-name="United_Kingdom" --country-abbr="GBR"
In qlandkarte the upload works like this:
file → load map → select garmin img map file
F1 (map) → F5 (select map) → click on map
F9 (upload)