現在は、避難所検索@伊勢 で利用するオフラインマップの作成処理は、OpenStreetMap のタイルサーバーに同居しています。当初、この処理を作った際の記事にも書きましたが、タイルサーバー上に常に最新のデータがあるのでそれを流用したかったため、このような構成にしてました。が、それができないうえに、どちらも地図データを処理するため、同じライブラリを利用していたりして、相互にメンテナンスをしていくのがちょっと面倒だったりしました。
少し時間的な余裕ができたので、しばらく放置していた 避難所検索@伊勢 がまだベータ版だったのを正式リリースにしようと思い立ったのを機に、オフラインマップの作成処理も既存のサーバーから分離して、別サーバー上にセットアップしようと思います。
以前、オフラインマップ処理について不具合対応した際に、途中まで作業していたので、その際のメモをまとめた感じになります(なので、記事中の作業日時とか結構前後してたりしますが、ご容赦ください)。
EC2 の立ち上げと初期設定
オフラインマップ処理ですが、若干重いこともありますが、伊勢近辺だけであればなんとかなるので、今回も EC2 で動かすことにします。
EC2 のインスタンスは、若干処理が重いのもあるため、
t3a.medium, 2 vcpu, 4GB メモリ
にして、OS は Ubuntu 20.04 にしました(タイムゾーン、日本語環境の設定などはこちらの記事を参照)。
各種ソフトウェアのインストール
mapsforge-creator の説明に従って、必要なソフトウェアをインストールしていきます。
以前こちらの記事で行ったのと基本的には同じですが、最新版の mapsforge-creator では、 graphhopper のファイルも同時に作成できるようになってそのあたりが便利になってます。
mapsforge-creator のインストール
オフラインマップは mapsforge-creator を利用して生成します。
ただし、オリジナルの mapsforge-creator は任意の領域に切り取る処理がありません。そこで、オリジナルのリポジトリを fork して、こちらの記事で追加した任意の領域に切り取る処理を追加したブランチを作成しましたので、今回はそれを使います。
ubuntu@ip-172-30-3-185:~$ mkdir bin ubuntu@ip-172-30-3-185:~$ cd bin/ ubuntu@ip-172-30-3-185:~/bin$ git clone https://github.com/junichim/mapsforge-creator.git Cloning into 'mapsforge-creator'... remote: Enumerating objects: 378, done. remote: Counting objects: 100% (38/38), done. remote: Compressing objects: 100% (31/31), done. remote: Total 378 (delta 13), reused 22 (delta 7), pack-reused 340 Receiving objects: 100% (378/378), 112.85 KiB | 9.40 MiB/s, done. Resolving deltas: 100% (234/234), done. ubuntu@ip-172-30-3-185:~/bin$
ブランチを trim に切り替えます。
ubuntu@ip-172-30-3-185:~/bin$ cd mapsforge-creator ubuntu@ip-172-30-3-185:~/bin/mapsforge-creator$ git checkout trim Branch 'trim' set up to track remote branch 'trim' from 'origin'. Switched to a new branch 'trim' ubuntu@ip-172-30-3-185:~/bin/mapsforge-creator$
graphhopper のインストール
clone した mapsforge-creator の map-creator.sh をみると、 graphhopper まわりでは Graphhopper の jar ファイルと設定ファイルの config.yml があればいいようです。それぞれダウンロードします。
ubuntu@ip-172-30-3-185:~$ cd bin/ ubuntu@ip-172-30-3-185:~/bin$ mkdir graphhopper ubuntu@ip-172-30-3-185:~/bin$ cd graphhopper ubuntu@ip-172-30-3-185:~/bin/graphhopper$ ubuntu@ip-172-30-3-185:~/bin/graphhopper$ wget https://graphhopper.com/public/releases/graphhopper-web-1.0.jar --2021-04-15 17:32:14-- https://graphhopper.com/public/releases/graphhopper-web-1.0.jar (中略) 2021-04-15 17:32:42 (1.05 MB/s) - `graphhopper-web-1.0.jar' へ保存完了 [29603807/29603807] ubuntu@ip-172-30-3-185:~/bin/graphhopper$ ubuntu@ip-172-30-3-185:~/bin/graphhopper$ wget https://raw.githubusercontent.com/graphhopper/graphhopper/1.0/config-example.yml --2021-04-15 17:34:03-- https://raw.githubusercontent.com/graphhopper/graphhopper/1.0/config-example.yml (中略) 2021-04-15 17:34:03 (25.6 MB/s) - `config-example.yml' へ保存完了 [9556/9556] ubuntu@ip-172-30-3-185:~/bin/graphhopper$
graphhopper 自体はすでに 2.x までバージョンが進んでますが、 map-creator.sh が 1.0 を使っていたのでそれに準じています。
map-write /poi-writer のインストール
Osmosis のプラグインとしてインストールするには、
~/.openstreetmap/osmosis/plugins
に jar ファイルを置けばOKです(こちら参照)。
ubuntu@ip-172-30-3-185:~$ mkdir -p .openstreetmap/osmosis/plugins ubuntu@ip-172-30-3-185:~$ ubuntu@ip-172-30-3-185:~$ cd .openstreetmap/osmosis/plugins/ ubuntu@ip-172-30-3-185:~/.openstreetmap/osmosis/plugins$ wget https://search.maven.org/remotecontent?filepath=org/mapsforge/mapsforge-map-writer/0.15.0/mapsforge-map-writer-0.15.0-jar-with-dependencies.jar -O mapsforge-map-writer-0.15.0-jar-with-dependencies.jar --2021-04-16 09:34:10-- https://search.maven.org/remotecontent?filepath=org/mapsforge/mapsforge-map-writer/0.15.0/mapsforge-map-writer-0.15.0-jar-with-dependencies.jar (中略) 2021-04-16 09:34:27 (449 KB/s) - `mapsforge-map-writer-0.15.0-jar-with-dependencies.jar' へ保存完了 [6711875/6711875] ubuntu@ip-172-30-3-185:~/.openstreetmap/osmosis/plugins$ ubuntu@ip-172-30-3-185:~/.openstreetmap/osmosis/plugins$ wget https://search.maven.org/remotecontent?filepath=org/mapsforge/mapsforge-poi-writer/0.15.0/mapsforge-poi-writer-0.15.0-jar-with -dependencies.jar -O mapsforge-poi-writer-0.15.0-jar-with-dependencies.jar --2021-04-16 09:35:15-- https://search.maven.org/remotecontent?filepath=org/mapsforge/mapsforge-poi-writer/0.15.0/mapsforge-poi-writer-0.15.0-jar-with-dependencies.jar (中略) 2021-04-16 09:35:25 (1.29 MB/s) - `mapsforge-poi-writer-0.15.0-jar-with-dependencies.jar' へ保存完了 [11649486/11649486] ubuntu@ip-172-30-3-185:~/.openstreetmap/osmosis/plugins$
その他
ドキュメントに従って、インストールしていきます。
Java ランタイムのインストール
ubuntu@ip-172-30-3-185:~/bin$ sudo apt install default-jre
osmosis
ubuntu@ip-172-30-3-185:~/bin$ sudo apt install osmosis
GDAL
ubuntu@ip-172-30-3-185:~/bin$ sudo apt install gdal-bin
このとき、python3-gdal も一緒にインストールされてました。 確認してみます。
ubuntu@ip-172-30-3-185:~$ python3 Python 3.8.5 (default, Jan 27 2021, 15:41:15) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from osgeo import ogr >>> ubuntu@ip-172-30-3-185:~$
エラー出ませんね。
zip
ubuntu@ip-172-30-3-185:~$ sudo apt install zip
最後に、 aws-cli (バージョン 2 )もインストールしておきます。
ubuntu@ip-172-30-3-185:~/$ cd tmp/ ubuntu@ip-172-30-3-185:~/tmp$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" ubuntu@ip-172-30-3-185:~/tmp$ unzip awscliv2.zip ubuntu@ip-172-30-3-185:~/tmp$ sudo ./aws/install ubuntu@ip-172-30-3-185:~/tmp$ aws --version aws-cli/2.1.38 Python/3.8.8 Linux/5.4.0-1028-aws exe/x86_64.ubuntu.20 prompt/off ubuntu@ip-172-30-3-185:~/tmp$
これで、インストール関係は終了です。
graphhopper 用の設定ファイル
graphhopper のファイルも同時に作成できるようになったため、 graphhopper 用の設定ファイルも用意します。今回は下記のようにしました。
今回作成するオフラインマップは 避難所検索@伊勢 で使うため、 vehicle (移動手段を指す)として foot を指定します。
# More options: foot,hike,bike,bike2,mtb,racingbike,motorcycle,car4wd,wheelchair (comma separated) # bike2 takes elevation data into account (like up-hill is slower than down-hill) and requires enabling graph.elevation.provider below. # modified by Junichi MORI, 2021/4/15 #graph.flag_encoders: car graph.flag_encoders: foot
以前の記事で述べた設定ファイルとは異なり、graphhopper 1.0 では、 profile という形で、どの vehicle に対してどのような優先順位で経路検索を行うかを設定します。
profile の名前は任意でつけることができます(graphhopper 利用時にこの profile 名などを指定します)。
##### Routing Profiles #### # Routing can be done for the following list of profiles. Note that it is required to specify all the profiles you # would like to use here. The fields of each profile are as follows: # - name (required): a unique string identifier for the profile # - vehicle (required): refers to the `graph.flag_encoders` used for this profile # - weighting (required): the weighting used for this profile, e.g. fastest,shortest or short_fastest # - turn_costs (true/false, default: false): whether or not turn restrictions should be applied for this profile. # this will only work if the `graph.flag_encoders` for the given `vehicle` is configured with `|turn_costs=true`. # # Depending on the above fields there are other properties that can be used, e.g. # - distance_factor: 0.1 (can be used to fine tune the time/distance trade-off of short_fastest weighting) # - u_turn_costs: 60 (time-penalty for doing a u-turn in seconds (only possible when `turn_costs: true`)). # Note that since the u-turn costs are given in seconds the weighting you use should also calculate the weight # in seconds, so for example it does not work with shortest weighting. # - custom_model_file: when you specified "weighting: custom" you need to set a yaml file that defines the custom_model. # If you want an empty model you can also set "custom_model_file: empty". # # For more information about profiles and especially custom profiles have a look into the documentation # at docs/core/profiles.md or the examples under web/src/test/resources/com/graphhopper/http/resources/ or # the CustomWeighting class for the raw details. # # To prevent long running routing queries you should usually enable either speed or hybrid mode for all the given # profiles (see below). Otherwise you should at least limit the number of `routing.max_visited_nodes`. # modified by Junichi MORI, 2021/4/15 #profiles: # - name: car # vehicle: car # weighting: fastest # ## - name: car_with_turn_costs ## vehicle: car ## weighting: short_fastest ## distance_factor: 0.1 ## turn_costs: true ## u_turn_costs: 60 profiles: - name: escape_by_foot vehicle: foot weighting: fastest
weighting が何を優先して、検索するかを指定するものです。今回は一番速いものを検索するようにしました。可能な選択肢はドキュメントをご覧ください。
graphhopper では経路検索を行う際に3つのモード(Speed mode, Hybrid mode, Flexible mode)があるようです(こちらのドキュメントなどを参照)。設定ファイルでは、 Speed mode を適用する profile 名を指定します(Hybrid mode は使わないので、指定していません)。
# Speed mode: # Its possible to speed up routing by doing a special graph preparation (Contraction Hierarchies, CH). This requires # more RAM/disk space for holding the prepared graph but also means less memory usage per request. Using the following # list you can define for which of the above routing profiles such preparation shall be performed. Note that to support # profiles with `turn_costs: true` a more elaborate preparation is required (longer preparation time and more memory # usage) and the routing will also be slower than with `turn_costs: false`. # modified by Junichi MORI, 2021/4/15 #profiles_ch: # - profile: car ## - profile: car_with_turn_costs profiles_ch: - profile: escape_by_foot
なお、どのモードを用いるかは経路検索時に指定可能です(ドキュメントを見ると、経路検索時のリクエストに ch.disable = true や lm.disable = true を追加することで指定するようです)。
その他はデフォルトのままとしておきます。
スクリプトの調整
以前のオフラインマップサーバーのセットアップと同様に、各種スクリプトを調整します。
mapsforge-creator
前回と同様に、 map-creator.sh はシェルスクリプトになっており、先頭部分に各種ディレクトリなど設定情報を記入する形になっていますので、スクリプトを修正します。
まずは作業ディレクトリを作成します。
ubuntu@ip-172-30-3-185:~$ mkdir -p work/offlinemap
下記のように map-creator.sh の Configuration 部分を設定します(この部分は実行環境に合わせる形になると思います)。
# Configuration [ $MAP_CREATION ] || MAP_CREATION="true" [ $POI_CREATION ] || POI_CREATION="false" [ $GRAPH_CREATION ] || GRAPH_CREATION="true" [ $OSMOSIS_HOME ] || OSMOSIS_HOME="/usr" [ $WORK_DIR ] || WORK_DIR="$HOME/work/offlinemap" [ $DATA_PATH ] || DATA_PATH="$WORK_DIR/data" [ $MAPS_PATH ] || MAPS_PATH="$WORK_DIR/maps" [ $POIS_PATH ] || POIS_PATH="$WORK_DIR/pois" [ $GRAPHHOPPER_FILE ] || GRAPHHOPPER_FILE="$HOME/bin/graphhopper/graphhopper-web-1.0.jar" [ $GRAPHHOPPER_CONFIG ] || GRAPHHOPPER_CONFIG="$WORK_DIR/gh_config.yml" [ $GRAPHS_PATH ] || GRAPHS_PATH="$WORK_DIR/graphs" [ $DAYS ] || DAYS="30" [ $TAG_VALUES ] || TAG_VALUES="false" [ $COMMENT ] || COMMENT="Map data (c) OpenStreetMap contributors" [ $PROGRESS_LOGS ] || PROGRESS_LOGS="true"
上記の WORK_DIR は新たに追加したものになります。
graphhopper用のzipファイルを作成する部分を下記のように修正します。これは、Android側の graphhopper ライブラリで解凍する場合は、フォルダがひとつ余分に入るための措置です。
@@ -263,7 +264,9 @@ if [ "$GRAPH_CREATION" = "true" ]; then # Zip - cd "$WORK_PATH" && zip -r "$GRAPHS_PATH/$NAME.zip" "$NAME" && cd - + # modified by Junichi MORI, 2021/4/15 + #cd "$WORK_PATH" && zip -r "$GRAPHS_PATH/$NAME.zip" "$NAME" && cd - + cd "$WORK_PATH/$NAME" && zip -r "$GRAPHS_PATH/$NAME.zip" "./" && cd - fi
起動スクリプト
次に、 map-creator.sh を起動するスクリプト、および全体を制御するスクリプトを作成します。 bin/offlinemap に以下のファイルを作成しました。
- bin/offlinemap/createOfflineMap : 全体を実行
- bin/offlinemap/doMapCreator : map-creator 実行
- bin/offlinemap/uploadS3 : S3 へのアップロードを実行
前回作成したオフラインサーバー用のスクリプトからほとんど変わっていませんが、 graphhopper ファイルの作成を自分で呼び出さなくてよくなった点など、若干修正しています。
一応、まとめて gist に上げておきますので、ご参考にしてください。 これで、一連のファイルを自動で作ることができます。
2021/4/17 追記
オフラインマップの生成処理が失敗したとき、 Amazon SNS にメッセージを投げることで通知を行うようにしました。 gist もこれに合わせて更新しました。
動作確認
最後に、動作確認をします。
ubuntu@ip-172-30-3-185:~$ cd bin/offlinemap/
ubuntu@ip-172-30-3-185:~/bin/offlinemap$ ./createOfflineMap
所定のディレクトリ(今回は ~/work/offlinemap/result )にファイルが作成されており、 S3 にもアップロードされていればOKです。
ubuntu@ip-172-30-3-185:~/work/offlinemap/result$ ls -l 合計 9312 -rw-rw-r-- 1 ubuntu ubuntu 4599179 4月 16 14:37 ise.ghz -rw-rw-r-- 1 ubuntu ubuntu 4928105 4月 16 14:36 ise.map -rw-rw-r-- 1 ubuntu ubuntu 26 4月 16 15:30 map_timestamp ubuntu@ip-172-30-3-185:~/work/offlinemap/result$
cron に登録
ここまでできたら、 cron に登録して、定期的に実行させます。
ubuntu@ip-172-30-3-185:~$ cd /etc/cron.d ubuntu@ip-172-30-3-185:/etc/cron.d$ cat offlinemap # The first element of the path is a directory where the debian-sa1 # script is located PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin:/home/ubuntu/bin:/home/ubuntu/.local/bin # run createOfflineMap at yy:xx everyday xx yy * * * ubuntu /home/ubuntu/bin/offlinemap/createOfflineMap >> /home/ubuntu/work/offlinemap/log/run.log 2>&1 ubuntu@ip-172-30-3-185:/etc/cron.d$
上記は毎日実行になってますが、そんなに頻繁に実行する必要はないでしょう。最終的な頻度は様子をみながら調整します。 なお、ログファイル出力先のディレクトリは事前に用意しておきます。
今後
今回、オフラインマップ処理を EC2 上に作成しましたが常時動かす必要はありません。なので、最終的には普段はインスタンスを停止しておいて、定期的に呼び出して処理を行い、終わったらシャットダウンするようにしたいと思います。それはまた別記事にまとめようと思います。
参考
今回 mapsforge-creator を fork して、自分用のブランチを用意しました。
その中で追加した multipolygon2polygons.py というファイルは、こちらの記事で触れた multipolygon を polygon に変換するスクリプトを、下記などを参考にして、新たに書き直したものになります。
python-gdal のコードの例
- Welcome to the Python GDAL/OGR Cookbook! — Python GDAL/OGR Cookbook 1.0 documentation
- PythonでGeoSpatialをやってみる。[Chapter 1] | OpenなGISのこと
特に前者のサンプルをいろいろと眺めているとなんとなく使い方がわかってくる
OGC 単純地物モデル
OGR の元になっているモデルは OGC 単純地物モデルという話