OpenStreetMapのデータに独自に地物を追加してnginxでタイルサーバー構築して大学のアクセスマップを作った

久々のブログです!

今回の記事は技術的な内容が多いので、興味ない方は適当に飛ばしながら読んでください。

国際信州学院大学は都会の大学と違って十分な予算があるわけでもないのでHP制作も外注せず学内で行われています。そのため、僕達のコンピューター同好会にも大学のHPの制作の仕事が回ってくることがあります。

今回はGoogle Maps APIの課金体制が変更になり費用が発生する恐れがあるため、HPのアクセスに掲載する周辺地図をOpenStreetMapにできないかという相談が大学から当会にありました。

OpenStreetMapというのは地図情報を誰もが利用できるように有志で協力して、フリーな地図情報データを作ろうというプロジェクトです。Wikipediaの地図版みたいなものです。

OpenStreetMap(OSM)の地図をサイトに載せようと思えば簡単ですが、国信大の場合2つ問題点があります。
一つは大学のページですから話題になればアクセスが増加し、OSMのサーバーに負荷がかかってしまう可能性があります。
もう一つはOSMの地図は有志の手によって作られているのですが、国信大は田舎の私立大学のため知名度がなくOSMには掲載されていません。OSMは有志が編集に参加できるため、国信大を追加することも可能ですが、今まで無名であった上に某匿名掲示板のユーザー達のイタズラにより架空の大学であるという情報がネットに流布されてしまいました。そのため、架空の大学であると思いこむ人が多く、OSMに追加したところで「架空の地物が追加されてる!これはOSMに対する破壊行為だ!」とか思われて即消しされそうなのでやめておきます。
(OSMは素晴らしい取り組みであり、地上に存在するものをマッピングするなどの決まりがありますので尊重しないといけません。)

そこで、大学の方で自前のタイルサーバー(地図画像を配信するサーバー)を用意し、そこにOSMのデータに修正を加えたものを導入することにしました。タイルサーバーの構築方法は調べればいろいろ出てくるのですが、地図データの編集についてはOSM本家に貢献することが前提となっていてOSMのデータにローカルで独自で地物(地図上の物や概念)を追加する方法の情報があまりありませんでした。試行錯誤の上、場当たり的な泥臭い方法ですがOSMのデータをローカルで修正することができましたのでまとめておきます。もっと適切な方法があれば(多分あるはず)教えていただきたいです。

必要なツールはosmosisとosmconvertとJOSMです。僕はArch Linuxを使っていますがJOSMはpacmanから入り、osmosisとosmconvertはAURから入れました。

まず、OSMのデータを入手します。地球上の全てを網羅したplanet.osmというものがありますが、圧縮しても30-50GBという代物ですしよほどの高スペックマシンでないと扱えないでしょう。ここでは中部地方だけのデータを入手したいと思います。geofabrikのサイトから入手できます。PBF形式でダウンロードできますが中部だけでも249MBもありますね・・・
(OSMデータのファイル形式には複数ありますが、ここでは.osmと.pbfを使います。.osmはXML形式で取り回しがよく編集時に使います。.pbfはバイナリ形式でコンパクトなので広域向けです。)

これでも少し大きいので長野県を囲む矩形領域だけ切り出しましょう。PBFファイルやOSMファイルを変換したりするのにosmosisというコマンドを使います。top,left,bottom,rightを緯度経度で指定し、切り出した領域をnagano-rect.pbfに書き出します。

$ osmosis –rb chubu-latest.osm.pbf –bounding-box top=37.05 left=137.255 bottom=35.15 right=138.85 completeWays=yes completeRelations=yes –wb nagano-rect.pbf

これで長野県を囲む範囲のデータになりましたので、地物を追加修正してタイルサーバーに突っ込みます。追加修正したいのですが、直接編集するにはまだ巨大なファイルです。編集用にキャンパスの周辺だけ.osmファイルに切り出しましょう。

$ osmosis –rb nagano-rect.pbf –bounding-box top=36.4 left=137.8317 bottom=36.366 right=137.89 –wx campus-around.osm

後で差分を取るため、コピーしておきます。

$ cp campus-around.osm camps-around-orig.osm

オリジナルをコピーしたら早速編集します。JOSMっていうjavaでできたOSM用のエディターがあるので先ほどのcampus-around.osmを開いて地物を追加修正削除していきます。iDっていう手軽なエディタがあるらしいけどローカルで修正するのには使えないかも。

うちの大学は田舎の私大のくせにTDL並にキャンパスが大きく、建物も多いのでノード繋いで名前つけてタグ付けして複雑な地物はリレーション設定して・・・正直めんどくさいです。OSMの貢献者の皆様には頭が下がります。(でもなれると楽しい!?)

編集が完了したら保存しJOSMを閉じます。閉じる時にアップロードするか聞かれますがアップロードせず保存するだけにします。早速OSMの差分を取りたいのですが一筋縄にはいきません。泥臭いやり方で強行突破します。

まず、編集後のOSMファイルをテキストエディタで開きます。XMLが見えると思いますが、新しく追加したノード等はid属性が負数になっています。負数のIDは仮のものでOSM本家にアップロードすると正数の固有のIDが割り当てられるそうですが、ここではローカルで済ませたいので負記号と上ひと桁を他と重複しなさそうな適当な数字列に置換してお茶お濁しましょう。ID置換後でも既存のIDより若くなるような数字列で置換すると後でエラーにならずにすみます。

osmosisを使って変換しようと思えばtimestamp,changeset,version属性も必要です。JOSMで追加したノード等には3属性がついておらず、action=’modify’属性がついていますのでそれを置換対象にうまく使って3属性を追加しましょう。ここでは「’ action=’modify’ lat=’」を「’ action=’modify’ timestamp=’2018-06-01T00:00:00Z’ version=’1′ changeset=’1′ lat=’」に置換しました。

nodeだけでなくwayやrelationにも追加する必要があるため「’ action=’modify’>」を「’ action=’modify’ timestamp=’2018-06-01T00:00:00Z’ version=’1′ changeset=’1′>」に置換しました。

次にosmosisが正常にこの.osmファイルを読み込んでくれるか確かめます。osmosisで無意味な変換をしてみます。

$ osmosis –rx campus-around.osm –wx campus-around-test.osm

これでエラーが出たら先ほどの置換を見直すなどしてエラーメッセージ(属性が足りない等)に対応します。何もエラーが出なかったら次に進みます。osmconvertを通します。

$ osmconvert campus-around.osm –emulate-osmosis -o=campus-around-converted.osm

これをしないとJOSMで削除したノード等が生き返ってしまいます。(osmosisがaction=”delete”をスルーしてしまうため)

やっとosmの差分を取る段階にたどり着きました。osmosisコマンドで.osmファイルの差分をとって.oscファイルに書き出します。–rxで.osmファイルを2つ指定していますが、編集後が前でオリジナルが後ろです。

$ osmosis –rx campus-around-converted.osm –rx camps-around-orig.osm –derive-change –write-xml-change file=”campus-around-change.osc”

ついにタイルサーバーに突っ込むデータに差分を適応する段階に来ました。今回は前半で用意したnagano-rect.pbfに適応してみます。もちろん中部全域のPBFファイルでも日本全域でも全世界のplanet.osmでもかまいません。

$ osmosis –read-xml-change file=”campus-around-change.osc” –rb nagano-rect.pbf –apply-change –wb nagano-rect-modified.pbf

これでタイルサーバーのpostgresに突っ込むデータが出来上がりました!!!長かった!!!!

あとはOSMのタイルサーバーの構築方法はググればいろいろ出てくるので構築して、osm2pgsqlで先程のnagano-rect-modified.pbfを突っ込んであげればOKです。

これでめでたく独自追加した地物が表示される自分たちだけのタイルサーバーが出来上がります。やったね!!

ちなみにタイルサーバーの構築はググればOKって言いましたが、こっちの方でもたくさん苦労がありました・・・タイルサーバーの構築まですることになるとは・・・まあ普通に生きててする機会なんてあまり無いですからね。
あとタイルサーバーはApache+mod_tileが鉄板なのですが、鉄板過ぎてそれを使わない方法の情報がなかなか出てこないんですよ・・・
nginxて構築しようと思ったのですが「構築した!」との情報はあっても具体的な指南が見当たらなかったように思います。

いろいろ試行錯誤した挙句postgres(postgis)+tirex(+mapnik)+lua-nginx-osmでタイルサーバーを構築しました。lua-nginx-osmは今回の案件にちょうどよかったのですが、github上のコードはそのままでは動かず少し修正する必要がありました。修正箇所は最後に載せておこうかなと思います。

冒頭にも書きましたとおりうちの大学は潤沢な予算がありません。今回のタイルサーバーとしてあてがわれたマシンも贅沢なものではなくメモリー2GBでCPUは2コア1.66GHz(Core2Duo T5500)と2018年となっては控えめなものです。

タイルサーバーを構築してわかりましたが、これって想像以上に負荷がかかるんですね・・・このマシンではタイルの描画に十数秒〜数分もかかってしまい、描画性能的には使いもになりません。ただ、一度描画したらtirexがキャッシュしていますし、cloudflareもかましていますので、キャンパスの周辺を表示するだけの用途なら一応大丈夫でしょう。

風のうわさで国信大のHPのサーバーはさくらVPSの1Gプランで運用されているとか聞いていてうちの大学はそんなに金がないのか・・・と思っていました。(蛞蝓亭の騒ぎで国信大が話題になったときはアクセスの集中でよく鯖落ちしていましたし)
高スペックの要求されるタイルサーバーもまさか1GのVPSに構築させられるのではないか心配していましたが、大学側が(焼け石に水かもしれませんが)少しマシなマシンを用意してくれたようです。

大学HPのアクセスページに掲載されていますが、一応出来上がった地図を貼っておきます。

OSMのライセンスはいまいちよく把握していませんが、「©OpenStreetMap contributors」って著作権表示をしておき、改変を加えたらそれを明示しておけば大丈夫だと思います。

HPの片隅にある何気ないアクセスマップですが、隠れた技術背景があることを知ってもらえたら構築に関わった者としては嬉しいです。

このようにうちの会は時々大学側から技術的なサポートを求められることもあり、タダ働き貴重な経験をすることができます。

国際信州学院大学に入学したら是非、コンピューター同好会に入会しませんか。

2018年度入会募集中

ちなみに当会は、それなりに活動していて、大学にもよく協力していて、サブドメインももらっていますが、実はまだ非公認のサークルなんです・・・
大学公認のサークルはアンカとかなんとかいうよくわからない方法で決定されているらしく、当会は対象に入ってなかったようです。まあ仕方ないですね。

 

最後に、lua-nginx-osmで修正したところを書いておきます。

osm/tile.lua 171行目からのif文
修正前

if ext == '' then
        captures = "^"..base.."/(%d+)/(%d+)/(%d+)"
    elseif sub(ext, 1) ~= '.' then
        captures = "^"..base.."/(%d+)/(%d+)/(%d+)"..'.'..ext
    else
        captures = "^"..base.."/(%d+)/(%d+)/(%d+)"..ext
    end

修正後↓

    if ext == '' then
        captures = "^/"..base.."/(%d+)/(%d+)/(%d+)"
    elseif sub(ext, 1, 1) == '.' then
        captures = "^/"..base.."/(%d+)/(%d+)/(%d+)".."%."..sub(ext,2)
    else
        captures = "^/"..base.."/(%d+)/(%d+)/(%d+)".."%."..ext
    end

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です