Soundscape を支える技術

このページの目的は、Soundscape アプリが内部でどのように動作しているかを大まかに理解してもらうことです。アプリを使うのにこれを読む必要はありませんが、これを書いた理由はいくつかあります。

  1. このアプリに興味を持った新規の方が、その限界がどこにあるかを理解できるようにするため
  2. このアプリで新機能によってほかに何が可能になりうるかを、ユーザーがイメージできるようにするため
  3. 開発者にアプリの機能の概要を伝えるため

このアプリを実現している技術は 2 つあります。GPS と OpenStreetMap のデータです。GPS は、スマートフォンがどこにあり、どこを通ってきたかを正確に把握させてくれます。次に OpenStreetMap のデータを使うと、近くに何があるかを見つけ、それをユーザーに説明できます。

音声ビーコン

技術的な観点では、これらは多くの面で最も実装が単純なものです。スマートフォンの位置と向きが分かっていると仮定すれば、ビーコンの音をその方向から聞こえるように調整できます。音声の位置付けには Steam Audio のライブラリを使用しており、頭部伝達関数 (HRTF) を用いて可能な限り最良の聞こえ方の位置付けを実現します。それ以外にすることといえば、ユーザーの向きとビーコンの位置の間の角度に応じて異なる音が再生されるよう、ビーコンの音を変えることだけです。角度は選択したビーコン (タクティル、フレア、ピングなど) によって異なり、ものによっては他より多くの音を持っています。これが最も単純なレベルでの音声ビーコンです。

唯一の追加的な複雑さは、スマートフォンの位置と、ユーザーが向いている方向の推定にあります。これらを順番に見ていきましょう。

位置

GPS が返す位置にはかなり大きな誤差が生じることがあり、これはスマートフォンの GPS から空がどれだけ見えるか、また何本の木や高い建物が GPS 信号をスマートフォンへ届く途中で反射しているかによって変わります。

位置のフィルタリングについて当社が採用している手法は、いわゆるマップマッチングです。これは、ユーザーが地図に載っている道や道路を進んでいる可能性が最も高い、という前提に立っています。当社では、すべての道路、小道、歩道をまとめて「Way」という用語で呼んでいます。マップマッチングは、ユーザーがこれまでどこを通ってきたかを見て、移動の方向と周辺の地図データを用いて、Way 上で最も可能性の高い位置を選びます。この手法は GPS の誤差だけでなく、地図データの誤差にも対応します。すべての Way が正確に地図化されているわけではないため、それらにも誤差があります。ユーザーがいる最も可能性の高い Way を判定するために、アルゴリズムは次の点を考慮します。

  • Way が GPS の位置および過去の GPS の位置にどれだけ近いか
  • 移動の方向 — Way と同じ方向に進んでいるか
  • 直前のマップマッチ済みの位置から新しい位置へ、Way のネットワークを通じて到達できるかどうか。これは、実際にはつながっていない Way 間の切り替え(例えば、橋で一方が他方の上を通っている、またはトンネルで下を通っている場合など)を排除するために必要です。 マップマッチングは、近くに Way がない、あるいはユーザーがどの Way 上にいるか確信が持てないと判断する場合があり、その場合は単に次の GPS の位置を待ち、確信が持てるまで再試行します。

方向

ソフトウェアでは、いくつかの方向を追跡しています。

  1. スマートフォンが向いている方向。これは、スマートフォンのロックが解除されアプリが使用中のときに使いますが、スマートフォンがロックされている場合でも、画面を空に向けて水平に持っている限り使用します。スマートフォンをバッグに入れるときには、この点を念頭に置いておくと役立ちます。立てて持ったバッグの底に水平に入れると、バッグが向いているでたらめな方向がアプリで使われてしまいます。
  2. スマートフォンが進んでいる方向。
  3. ヘッドトラッキング付きヘッドホンからの方向。現在は使用していませんが、iOS アプリは対応していました。将来追加できるように技術的な準備はできています。

スマートフォンがロックされてバッグの中にある場合、アプリは移動の方向を使います。ただし、ユーザーが移動していない場合は方向が得られません。これが起きると、音声ビーコンは音が小さくなり、ビーコンの現在の方向が分からないことを示します。ユーザーが位置を変えずに向きだけを変えている可能性があるからです。

アプリ内のいくつかの方向の用途では、方向はマップマッチ済みの Way の方向に「スナップ」されます。そのため、ユーザーがおおむね Way の方向に歩いている場合は、Way の実際の方向が正しいと見なされ、それらの計算に使われます。

まとめ

一見すると音声ビーコンは単純ですが、位置と方向の誤差を取り除こうとするマップマッチングの使用によって、相当な複雑さがもたらされています。

地図データ

アプリが使用する地図データは、そのほとんどすべてが OpenStreetMap プロジェクトに由来します。当社は、複数のズームレベルで全世界の地図を保持するサーバーを運用しています。各ズームレベルはタイルに分割されています。ズームレベル 0 は 1 タイル、レベル 1 は 4 タイル、レベル 2 は 16 タイルと続き、レベル 14 では地球全体を覆うのに約 2 億 6800 万タイルになります。各タイルには複数のレイヤーが含まれ、各レイヤーには、グラフィカルな地図を描くために使える点、線、ポリゴンがあります。そのグラフィカルな地図が、アプリの GUI でユーザーに表示されるものです。各点、線、ポリゴンには、それが何であるかを記述するメタデータが付いています。これは大部分が OpenStreetMap のデータそのままで、例えばある線は sidewalk(歩道)である footway や、minor(細道)である road といった具合です。

データは「スタイル」を通じてグラフィカルな地図に変換されます。スタイルには、各レイヤーの異なる点、線、ポリゴンをどのように描くか(例えば、小道の描き方、森林の描き方、バス停の描き方)のルールがあります。ルールはズームレベルによって変わることがあり、これがズームインするにつれて、ズームアウト時には見えなかった点や線(例えばバス停や小道)がどんどん見えてくる理由です。

スタイルを変えることで GUI 地図の見た目を変えられます。これが、当社が試している「アクセシブル マップ」の由来です。これは、より高いコントラストと、より太い線やテキストを持たせることを目指しています。スタイルはアプリに組み込まれているので、見た目を変えるためにサーバー上の地図を変更する必要はありません。

では、地図データを音声にはどう使っているのでしょうか。

地図データを音声に使う

当社は現在、音声ユーザーインターフェースを生成するために、地図データのうち比較的少量を使用しています。音声 UI のほとんどすべては、最大ズームレベルのタイルだけを使います。アプリはユーザーの周りで 2×2 のタイルのグリッドをつなぎ合わせ、その中の数個のレイヤーだけを見ます。

  • transportation - 道路、小道、鉄道、トラム軌道などすべての種類の Way 向け。
  • poi - 特定地点。例えば店舗、スポーツセンター、ベンチ、郵便ポスト、バス停など。
  • building - 単なる点としてではなく、それ以上のものとして地図化されている poi 向け。例えば大型スーパーマーケットや市庁舎など。

これは、タイルの境界をまたいで線とポリゴンをつなぎ、すべての Way をつながった Way のセグメントと交差点に変換します。これは重要で、Way に沿って検索し、どこへ行けるかを調べられるようになるからです。

解析されたデータはすべて、検索しやすい形式にも変換されるので、アプリは地図上のどの地物が近くにあるかを簡単に見つけられます。この時点でデータはカテゴリに分類されます。現在のカテゴリは次のとおりです。

  • 道路
  • 道路と小道(すべての Way)
  • 交差点 - Way が交差する点
  • 入口 - 建物上で入口として記された点。
  • 横断歩道 - 道路の横断箇所
  • POI - すべての特定地点
  • 公共交通の停留所 - バス停、鉄道駅、トラム停留所など。
  • POI のサブカテゴリ:
    • 案内
    • 物体
    • 場所
    • ランドマーク
    • 移動
    • 安全
  • 居住地とそのサブカテゴリ(次のセクションを参照)
    • 市 (City)
    • 町 (Town)
    • 村 (Village)
    • 集落 (Hamlet)

これが整っていれば、アプリは任意の位置について次のことを簡単に見つけられます。

  • 「50m 以内のすべての公共交通の停留所」や
  • 「前方の最も近い交差点」や
  • 「最も近い集落、村、町、市」

これが整っていれば、音声コールアウトの作成は、現在の位置と方向に基づいてデータを問い合わせるだけのことになります。ユーザーがタイルのグリッドを横切って移動すると、現在の位置を中心とするようにグリッドが更新されます。

さらに多くのデータ

当社のごく局所的な地図データのグリッドの問題点の 1 つは、どの方向にもせいぜい約 1km しか「見る」ことができないことです。目の前にあるものを説明するにはそれで構いませんが、ときにはもっと文脈を伝えたいことがあります。その主な例が、ユーザーが歩いていないときにアプリが使われる場合です。

ユーザーが毎秒 5 メートルを超える速さで移動しているとアプリが検出すると、世界の説明の仕方を切り替えます。すべての交差点や POI を読み上げる代わりに、読み上げる頻度を下げ、近くの道路だけを読み上げます。これの問題は、道路名を知っていても、それがどの町にあるか分からなければあまり役立たないことです。

これに対処しようと、当社は現在、より低いズームレベルでも地図データを解析し、place レイヤーからデータを抽出しています。これには町、市、地区、村などの名前が含まれます。物事を地図化することの問題の 1 つは、これらの場所の間に明確な境界が常にあるとは限らないことです。OpenStreetMap には市の境界がデータベースに含まれていることもありますが、その場合でも、当社のタイル化された地図に届く頃にはその情報が失われていることがよくあります。当社が持っているのは、地図上に場所の名前が描かれている位置です。これらは分類され、アプリはユーザーに最も近い集落、村、町、市を見つけて報告します。

多くの市では、市の正式名称が読み上げられることはありません。なぜなら、ほとんどの市は地区などのより小さな区分に分かれているからですが、それらは追加の文脈を与えてくれてとても役立ちます。ただし、特定の地区にあるある通りの近くにいるとアプリが報告するのは、その地区のラベルが最も近い点だというだけのことであり、間違っているかもしれず、あるいは川の向こう側だということさえあり得る、ということを覚えておいてください。

さらなる文脈

説明に加えられる文脈は、簡潔で予測可能に保たれている限り、多ければ多いほど良いものです。交差点を説明する際に見られた問題の 1 つは、しばしば「無名の」Way が関わってくることです。これらは名前のない Way です。地図データでは、これらは単なる小径、小道、連絡道路だったりしますが、それ以上の文脈がないと、テキストの説明ではあまり役に立ちません。幸い、もっと良くできます。アプリがすることは、無名の Way を読み上げようとするたびに、それについてもっと文脈を見つけられないか調べることです。

  • それは歩道か? OpenStreetMap の多くの地域では、現在では歩道が道路とは別に地図化されています。これらは通常 sidewalk とタグ付けされますが、その歩道がどの道路の歩道なのかは通常記されていません。

    アプリが無名の歩道に出くわすと、その横を並走していると思われる道路を探し、それを使って歩道に名前を付けます。これは当社のコールアウトにとって非常に重要であることが分かりました。歩道のすべての交差点を読み上げる代わりに、歩道に沿って移動するにつれて、関連する道路に沿って移動しているかのようにコールアウトが行われます。「小道を西へ移動中」ではなく、「Moor Road を西へ移動中」となります。ユーザーは地図化された歩道の上にいますが、説明の方がより理にかなっています。

  • 名前のある Way で終わるか? 2 つの道路をつなぐ歩行者用の小道は非常によくあります。小道の両端を見ることで、その文脈を簡単に追加でき、一方向では「Moor Road への小道」、反対側から近づくと「Roselea Drive への小道」となります。これは小道が分岐しない場合にのみ行われ、2 つの無名の小道に分岐する場合は、この文脈を追加しようとはしません。

  • マーカーの近くで終わるか? 無名の Way がマーカーの近くで始まる、または終わる場合、それを使って説明します。例えば「大きな木の分岐への小道」など。ユーザーはどこにでもマーカーを追加でき、小道のネットワークに沿ってマーカーを追加することで、ルート全体に文脈を加えられます。

  • POI に入るか出るか? 無名の Way が POI の外で始まり、その中で終わる(またはその逆の)場合、その文脈を追加できます。例えば「Lennox Park への小径」など。

  • 入口の近くで終わるか? 無名の Way が入口のより近くで始まる、または終わる場合、その文脈を追加できます。例えば「Best Buy への連絡道路」など。

  • ランドマークや場所の近くで終わるか? 無名の Way がランドマークのより近くで始まる、または終わる場合も、その文脈を追加できます。例えば「St. Giles Cathedral への連絡道路」など。

  • 行き止まりか? アプリは、どこにもつながっていない無名の Way を行き止まりとして記します。

  • 何か階段を通るか? 無名の Way が橋を渡る、トンネルを通る、または階段を上り下りする場合、これが記録され文脈に追加されます。これは目的地のタグ付けとは別のものなので、「橋を通って Lennox Park への小道」のような文脈も可能です。

これらの文脈は順番に追加されるので、一方向では「階段を通って Park Lane への小道」、反対方向では「階段を通って Lennox Park への小道」とすることが可能です。名前のある通りは出ていくときに優先され、公園は入っていくときに使われます。

将来の文脈

将来追加したいと考えている追加の文脈はさまざまあり、次のものを含みます。

  • 線状の水域に沿った Way の文脈。例えば「River Dee の隣の小道」
  • 水域の縁に沿った Way の文脈。「Milngavie reservoir の隣の小道」
  • 鉄道に沿った Way の文脈。例えば「鉄道の隣の小道」。これには鉄道路線の名前まで含められるかもしれません
  • 橋やトンネルに追加の内容を加える。それらが何の上や下にあるか。例えば「鉄道の上の橋を通って Moor Road への小道」

音声コールアウト

地図データを簡単に使える形式に整えられたので、コールアウトの生成は実際にかなり単純です。

歩行中のコールアウト

歩行中に発生し得る音声コールアウトは次のとおりです(優先順位の高い順)。

  1. 現在の目的地までの距離を説明する
  2. これから近づく交差点を説明する
  3. 最も近い 5 件の特定地点を説明する

すべてのコールアウトは頻度が制限されており、繰り返しが多くなりすぎないようになっています。ユーザーが移動を止めるとコールアウトは止まり、移動中であっても、新しい GPS の位置ごとにコールアウトが繰り返されることはありません。頻度は iOS アプリと同じで次のとおりです。

  • 現在の目的地は 60 秒ごと
  • これから近づく交差点は 30 秒ごと
  • 特定地点は 60 秒ごと

コールアウトは設定メニューでフィルターでき、この挙動を広げる余地は確かにあります。

より速く移動しているときのコールアウト

毎秒 5 メートルを超える速さで移動しているときも、現在の目的地へのコールアウトは引き続き行われますが、交差点と特定地点のコールアウトは、ユーザーがおおよそどこにいるかを説明するコールアウトに置き換えられます。これは、近くの公共交通の停留所、自分を含む POI(例えば大きな公園の中)、あるいは近くの道路と居住地を伝えます。これらは先に説明したデータを使っており、将来これのカスタマイズを許可する余地は明らかにあります。

マーカーとルート

ほとんどの場合、マーカーとルートは、GPS にも地図データにも実際には依存しない単なるユーザーインターフェースの機能です。マーカーは、ユーザーが保存したい名前付きの場所であり、ルートはそれらのマーカーの順序付きのリストです。両方を作成するユーザーインターフェースは、iOS 版から直接取り入れています。

ルートの再生

ルートが息づくのはルートの再生です。ルートが再生されると、ルートの最初のマーカーに音声ビーコンが作成されます。ユーザーがそのマーカーに近づくと、ルートは自動的に音声ビーコンをルート内の次のマーカーへ移動します。マーカーがもうなければ、ルートの再生は終了します。

まとめ

このアプリがどのように機能するかについて、いくらか理解していただけたなら幸いです。このアプリは常にユーザーからのフィードバックに基づいて発展しているので、追加できると思うものが何かありましたら、ぜひご連絡ください。


This site uses Just the Docs, a documentation theme for Jekyll.