「ちょっとSpatial、おもしろいよね」

新井庸介氏(以下、新井):ここから早川くんに加わってもらい、2人でセッションをします。では早川くんちょっと来てください。早川くんが動いている間にちょっと僕はデモの環境のセットアップをします。では1つ、よろしくお願いします。

早川:よろしくお願いします。

新井:デモに入る前に……、彼が何者なのかを直接語ってもらいます。はい、どうぞ。

早川博氏(以下、早川):ご紹介にあずかりました、早川と申します。私、日本オラクルでプリセールス・エンジニアという仕事をしております。

プリセールスは、製品を買ってくれそうなお客さまに「こうやって扱ったらうまく製品を活かせますよ」と、導入のコンサルティングのようなことをしている仕事です。技術的にはJavaを中心にして、弊社のミドルウェア製品、あとはPlatform as a Serviceですね、PaaSの製品群をやっております。

実はデータベースは、私がいくら売っても数字にならないという関係性なんですけれども。「ちょっとSpatial、おもしろいよね」ということで、いろいろいじらせていただきました。

最近はマイクロサービス・アーキテクチャを少し勉強していて、外で話したりもしています。という自己紹介でございました。

新井:ErgoDoxについてはいいんですか?

早川:えっと、これは……、大丈夫です(笑)。

新井:(笑)。

早川:お好きな方は声かけてください。よろしくお願いします。

新井:早川くんはこういう2分割されているキーボードを使っている、すてきな感じなんですけど。

僕、今日はぜひ聞いてみたいのです。「ErgoDoxを使ってるぞ」という方いらっしゃいますか?

(会場無音)

い……いない? いないね。早川くんはこれをメジャーだと言い張っていますが、そうでもないということが今日わかりました。すいません。

最適避難経路のリアルタイム算出に挑戦!

では、デモにいきたいと思います。まず最初にデモのシナリオをご紹介します。これで最適避難経路のリアルタイム算出をやってみたいと思います。ちょっと硬いですけれど、防災の話があり、作っていたものです。

現在の位置を起点として最適な避難経路をお伝えをするというアプリケーションを作りました。そういった感じで見てください。

例えば「ゲリラ豪雨がありました」というときに、どこに逃げたらいいかわからないですよね。避難所とか言われてもわからない。そこで「あなたのいるところだったら、ここに行くといいですよ」とガイドしてくれるアプリケーションです。

ただ、このアプリケーションの特徴は……。災害状況などは、例えばゲリラ豪雨だったり、路面が陥没したり、状況は刻々と変わるわけですね。陥没したとか、ここは混雑して行っちゃダメ……など。

そういうものをリアルタイムで教えてもらわないと、結局どこにも行けないみたいなことがある。災害状況の変化に合わせて、動的にそういう情報がサーバから降ってきて、動的にリルートをしてくれるものがあると便利かなと思い、今回作ってみました。

Google マップでは普通にナビゲーションなどができて、みなさんの中でもお使いになってる方もけっこういらっしゃるんじゃないかと思います。どの道が混んでるのか、どの道が通行止めなのかはGoogle側がすべて握ってて、僕たちが好きにできるわけじゃないんですよね。

ここでSpatialを使いました。まさにナビゲーションシステムそのものを作って、自分の好きなように「ここには立ち入るな」「ここは来ちゃダメ」「こっちに逃げるといいよ」とガイドできるようなものを作ってみた。まさににナビを作ったという感じですかね。そんなふうに見ていただければと思います。

刻一刻と変わる避難情報をどうとらえる?

デモシナリオとしては、4つお見せしたいと思います。まずは、自分がいる場所から「逃げるべき避難所はここですよ」というガイドがあり、そこまでのルートを案内させる。

まずシナリオ1ですね、「ある道路が立ち入り禁止になりました」というときにどうなるか。それから「あるエリアが立ち入り禁止になりました」というときに「こういうふうになりますよ」など。それから、「自分が逃げている避難所が使えなくなりました」。そして「自分が逃げている避難所よりもいいところが新しく増設されました」という、この4つのシナリオをお見せしたいと思います。

ちなみに、地図が出てきて「こういうふうに行ったらいいよ」とナビゲーションがありますけど、その経路検索はすべてSpatialで計算をさせています。線の立入禁止や面の立入禁止も、Spatialにデータを突っ込むことによって実現させています。

また地図が出てきますけど、Google マップのAPIは避難所のポイントを描画し、Spatialから降ってくる最適避難経路を1本の線として描画する描画APIしか使っていません。という感じで見ていただければと思います。

では、前置きが長くなりましたがいきましょうか。これはモバイルの画面とかと思っていただければいいかと思います。うまくGPSがとれなかったので渋谷を起点にやりました。

今、自分がここにいるとして、ゲリラ豪雨や陥没があって、ちょっと避難しなきゃいけない状況だった時。この画面を、このアプリケーションを立ち上げたと思ってください。

そうするとまず自分の現在地を起点に、一番近い避難所3点をご案内する仕掛けになっています。

例えば「ここ一番近そうだね」と見ますと、避難所の情報とか出てきて「まだ空きがあるからいけそうだね。ナビゲーションを開始」とやると、こういうふうになります。

ちなみに、今ここではなにをしたかというと、現在地(origin)、それから自分が逃げるべき場所(destination)の2つを、mBaaSを介してSpatialに渡してあげる。そうすると、Spatialが最適経路検索をしてデータを返してくれる感じになっています。

こうやって経路検索で経路が出ましたので、「なるほど、スペイン坂あたりを通って逃げればいいのね」がわかりました。

Spatialが避難場所への最適経路を表示する

さて、こうやって僕が歩いている間に状況が変わったとします。まず1つ、「ある通りが通行止めになりました」というのがあります。バックエンドのオペレーターである早川くんは、管理画面を通じてSpatialに「ここの線は通行止めだよ」と指示を送ります。……送ってください。

はい、送りますとこうなります。現在の避難経路に通過できない箇所があることがわかりました。ほかの経路を表示します。

自分が逃げるべき避難所をポイントする。自分の場所と避難所の情報をSpatialに送ってあげると、最適経路を出してくれる。そこで「状況が変わりました」と表示されます。これを押すと、こうなるわけですね。

今、早川くんはこの地図の赤いエリアが通行止めだよというデータをSpatialに送りました。それがイベントとして、このモバイル画面に降ってきます。

リルートをしたときにSpatialは、先ほどと同じように自分がいる場所と避難所との間で経路検索をします。しかし、通れないエリアを考慮して「じゃあこう逃げると最短です」と返してくれています。まさにカーナビゲーションですよね。

では、続いて面の立ち入り禁止についてです。ある通りが通行止めになるケースもあれば、ある面がボコッと通行止めになるケースもありますよね。そういった場合にどうでしょうか。

もう1回やりますね。現在の避難経路に通過できない箇所があることがわかりました。ほかの経路を表示します。

今度はここが全部ダメになってますね。そうすると、「このdisableになっているエリアを鑑みるとこう逃げるのが最短ですよ」とSpatialは教えてくれます。

人間の目ではいまいち「遠回りなんじゃないの?」と思うんですけど、これが最短みたいですね。こんな感じです。

地図情報が入っている構成をデータベース側に作っておく

では、指示されたとおりに逃げているとします。例えば「この避難所が実は使えなくなりました」「定員オーバーでもう行けなくなりましたよ」となった場合、ここが黒くなって別のところが案内される。

「しょうがない。こっちに逃げようかな」とナビゲーションをしますが、新しい避難所がオープンすると、このような感じでデータが降ってきます。そして「では、こちらに逃げようかな」とできるわけですね。そういった感じです。

2度目はうまく動いてよかったですね。bunkamura オーチャードホールが表示されているので、こちらに逃げましょうか……となる。だいたいこんな感じのことができるようになっています。

まさしくカーナビゲーションです。しかも、本当にデータベースの中に地図の情報が全部入っていて、自分の場所と避難所の場所をもとに経路検索をさせているものになります。なかなか素敵じゃないかなと思うんですけれども、具体的にどんなふうに作っているのかを、ここから早川くんにバトンタッチしまして、少し説明してもらいます。お願いします。

早川:はい。再びの早川です。

今回は防災というテーマで、ある提案活動のなかでデモを作るということで、今回お見せしたデモを私のほうで作りました。どう作っているのかを少しご紹介させていただきます。

構成としてはこうなっています。地図情報が入っている構成をデータベース側に作っておくのは、今までの話のとおりです。

アプリケーションのところで、クライアントサイドとサーバサイドのアプリケーションを用意する必要はあります。しかし、Java EEではなくて、サーバサイドはSpring Bootを使ってRESTのAPIを実装しています。

データベースの位置情報検索の処理など、先ほどSQLでデータベースで処理を依頼する例を新井さんご紹介してましたが、JavaのAPIからこれを操作することができて、それを実行してRESTの口をクライアントに出しています。

被災者用のクライアント側には、Google マップのAPIを使っています。あとは先ほど、通行止めの経路を追加したりしていた管理者側ですかね。そういったものを操作するAPIも用意しています。そこには今GUIはないんですが、RESTで叩いて場所を追加したりしています。

最短経路を計算し、立入禁止区域も考慮

あとは、管理者が追加したときに自動的に被災者側のクライアントにプッシュで通知するところに関しては、Server Sent Events。サーバからのプッシュで情報を送る方法にはWebSocketなど何種類かあると思うんですけど、今回はたまたまServer Sent Eventsを使いました。

これはとくに深い理由はなくて、その時に自分がやってみたかった技術がこれだったからですね(笑)。という感じで実装しています。

全体の構成としてはこうなんですが、今回のポイントは位置情報検索をどうやるか、あと経路検索をどうやるかというところです。

この中では2種類の方法でデータベースにアクセスをしています。もうすでにご紹介のあったSQLでつないでいる部分が、地図上のオブジェクトを検索するというものです。指定した距離の範囲内で該当するものを何個かあげてくれる。

今回の場合は、半径を指定するのではなくて、自分の位置から最短のものを上位何件というかたちで指定してとってくるようになっています。

もう1つは、自分の位置から目的地までの最短経路を計算するところです。ここはSQLをJavaから直接書くわけではありません。SpatialのJava APIというものがあり、ここから間接的にデータベースを使っています。

後ほどサンプルコードをご紹介しますが、これを使うと2点間の最短経路を簡単に計算するし、立入禁止区域とかを考慮した指定の仕方ができます。

コード例です。コード例はSQLではなくて、先ほど右側にあったSpatial Java APIの使い方のコード例です。

準備しなくちゃいけないオブジェクトが3つあります。今ここで映っているのは2つなんですけれども、NetWorkMetadataをまず作って、NetworkIOというオブジェクトを作ります。これは……細かいところはあれなんですけど、こんな感じでやります。

データベースに登録しておいたネットワークネームを使いますが、これをやるとNetworkIOというオブジェクトに地図情報の中の道路のネットワーク情報がメモリにロードされます。それを持っているのがNetworkIOというオブジェクトなんですが。

ダイクストラ法というのが1つのアルゴリズムを活用

次のところ、この下側のところですね。

ここではgetNetworkAnalystというメソッドを呼び出します。返り値としてはNetworkAnalystという型のオブジェクトが返るんですけれども、これを呼び出すと、メモリにロードしたネットワークを使って、それに対して最短経路を算出したりします。そういう分析のAPIを提供するオブジェクト、それがNetworkAnalystなんです。それが返ってきます。

新井:ネットワーク情報はいわゆる道路の情報で、渋谷でいうと公園通りからこう通ってスペイン坂こうでみたいな情報です。NetworkAnalystはそれを分析するためのユーティリティインスタンスみたいな感じですかね。

早川:そういう感じですね。はい。実際ネットワーク情報にアクセスする場合は、そのAnalyst経由でいろんな処理を実行します。

先ほどのデモのシナリオの中で、まず避難所を検索します。3つピックアップして、それぞれの最短経路を算出することをやりたい場合、どう書くかがこちらです。

避難所の候補を3件を取り出してくるということに関しては、SQLを書いてJDBCで投げます。上の部分、ちょっとSQLで直接書いていないんですけど。このコードの中でSQLを組み立てるようにしています。そういうものが書いてあります。

後半部分がポイントで、前のスライドで出てきたNetworkAnalystというオブジェクトの……ここですね。

新井:analystですね。

早川:analystのget.shorttestPathDijkstraというメソッドを呼びます。引数は主にoriginと目的地。後ろはちょっとしたオプションです。

これを使うと、ダイクストラ法というネットワーク上の経路を検索するアルゴリズムがあります。それを使って最短経路を出してくれと、データベースに投げます。そして返ってきた結果がPathというかたちになる。そういうオブジェクトで返ってくる。

新井:これもなにかほかにもいくつかメソッドがありましたよね。なにかいろんなアルゴリズムを……。

早川:そうですね。ダイクストラ法というのが1つのアルゴリズムなんですけど。A*(A-Star)というものがあるみたいです。あまりくわしくないのであれなんですけど、APIドキュメントを見ると、そういうものを選べるんだなということがわかります。

という感じで、あとは返ってきたものを描画してあげる。

イベントを受けて、もう1回経路検索をする

新井:返り値は、いわゆる経路の曲がるポイントがすべて緯度経度で返ってくる感じですよね。

早川:そうですね。はい。

新井:先ほど戻ってきたオブジェクトからそれを取り出してあげて、描画に都合のいいかたちにして、RESTのJSONのオブジェクトを返してあげればいい。フロントエンド側ですが。これは単純にGoogle マップのAPIを使うんですけど、経路検索に関してはDB側でやっています。そのため、単なる描画だけこちらでやっています。

HTML上でGoogle マップのキャンバスを作ってあげて、それに対してJavaScriptで描画のメソッドを呼んであげる。そうすると、地図上に線を書いたり、避難所のポイントを置いたりすることができます。

少し細かい話ですけど、RequireJSというフロントエンドのフレームワークを使っている場合は、こういうふうにGoogle マップのAPIをロードしなきゃいけない。そのため、こんなことをしていますというだけですね。

あとはServer Sent Eventsでサーバからプッシュで送るところです。これはServer Sent Events自体の仕組みみたいなところになります。Server Sent Eventsは、平たく言うとブラウザでファイルをダウンロードするようなかたちの接続ですね。1回接続するんですけど、サーバからデータを送ってもらう間、接続が維持されているものの延長みたいなイメージです。

1回接続すると、データ自体は送られてきません。それをそのままにしておいて、データをダウンロードするかたちでサーバ側がこれを送る。そうすると、接続が維持されていますので、クライアント側にデータが送られてくる仕組みになっています。

ですので、中身の段階でいうと、最初にクライアントとサーバの間でコネクションを確立しておいて、管理者が操作をしたらサーバからプッシュで送る。そして、その維持されているコネクションを使ってデータを送ることができます。そこから、被災者の方の端末の表示を更新する、そんな流れです。

これもちょっとコード例あるんですけど……これはなにを言ったらいいかな。

新井:あと2〜3分なので……サラッと。

早川:EventListener。これはJavaScriptの仕組みなんですけど、EventListenerというものを登録してあげます。そこでコールバックメソッドも入れておきます。

サーバ側は、これがspring bootの仕組みで、SseEmitterみたいなオブジェクトを使ってデータをプッシュします。ある名前をつけてデータをプッシュすると、JavaScript側でそれと同じ名前でイベントが発火することで実現できています。

新井:でも、クライアント側でやっているのは、イベントを受けて、もう1回経路検索をするだけですね。

早川:そうですね。画面をリフレッシュするので、もう1回サーバに聞きにいくということが行われています。そんな感じですね。はい、以上です。

Oracle Cloudのトライアルで空間検索を試せる

新井:ありがとうございます。そんな感じで、クライアント側でゴリゴリしているわけじゃなくて、サーバ側で経路検索をやっているというのが、実装例を見てわかっていただけたんじゃないかなと思います。ありがとうございます。

このSpatialなんですけど、もともとオンプレの時はそこそこ高いオプションだったので気軽に試すのはどうかなという感じだったのです。しかし、Oracle Cloudでも試せるようになってまして。

実はこれ、Oracle Cloudのトライアルで空間検索などで試せるようになっています。ぜひみなさん試してみて、「こんなことできるんだ」と実感いただきたいと思います。

(観客側に向かって)写真を撮っていただいてすごくうれしいです。ありがとうございます。

この資料はすべてダウンロードできますので、みなさんもあとでじっくり見てやってみてください。とても簡単です。まず、トライアル環境を入手して、Oracle Database CloudのHigh performance editionを立ち上げてください。

そのあとは、自分が探したいスポット情報、渋谷の109でもハチ公でもなんでもいいんですけど、検索します。そしてそれを格納する表を作って、インサートをしてみてください。その手順はこのブログにけっこうまとまっています。

あとは、先ほどお見せしたSDO、WITHIN_DISTANCEの空間演算子を試して検索みてください。もうここまで来ちゃえば、あとは簡単にそれを発行するNode.jsのアプリ書いて、APIで公開すればできてしまう代物です。ぜひお試しいただければと思います。

「Oracle Spatial 空間データで遊ぶ」

Oracle Spatialに関しては、SlideShareにけっこういい情報があがっています。概要と、あとこれのために「空間データで遊ぶ」の続編の資料があげられています。これはどういうふうに表を使って、どうやってデータを入れ込んでいけばいいかを懇切丁寧に書いてあるので、ぜひご覧になってください。

それからOracle Cloudの使い方に関してもブログに情報がまとまっています。ぜひ試してみてください。

あと、今日はアプリケーションの中でGoogle マップを使っていました。別に試して使う分にはまったく問題ないかと思うんですけど、「ここまで来たんだから、Googleのフリーでいきたいじゃん」みたいな気持ちを持たれる方もいらっしゃるんじゃないかと思います。

この中でご案内している「Oracle Spatial 空間データで遊ぶ」の中では、OpenStreetMapというオープンソースでこういう地図情報をまとめて提供するサイトの情報をOracle Databaseに入れ込んでいます。これをもとに経路検索をさせるみたいな手順についても、今、一生懸命まとめたりしています。

ですので、コアな方はGoogle マップ フリーで僕らが今お見せしたようなサービスなんかも作れちゃうかもしれません。このオレンジのほうの資料はときどき更新するみたいなので、たまに見ていただいて、いろいろ参考にしていただければと思います。

こんなふうにも使えるOracle Cloud、けっこうおもしろい内容だと思います。ぜひ触ってみてください。

では少し時間が過ぎちゃいましたけれども、私たちのプレゼンは以上になります。ご清聴ありがとうございました。

(会場拍手)