OpenLRによる位置参照

# はじめに
この記事ではOpenLRという位置参照方法について簡単に解説します。

### そもそもなぜ位置参照が必要か
交通情報サービス提供者と交通情報サービス利用者の例を使って考えてみます。
提供者が生成した交通情報(例えば、区間Aが道路工事中)を利用者が活用する場合、この「区間A」の場所を正確に把握する必要があります。この「区間A」をどのように表現するのかというのが位置参照方法になります。

### 主な位置参照方法
世の中で主に利用されている位置参照方法は以下となります。
1. **座標参照**: 緯度・経度: 地球上の位置を緯度と経度で表現する方法
1. **道路ネットワーク参照(ID参照)**: リンクやノードとして表現する方法
1. **オープンスタンダード**: OpenLRで表現する方法

### 座標参照の課題
座標参照は多くの方に馴染みがあるのではないでしょうか？
多くのGISツールで標準機能として使用できる点を考えるとこの表現が一番良いように感じるかもしれません。確かに、点(Point)のみを表現する場合は、この参照方法が最適だと思います。地図によって多少ずれる可能性はあるものの概ね誤差なく表現できる可能性が高いからです。
線(LineString)を表現する場合はどうでしょうか？
線を表現する場合にもこの参照方法を使用することはできますが、交通情報のようなLineStringで表現されるパターンが多い場合では最適とは言えません。長いLineStringや複雑なLineStringをイメージしてもらうとわかるかと思いますが、位置参照が長くなっていきますし、そもそもこのLineStringは情報提供側の地図ベースで生成されたものなので、LineStringをそのまま表現しても情報利用側の道路ネットワークと一致しない可能性もあります。
また、データサイズの観点から考えても最適とは言えないと思います。

### ID参照の課題
この参照方法は情報提供者と情報利用者とで同じID体系であることが前提になっています。両者が同じものを使うことで、高い正解率で参照できる良い面がある一方、世の中の道路ネットワークは常に変化していくため、バージョンの違いによる参照失敗や、(当然ですが)そもそもリンクとして定義されていない道路に対しては位置参照できません。またID参照テーブルをメンテナンスするコストも必要になります。

### OpenLRとは(ChatGPTより抜粋)
>位置情報を表現するためのオープンな標準フォーマットです。OpenLRは、地図データに依存せずに位置情報を表現できるため、自動運転車やスマートフォンアプリなどのさまざまな用途に活用されています。

### OpenLRでの位置参照
以下でOpenLRが具体的にどのようなものか説明しますが、OpenLRはどの地図に対しても位置参照できる仕様になっています。表現区間を見つけるための必要最低限の属性情報だけを提供するため、情報提供者も情報利用者にも最適な位置参照となります。ただし、ID参照とは異なるため表現区間を探索する処理の実装が必要にはなりますが、OpenLRの仕様に沿って構築されたコードがすでにGitHubにありますので、少しの開発で地図に依存しないOpenLRの活用ができます。
情報提供者と情報利用者とで地図が異なる場合でも利用者側が処理を少し調整するだけで正解率も格段に上がることが期待できます。

::: note 
OpenLRの詳細な仕様はこちらを参照してください。
https://www.openlr.org/location-referencing/

Github
- Java: https://github.com/tomtom-international/openlr
- Python: https://github.com/tomtom-international/openlr-python
::: 

OpenLRには、Encoding(情報提供者が生成)とDecoding(情報利用者による参照)とがありますが、ここではDecodingについて説明します。

### OpenLRの種類
OpenLRで表現可能なものは以下のものがあります。
- Line Location
- Point Location
- Geo-Coordinate
- Circle
- Polygon

この記事では、Line Locationに関しての説明します。
以降はOpenLRの一例として`C7815BWdTiObA/9rAGAjCw==`を使って説明します。

### OpenLRに含まれる属性
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987115/fd5e02ac-c63d-41b2-8df5-4ba3aa9b3f16.png)

- OpenLRは少なくとも2点以上のLocation Reference Pointで構成されます。
- 始点・終点の緯度経度に加え、FRCやFOW、Bearingなど位置を正しく表現するための情報が格納されています。具体的な値の読み方については下で説明します。

##### Line Locationの場合の変換表
OpenLRの種類ごとに変換表の定義が異なります。下記はLine Locationの場合のものになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987115/fbb9a231-80b2-43f8-a880-bf8a2804b839.png)

### OpenLRのデコーディング
ここでは[文字列→数値化]の手順は割愛します。
※主なプログラミング言語には、この変換手順をするライブラリが存在するのでそれを活用するのがおすすめです。

数値を[Line Locationの場合の変換表]に当てはめるとこのようになります。一部文字色を変えてどの桁が何を表現しているか見やすくしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987115/cc8b46be-a896-4472-9733-9288ec42f653.png)

### OpenLRに含まれている属性情報
ここでは主要なものに絞って解説します。説明されていない属性については、whitepaperを参照ください。

<dl>
  <dt>Functional Road Class(FRC)/ Lowest FRC Next Point</dt>
  <dd>道路格を表現します。
  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987115/252bac29-74ba-48e5-b6ee-b55e63d1a7aa.png)
  </dd>
  <dt>Form of Way(FOW)</dt>
  <dd>道路の形状を表現します。
  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987115/8ece7e3a-15e5-4161-893a-039628fc20e6.png)
  </dd>
  <dt>Bearing</dt>
  <dd>方向を表現します。真北を0とし、時計回りで計算されます。
  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987115/612cccf0-af82-457b-8bda-5be991ed3850.png)
  </dd>
  <dt>Distance to next point (DNP)</dt>
  <dd>2点間の距離(m)を表現します。
  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987115/66747b91-1f29-4493-a311-740874bff0cc.png)
  <dd>
</dl>

### 最適候補の探索(簡易版)
OpenLRから取得した各種属性情報を使用し、表現対象地図の候補リンクを探索します。
※この処理もGithubのコードがすでに実装しているので独自で構築する必要はありません。

表現する地図に対して、以下の手順で候補探索を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987115/e233abd6-6c46-46b0-8a37-791f0fe8493e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987115/a4e53376-e4b5-45a4-b121-bfec9e84fa6c.png)

※始点の候補リンクと終点の候補リンクをペアごとにランク付けし、一番スコアの高いものを選ぶという処理が裏では行われています。このスコア付けの部分は地図の特性に合わせて調整することができます。

### デコーディングの精度
OpenLRに含まれる属性情報は情報提供者の地図属性に依存するため、情報利用者側は情報提供者がどの地図を使っているのか把握することが必要になります。
同じ地図を使用する場合はかなり高い正解率で表現することができます。

#### OpenLRの課題(よくある失敗例)
大きく2種類の失敗パターンがあります。

1. パスが見つからない
1. 意図するパスと異なる

パスが見つからない原因の多くは道路ネットワーク自体に差があるケースです。地図の違いによるものはもちろん、バージョンの違いで新規道路の有無で失敗するパターンが多いです。ただ、表現地図側にそもそも道路リンクが存在しないのであれば表現は不可能であるため、失敗のままで処理するのが正しい処置となります。

一方、意図するパスと異なる失敗は対処するべきものになります。
この失敗の主な原因も同様に地図の違いによるものですが、大きな違いは属性の定義の差異による失敗のことが多いです。
例えば、区間Aを構成する道路を情報提供者側ではFRC=1と位置付け、情報利用者側ではFRC=3と位置付けられていた場合、当該道路を正しく選択できない大きな原因の一つとなります。

#### 対策
本記事では説明を割愛していますがOpenLRの最適候補探索の処理では多くのパラメータが用意されていてすべてカスタマイズが可能です。

- 緯度経度から半径nメートルまでを候補リンクとみなすか
- FRC差異の重みづけ
- FOW差異の重みづけ
- Bearing差異の重みづけ
- 距離差異の重みづけ
- 合格スコアライン

他にもパラメータがあるので、それを自分の地図に合わせて調整することで正しく位置参照できる確率が上がります。


# まとめ
本記事では、OpenLRによる位置参照がどのような仕組みで成り立っているのか解説しました。この記事で言及したのはLine Locationの例かつ始点と終点の2点のみで構成されるものでした。中間点が含まれる場合も処理自体に大差はなく、参照する番号の位置をずらすだけで解決します。