でじたるチリクラブ

でじたるチリクラブ

おそらくカニ料理の話は出てきません。

FOSS4G 2024 Japanのコアデイに参加した

11月9日と10日に開催されたFOSS4G 2024 Japanの、コアデイ(2日目)に参加した。

www.osgeo.jp

参加概要

国内で開催されるFOSS4Gの大きめのイベントとしてTOKAI・Hokkaido・Japanがあり、それらの中で現地参加したのは今回のJapanがはじめて。これまではイベントが終わってから公開される録画配信やスライドを見るだけだった。

会場は神奈川県にある専修大学の生田キャンパス。自宅から日帰りで参加できる場所なのがありがたかった。最寄りの向ヶ丘遊園駅から大学までバスも出ているようだけど、駅でバスを待つ時間含めたら徒歩で行くのと所要時間かわらないのでは、と思って駅から歩いていくことにした。大学が山の上にあるとは知らず、途中から坂を登るのがきつくなって、バスを使えばよかったと後悔した。

コアデイの会場である専修大学生田キャンパスの7号館

コアデイは、セッション数が30個以上と盛りだくさんだった。時間帯によっては4トラック同時進行となっていて、どの発表を聴くかでけっこう悩んだ。発表のテーマとしては、点群やPLATEAUの3Dが多めな印象ではあるけれど、DBだったり、ツールやアプリだったり、事例紹介だったり様々。「FOSS4G」というのは間口の広いキーワードなんだなということをあらためて実感した。

コアデイの参加は午後からになってしまったけど、パネルディスカッション含めて8つのセッションに参加できた。どのセッションも、自分の知らなかった分野・技術にふれられたり、知識をアップデートできたりとよい学びになった。

特に印象に残ったセッション

参加した8つのセッションのうち、特に印象に残った2セッションについて感想を書く。

Transformer, Diffusion Modelを用いた衛星画像Hack! (AWS GPUインスタンスで地理情報系画像生成AIサービスは有効か?)

前半は衛星画像から建物や道路のジオメトリを抽出して出力する仕組みをつくった話、後半はその仕組みをAWSでサービス化するための構成とコストの削減方法を検討している話だった。

これまで衛星画像はさわった経験がほぼなく、なんとなくぼやけた画像というイメージしかなかったので、超解像度化されると画像がここまで鮮明になるのかと驚いた。安価だけれども低解像度の衛星画像からも、精度良く建物や道路を抽出できるようになるのなら、サービスとしてうれしい気がする。ただ、超解像度化におけるAWSGPUインスタンスの利用料が高くつくとのことで、そのコスト次第では、はじめから高解像度の衛星画像を購入してジオメトリを抽出する方が安い、となったりするのだろうか。

質疑応答でハルシネーションへの対処について質問が出ており、車が家になるようなハルシネーションの発生をどうやって検出したり抑制するための工夫をしてきたか知りたくなった。

Overture Maps Foundationを読み解く – 何を目的として、どこに向かっていくか?

Overture Mapsの運営団体と提供されているオープンデータについて、考察を加えながら紹介する発表。

以前からOverture Mapsには興味があったので、団体が設立された背景や目的、加盟企業の関わり方、提供データの種類とそのライセンス、GERSというID付与方式、など様々な観点から情報を得ることができてよかった。公開されている情報を整理して要点を紹介するだけでなく、

  • OpenStreetMapがあるなかでなぜ新しくオープンデータをつくるのか
  • Overture Mapsが採用したID付与方式のメリットや可能性
  • Overture Mapsが提供するデータの課題と持続性のリスク

といった考察込みの話を聴けたことが有益だった。

Overture Mapsに関する公開情報は誰でも見れるかもしれないけど、そこに対して説得力のある意味付けや解釈をしたり、今後起こり得ることを考えるためには、豊富な経験や関連知識が必要だと思う。今の自分がOverture Mapsのことを調べてもここまでの洞察はできないので、純粋にスゴイなと思った。

懇親会

懇親会は大学内を移動して、別館のホールで開催。FOSS4G関連のイベントには今年の夏から参加しはじめたこともあり、懇親会でも知らない人ばかり。いろいろな人にはじめましてとあいさつして、話をさせてもらった。これからイベントに登壇したりブログ書いたりとアウトプット増やして、少しずつ認知されるようになりたい。

さいごに

FOSS4G Japanに参加してよかった。地理空間情報に関わる様々な話題を1日でたくさん摂取できて、調べたいことが出てきたり自分も発表したくなったりと、モチベーションが高まるイベントだった。会場の空気感込みのライブで発表を聴いたり、懇親会で初対面の人と話をしたり、といった体験を得られるところが現地参加のよさなんだと実感した。

これだけの規模のイベントを開催するのは、事前の準備も当日の運営も、いろいろとたいへんだったはず。発表された方だけでなく、スタッフの皆様にも感謝です。ありがとうございました。

Mapillaryのモバイルアプリ(iOS版)を使って街路画像をアップロードする

Mapillaryは、撮影した街路画像 (street-level imagery) を共有するプラットフォームである。Mapillaryにアップロードされた画像は、オープンデータ (CC BY-SA 4.0) として利用することができる。

これまで他の人がアップロードした画像を利用する機会はあったが、自分が撮影した画像をアップロードしたことはなかった。画像を使わせてもらうばかりだと悪いので貢献してみるかという気持ちと、画像をアップロードするアプリがどんなものか知りたいという興味から、MapillaryのiOS版モバイルアプリ(以下、アプリ)を使ってみることにした*1

アプリの使い方

アプリの使い方は、Mapillaryが出しているコンプリートガイド(リンク先はiOS版だが、Android版もある)に書かれている。英語だけれどChromeの自動翻訳を使えば十分意味がわかるし、画面キャプチャも載っているので理解しやすい。そもそもがスマホで周りを撮影してアップロードするためのアプリであり、直感的に使えるということもある。 help.mapillary.com

使い方の補足

コンプリートガイドでふれられていることも含むけど、アプリを使う上で知っておいた方がよいと思うことを書く。

撮影モードは自動のみ

アプリの以前のバージョンでは 撮影モードを手動と自動で切り替えできたらしい。2024/10現在のバージョンでは、撮影を開始するとアプリが自動的にシャッターを切る、自動モードのみとなっている。アプリの設定で「手動キャプチャを許可する」をONにすると、ユーザーが手動でシャッターを切ることも可能になる*2

画像はアップロード後にスマホから削除される

アプリで撮影した画像は、アップロードが完了するとスマホから削除される。画像を残したければ、アップロード前に対象の画像を選んで保存する操作が必要となる。保存しそこねた場合、アップロード後の画像をMapillaryのWebアプリであるウェブエクスプローラーからダウンロードすることができるが、横幅が最大2048pxにリサイズされ、後述のぼかしが入ったものになる。

車のナンバープレートと人の顔にはぼかしが入る

車のナンバープレートと人の顔が写った画像は、アップロード時に自動でぼかしが入る仕組みになっている。そのため撮影時に車や人を写さないように気を使う必要はないのだけれど、念のためアップロード後に画像を確認した方がよさそう。ウェブエクスプローラー上で、ぼかしを編集することもできる。

感想

アプリを使ってみて、便利に感じたのは以下の2点。

  • 撮影からアップロードまでスマホだけで完結すること
  • 撮影が自動で行われるので、シャッターを切る場所や間隔を気にしなくてよいこと

ただ、アプリとは関係なく、スマホで撮影する場合にはシャッター音が気になる。スマホをかまえて、カシャカシャと音を鳴らしながら街中を歩くのは勇気がいる。特に対向者が来たときに、カメラを向けて撮影している感が出てしまうのが気まずい。対向者が通り過ぎるまで撮影を中断することもあるのだけれど、頻度が多いと撮影が進まない。そのためスマホを使っての撮影は、人通りの少ない場所や時間帯を選んで行うようになった。もっとガッツリとMapillaryの撮影をしたくなったら、シャッター音の消せる360°カメラやアクションカメラを買おうと思う。

環境

  • 機種:iPhone 12 mini
  • iOS:17.6.1
  • Mapillaryアプリ:6.0.3

*1:MapillaryのiOS/Androidモバイルアプリを使わず、スマホ標準のカメラアプリで撮影した画像をPCに移し、Mapillaryのデスクトップアプリもしくはコマンドラインツールでアップロードする方法もある。

*2:アプリが自動的にシャッターを切ることをOFFにすることはできない。

沖縄旅行してきた

8月の終わりに、家族で3泊4日の沖縄旅行にいってきた。11歳の息子はもう何度も行っているけど、2歳の娘にとっては初の沖縄。観光はせず、ホテルにこもってプールと海を楽しむ旅。台風の影響で飛行機がとぶか心配だったけど、往路のルートが少し遠回りになっただけだった。沖縄はおおむね快晴。

子連れでの旅行の感想を、宿泊・食事・移動の3つの観点で書く。

宿泊

旅行の際のホテル選びはいつも迷う。沖縄は規模や施設の似ているホテルが多いので、決めるのに時間がかかる。今回の旅行では以下の条件をもとに、1-2泊目を「ホテルモントレ沖縄スパ&リゾート」、3泊目を「琉球ホテル&リゾート名城ビーチ」にした。

  • 子ども向けのプールとビーチがある
  • 屋内プールとキッズスペースがある(雨が降ったときのため)
  • 部屋の風呂が洗い場付き
  • コインランドリーがある

どちらのホテルもプールの種類がたくさんあって、プールとビーチの行き来もしやすいので、11歳の息子は飽きずにずっと水で遊んでいた。部屋をはじめ館内もきれいでリゾート感のあふれるつくり。水につかりたいと思ったときに、部屋で水着に着替えてそのままプールと海にアクセスできるのはすばらしいと思う。

モントレ沖縄のプールとビーチ

部屋から見たプール。ビーチは右側、プールをいったん出て坂を下った場所にある。

ぼよんぼよんしたり、すべったりできるドームのプールに息子がはまり、繰り返し遊んでいた。子どもが楽しめるプールとして、スライダーと波の出るプールもある。娘は波の出るプールにつかっていた。

ビーチはサンゴが多めで裸足だと痛い。

琉球ホテル&リゾートのプールとビーチ

部屋からの眺め。プールとビーチがつながっていて行き来が楽。手前側のプールエリアが子ども向けのようで、バケツスプラッシュとアスレチックのある浅いプール、流れるプール、スライダーと充実していた。

プールサイドに植物がもりもり植えられていて南国気分を高めてくれる。

海は遠浅で透明度が高めだった。ビーチはさらさらの砂で裸足でも痛くない。

食事

今回の旅行では夕食に困った。朝食はホテルでビュッフェだし、昼食は道の駅や市場に行けばおにぎりやソーキそばを売っており、2歳の娘にも何かしら食べさせられるものがある。でも夕食はホテル内も周辺の店もほぼ予約で満席。空いているところがあっても、遅めの20時とか21時の枠だったり、お値段が高めで子連れで入りづらそうなところだったり。

どの店も夏のハイシーズンに合わせて席を用意しているわけではないから、この時期に混むのは仕方ないと思うがこれほどとは…。前もって下調べして予約しておけばよいのかもしれないけど、当日そのときの気分で何を食べるか決めたいという気持ちもある。

そんな中、今回の旅行でごはんが一番おいしかったのが「糸満漁民食堂」。3泊目の琉球ホテル&リゾートから車で10分くらいと近く、評判もよさそう。予約不可なので、開店時間の18:00に合わせて行ったら意外とすんなり入れた。周りに小さい子どもを連れた家族が何組かいたし、店内に絵本が置いてあったりと、子連れでも入りやすい雰囲気だった。頼んだ料理すべてがおいしかったし、値段も手頃でまた行きたい。

移動

2歳の娘を連れての沖縄旅行の懸念は飛行機での移動にある。羽田と那覇の間の片道3時間くらい、機内でおとなしくしていられるか。

往復ともにJALA350に乗ったのだけれど、エコノミーでも機内エンタメが観られることに助けられた。おやつを食べたり昼寝もしたので、動画をずっと観るわけではないけれど、搭乗してから着陸するまで、娘が観たいと言ったときにすかさず観せられる環境はすごくいい。シナぷしゅ・アンパンマンひつじのショーンなど子ども向けのコンテンツがそこそこある。旅行前の準備として、娘の好きなシナぷしゅをAmazon Prime VideoからPCにダウンロードしたり、シールブックと大量のおやつをかばんにつめこんだりと万全の体制で行ったけど、おやつ以外は必要なかった。A350は新しい機体だけあって、エンジン音が気にならなかったし、空気も乾燥してないし、と大人にとっても快適だった。

FOSS4G LT会 #001で登壇した

8/7に技術コミュニティのイベントで初登壇してきた。

osgeojp.connpass.com

申し込み

FOSS4G関係のイベントに参加したいと思っていたところ、OSGeo.JP主催のLT会があることを知った。他の人の発表を聞くだけでもよかったけれど、発表時間5分だし、参加者は多くても50人くらいだし、配信や録画なしだし、これは人生初の登壇をするよい機会なのではと思った。

とはいえ、登壇してみるかと思うことと、実際に登壇の申し込みをすることの間には大きなギャップがあった。登壇を申し込むぞーとconnpassのイベントページに行くのだけれど、準備や発表がきちんとできるか不安になって、なかなか申し込みのボタンを押せない。そうして何日か迷っているうちに、だんだんと登壇枠が埋まってきて焦る。

登壇枠が残り2-3枠になったところでようやく覚悟を決め、申し込みのボタンをポチっと押せた。このまま登壇枠が埋まるのを眺めて登壇する機会を逃したら次も登壇しないだろうということと、登壇しなかったことを後悔するよりは登壇して失敗したことを後悔する方が自分のためになるのではということを考えたりした。「#とりあえず登壇」という言葉や、「登壇はいいぞ」って言っているブログ記事などを見て後押しされたのもある。

準備

登壇の申し込みを迷っているときから、発表するならMapillaryの画像データとStreetCLIPを使ったネタにしようと考えていた。5分の発表時間に収めるストーリーをあれこれ考えたり、画像データの収集をはじめとするプログラムを書きだしたのは申し込みをしてから。準備の見積もりが甘く、スライドにはりつけるグラフを発表当日までつくったりとけっこうドタバタだった。

準備のなかでも時間がかかったのはプログラムを書くところ。ふだん仕事であまりプログラムを書かないし、今回はStreetCLIPを使うから全部Pythonで書くと決めたけれど、Rに比べてPythonは不慣れでちまちま調べながら進めることになった。たいへんではあったけれど、自分が調べてみたいと思ったことのためにプログラムを書くのって、こんなに楽しかったんだとあらためて気付いた。

発表当日

準備のところでも書いたとおり、スライドづくりがギリギリになってしまい、当日会場に向かう電車の中でもスライドをなおしていた。さらに自分が発表で使うM1 MacBook AirHDMIの口がないことに気づいたのが当日で、あわてて赤坂見附ビックカメラに寄ってUSB Type-CとHDMIの変換ケーブルを買ってから会場入りした。

会場の紀尾井タワー

会場案内

初登壇ということもあり、オープニングから自分の発表までひたすら緊張していた。自分の番がきたとき、外付けディスプレイとKeynoteの設定であたふたしてしまい、運営スタッフの方々にお手伝いしてもらった(すみません)。話し始めたら少しずつ緊張がとけて、無事に時間内におわることができた。

他の人の発表は、LTとは言えどれも地理空間情報の深くて濃い話ばかりで、こんな分野もあるのかと自分の知らない世界が広がった。発表後の交流会では、ぼっちにならないか心配だったけど、ありがたいことに話しかけてくれる人・話してくれる人がいてうれしかった。「発表おもしろかったです」と言ってくれる人もいて、そう言ってもらえたことはこれからもずっと憶えているんだろうな。

さいごに

「登壇はいいぞ」を実感できた。登壇の申し込みボタンを押すことができてよかった。運営スタッフの皆様、参加者の皆様ありがとうございました。

登壇者はTシャツがもらえた。うれしい。

AWS SAA-C03合格までに勉強したこと

久しぶりの投稿。2024年1月末にAWS Certified Solutions Architect Associate 試験(SAA-C03)を受けて合格したので、いまさら感はあるが自分が勉強した内容を記す。

試験勉強を始める前の状態

試験勉強を始める前の、自身のAWSの知識と経験を前提条件として載せておく。これまでにAWSで利用したことがあるサービスは、EC2・VPC・RDSあたり。利用したといっても10年くらい前の話なので、たとえばEC2に関してはインスタンスタイプを選ぶとか、EBSやPublic IPをつけたりはずしたりできるとか、おぼえているのはそのくらいのレベル。その他にいくつかのサービスを机上調査として調べたことがあり、それらのサービスは使ったことはないものの、名前を聞いたらどういう場面で使われるものかはわかる。ここ数年はAWSをさわる機会がなく、仕事でクラウドサービスが必要になったときにはAzureを使っている。

試験勉強として行ったこと

受験にあたり、以下の3つの教材を使って勉強した。

  1. Udemyの講義動画
  2. AWSの試験問題サンプル
  3. Udemyの問題集

はじめにUdemyの講義動画を購入し、見終わったら受験するかと軽く考えていた。が、なかなか視聴のペースが上がらず、2ヶ月たっても1/4くらいしか進まなかった。このままだと動画が見終わらず、いつまでたっても受験できないのではと思い、勉強法をかえることにした。とりあえずゴールをつくって自分を追い込もうと思い、1ヶ月後の試験を予約した。そこから試験までの1ヶ月は、AWSの試験問題サンプルとUdemyの問題集を使って勉強した。

1. Udemyの講義動画

AWSのサービスの全体像を把握したいと思い、SAA-C03の試験対策として評判のよいUdemyの講義動画「Ultimate AWS Certified Solutions Architect Associate SAA-C03」を購入した。

www.udemy.com

コンテンツはスライド資料による講義がメインで、ハンズオンとしてAWSの管理画面上でデモを行う動画が入っていたり、セクションの最後にミニテストがある。

スライドの文字、口頭説明などすべてが英語。自分はスライドの文字の読み取りはなんとかなったが、口頭説明の聞き取りができず、自動翻訳の字幕に頼りっきりになってしまった。自動翻訳の字幕があるのはありがたいのだが、訳文がわかりにくかったり反対の意味になっていることがあり、違和感をおぼえるたびに見返したり調べたりするのが地味にストレスだった。

全体で約28時間ある動画を、1日あたり5-30分見た。ペースにばらつきがあるのは、その日のモチベーションと疲れ具合によるもの。2ヶ月かけてEC2とRDS, Auroraのセクションまで見終わったところであきらめた。

スライドは要点がわかりやすいし、(自分は途中までしか見ていないが)AWSの主要なサービスを一通り網羅しているので、英語が苦にならない人にはよい教材だと思う。

2. AWS公式の試験問題サンプル

20問だけではあるが、正解と解説つきの試験問題サンプルがAWSから無料で提供されている。「AWS Certified Solutions Architect - Associate」のページからPDFをダウンロードできる。

aws.amazon.com

Udemyの講義動画をあきらめた後に1回、本番の試験直前に1回と計2回解いた。問題を一通り解いた後、1問ずつ答え合わせをして、正解・不正解にかかわらず、すべての選択肢についてなぜ合っているのか、どこが間違いなのかを自分が納得するまで調べるようにした。

本番の試験における設問と選択肢の出かたが把握できるので、SAA-C03の受験を決めたら一番はじめにとりかかるとよいかもしれない。

3. Udemyの問題集

AWS公式の試験問題サンプルは有用なのだが、いかんせん20問しかなく試験範囲をカバーできないので、Udemyで問題集「【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集(6回分390問)」を購入した。

www.udemy.com

全部で6回分の試験が含まれているが、購入した当時は最後の6回目の試験がSAA-C02版だった(はず)なので、解いたのは5回分。1回分の試験は、本番と同じ65問で構成されている。問題集の使い方はAWS公式の試験問題サンプルと同様で、1回分の試験を解いた後に、1問ずつ解説を参考にすべての選択肢の妥当性を確認するようにした。問題を解くのに1-2時間、答え合わせに3-4時間かかった。5回分の試験をすべて2周できればよかったのだが、1ヶ月では時間が足らず、2周目ができたのは1回分だけだった。とはいえ、答え合わせに時間をかけたことで、1周しただけでも知識の補強と定着ができたように思う。

試験当日から合格まで

試験は自宅に最寄りのテストセンターで受けた。前半の問題で悩みすぎて最後の方は時間が足りなくなってしまい、全問回答したのは試験終了の3分前だった。本番の緊張感と長文の設問を繰り返し読んだことで、試験後は疲れがどっと出た。感覚的に5-6割しか正解していないだろうから不合格だと思って、試験後すぐに次回の試験に備えて復習をはじめた。

合格を知ったのは、試験翌日にAWSのトレーニングサイトを見たとき。720/1000点以上で合格のところ、776点とれていたので驚いた。合格自体は、試験当日の夜にcredly.comドメインのメールアドレスから、SAA-C03のバッジを獲得したよとお知らせメールが来るのでわかる。自分の場合は、バッジ獲得お知らせメールをOutlookがフィッシングと誤解して隔離しており気がつかなかった。

OSRMのルート検索結果をOpenStreetMapの地図上に描画する

前回はPC上にOSRMのサーバを用意し、ルート検索を実行するまでの流れを確認した。

bannyaaa.hatenablog.jp

今回はその続きとして、OSRMのサーバから返されたルート検索結果を、Leafletを用いてOpenStreetMapの地図上に描画する。

環境

  • OS: Windows 11 Home: 21H2
  • Leaflet: 1.8.0
  • Chrome: 104.0.5112.81
  • OSRMのサーバ周りの環境は前回の記事を参照

地図の表示とルートの描画

ルート描画時に背景となる、OpenStreetMapの地図タイルを表示する仕組みを用意する。LeafletのQuick Start Guideを参考に、以下のHTMLファイルをつくる。

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>OSRM routing</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css" 
   integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ=="
   crossorigin=""/>
  <script src="https://unpkg.com/leaflet@1.8.0/dist/leaflet.js"
   integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ=="
   crossorigin=""></script>
</head>
<body>
  <div id="map" style="height:600px"></div>
  <script>
    // 東京駅と羽田空港が収まる地図の初期表示位置
    let map = L.map('map').setView([35.61, 139.78], 12);
    
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);
    
  </script>
</body>
</html>

地図タイルの表示ができたところに、ルートを描画する仕組みを追加する。OSRMのサーバに対してルート検索のリクエストを実行し、そのレスポンスから抽出したGeoJSON形式のジオメトリをLeafletに渡す処理を書けばよい。上記のHTMLファイルに追記するJavaScriptのコードは以下のとおり。

// ローカルPC上のOSRMサーバで東京駅から羽田空港までのルートを検索するURL
const url = 'http://127.0.0.1:5000/route/v1/driving/139.7681482,35.6798851;139.7845835,35.5491518?geometries=geojson&overview=full'

async function addRouteLayer(){
  const response = await fetch(url);
  const json = await response.json();
  L.geoJSON(json['routes'][0]['geometry']).addTo(map);
}

addRouteLayer();

なお、json['routes'][0]['geometry']とアクセスすることで、以下のGeoJSON形式のジオメトリが抽出できている。

{"coordinates":[[139.768429,35.679767],[139.768491,35.679864],[139.768635,35.68016],[139.769065,35.680895],
...省略...
[139.784785,35.549047],[139.784681,35.549197]],"type":"LineString"}

できあがり

最終的にできあがったHTMLファイルは以下のとおり。

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>OSRM routing</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css" 
   integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ=="
   crossorigin=""/>
  <script src="https://unpkg.com/leaflet@1.8.0/dist/leaflet.js"
   integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ=="
   crossorigin=""></script>
</head>
<body>
  <div id="map" style="height:600px"></div>
  <script>
    // 東京駅と羽田空港が収まる地図の初期表示位置
    let map = L.map('map').setView([35.61, 139.78], 12);
    
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    // ローカルPC上のOSRMサーバで東京駅から羽田空港までのルートを検索するURL
    const url = 'http://127.0.0.1:5000/route/v1/driving/139.7681482,35.6798851;139.7845835,35.5491518?geometries=geojson&overview=full'

    async function addRouteLayer(){
      const response = await fetch(url);
      const json = await response.json();
      L.geoJSON(json['routes'][0]['geometry']).addTo(map);
    }

    addRouteLayer();
    
  </script>
</body>
</html>

ローカルPC上でOSRMのサーバを立ち上げた状態で、このHTMLファイルをChromeで開くと、東京駅から羽田空港までのルートが青線で描画されていることが確認できる。

© OpenStreetMap contributors

OSRMのサーバを立ち上げてルート検索を行う

OpenStreetMapのデータをもとにルート検索を行える、OSSのルート検索エンジンの1つに、OSRM (Open Source Routing Machine, http://project-osrm.org/) がある。今回は、PC上にOSRMのサーバを用意して、ルート検索を行う。

環境

  • OS: Ubuntu 20.04 LTS (Windows 11 Home: 21H2のWSL2にインストール)
  • Docker Engine: 20.10.7 (上記のUbuntuにインストールしたCommunity Edition)
  • OSRM: 5.26.0

ルート検索の準備

OSRMのサーバをPC上に立てる。OSRMのサービスを構成する複数のソフトウェアがGithubで公開されているが、今回はそのなかからルート検索エンジンの本体にあたるosrm-backendを使う。osrm-backendのリポジトリのQuick StartにDockerコンテナを用いたサーバ構築手順が書かれており、その流れに沿って作業をする。

はじめにGeofabrikからOpenStreetMapのデータを取得する。Quick Startの手順ではベルリンのデータをダウンロードしているが、ここでは日本の関東地方のデータをダウンロードする。

$ wget https://download.geofabrik.de/asia/japan/kanto-latest.osm.pbf

次に、ダウンロードしたOpenStreetMapのデータを加工する。OSRMでは、ルート検索の計算プロセスとして「Contraction Hierarchies (CH)」と「Multi-Level Dijkstra (MLD)」の2種類が用意されている。どちらの計算プロセスを選択しても、ルート検索の処理速度を向上させるために事前にデータ加工を行う必要がある。Quick Startには、巨大な距離行列 (どの程度の大きさか具体的な指標は書かれていないが) を扱うような場合を除いて、基本的にMLDを使うのがおすすめと書かれている。Quick Startの手順もMLDを使ったものになっているので、ここでもMLDを使うことにする。

先ほどダウンロードしたOpenStreetMapのデータの置かれているディレクトリで、以下のMLD用のデータ加工のコマンドを実行する。

$ docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-extract -p /opt/car.lua /data/kanto-latest.osm.pbf
$ docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-partition /data/kanto-latest.osrm
$ docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-customize /data/kanto-latest.osrm

実行結果として、以下のファイルが生成される。

$ ls kanto-latest.osrm*

kanto-latest.osrm                   kanto-latest.osrm.enw                 kanto-latest.osrm.properties
kanto-latest.osrm.cell_metrics      kanto-latest.osrm.fileIndex           kanto-latest.osrm.ramIndex
kanto-latest.osrm.cells             kanto-latest.osrm.geometry            kanto-latest.osrm.restrictions
kanto-latest.osrm.cnbg              kanto-latest.osrm.icd                 kanto-latest.osrm.timestamp
kanto-latest.osrm.cnbg_to_ebg       kanto-latest.osrm.maneuver_overrides  kanto-latest.osrm.tld
kanto-latest.osrm.datasource_names  kanto-latest.osrm.mldgr               kanto-latest.osrm.tls
kanto-latest.osrm.ebg               kanto-latest.osrm.names               kanto-latest.osrm.turn_duration_penalties
kanto-latest.osrm.ebg_nodes         kanto-latest.osrm.nbg_nodes           kanto-latest.osrm.turn_penalties_index
kanto-latest.osrm.edges             kanto-latest.osrm.partition           kanto-latest.osrm.turn_weight_penalties

OSRMのサービスを5000番ポートで起動すれば、ルート検索を実行できるようになる。

$ docker run -t -i -p 5000:5000 -v "${PWD}:/data" osrm/osrm-backend osrm-routed --algorithm mld  /data/kanto-latest.osrm

ルート検索の実行

OSRMのサーバが用意できたので、ルート検索を試してみる。検索対象は、東京駅の八重洲口から羽田空港の第1ターミナルまでの道のりとする。

OSRMのサーバの使い方は、OSRMのAPIドキュメント(2022/07/28時点でドキュメントのバージョンはv5.24.0)に書かれている。OSRMのサーバは複数のサービスを提供しており、今回はそのなかから、2点間の最速ルートを探すRoute serviceを使う。APIドキュメントのRoute serviceの箇所を参照して、OSRMのサーバに送るリクエストを準備する。

Route serviceのリクエストは、出発地点と到着地点それぞれの緯度経度が必須のパラメータとなる。出発・到着地点の緯度経度の取得方法として、OpenStreetMapのWebサイトで提供されている地物検索の機能を使い、それぞれの地点付近の適当なノードを探すアプローチをとる。

出発地点の東京駅八重洲口は、ID: 6397151768のノードの緯度経度35.6798851, 139.7681482を設定する。

© OpenStreetMap contributors

到着地点となる羽田空港第1ターミナルは、ID: 2206530973のノードの緯度経度35.5491518, 139.7845835を設定する。

© OpenStreetMap contributors

また、ルート検索結果を地図上に可視化するときなどにデータの扱いが便利になるため、以下のオプションをリクエストに付与する。

  • 検索結果のルートのジオメトリをgeojson形式で取得するためのgeometries=geojson
  • 検索結果のルートのジオメトリを詳細な部分まで取得するためのoverview=full

出発・到着地点の緯度経度 (「経度,緯度」の順番にする必要がある点に注意) と追加のオプションを設定したリクエストを、自身のPC上で起動したOSRMサーバに送る。

$ curl "http://127.0.0.1:5000/route/v1/driving/139.7681482,35.6798851;139.7845835,35.5491518?geometries=geojson&overview=full" 

以下のようなレスポンスが返ってくれば、ルート検索が実行できている。

{"code":"Ok","routes":[{"geometry":{"coordinates":[[139.768429,35.679767],[139.768491,35.679864],[139.768635,35.68016],
...省略...
[139.784681,35.549197]],"type":"LineString"},"legs":[{"steps":[],"distance":21800,"duration":1230.7,"summary":"","weight":1230.7}],"distance":21800,"duration":1230.7,"weight_name":"routability","weight":1230.7}],"waypoints":[{"hint":"SwJCgP___3-0AAAA0gAAAAAAAABVAAAAL4OWQkw1QkEAAAAAQ1YNQrQAAADSAAAAAAAAAFUAAADvAwAAbbJUCBduIAJUsVQIjW4gAgAAvwHZCL3c","distance":28.611262,"name":"","location":[139.768429,35.679767]},{"hint":"bjgzgP___38RAAAARgAAAAAAAAAAAAAAigmZQbnlaUIAAAAAAAAAABEAAABGAAAAAAAAAAAAAADvAwAA6fFUCA1wHgKI8VQI4G8eAgAArxTZCL3c","distance":10.116086,"name":"","location":[139.784681,35.549197]}]}