ARKitはどうやって自己位置推定と環境マッピングを行なっているのか

さあ始まりました。ARKitアドベントカレンダー2018！

トップバッターの私は今回、「**ARKitはどうやって自己位置推定と環境マッピングを行なっているのか**」についてまとめたいと思います。

## ARを支える技術

![image](https://cdn.uploadvr.com/wp-content/uploads/2016/11/SLAM-data.png)

ARというテクノロジーは、

- **カメラから取得した画像を元に平面や物体を認識して空間を作成する**
- **撮影しているカメラの位置がその空間内でどこにいるか把握する**

大きくこの２つのテクノロジーで成り立っています。

それぞれ、

- **周囲環境マッピング(環境地図作成)**
- **自己位置推定**

と呼ばれることが多いです。

この前提の元、**ARKitはどうやって自己位置推定と環境マッピングを行なっているのか**を理解しましょう。

## ARKitはどうやって自己位置推定と環境マッピングを行なっているのか

ARKitの公式ドキュメントには以下のように書かれています。

>To create a correspondence between real and virtual spaces, ARKit uses a technique called visual-inertial odometry. This process combines information from the iOS device’s motion sensing hardware with computer vision analysis of the scene visible to the device’s camera. 
https://developer.apple.com/documentation/arkit/understanding_world_tracking_in_arkit

*ARKitはVIO(visual-inertial odometry)と呼ばれるテクノロジーを使っています。この技術は、iOSデバイスのモーションセンサー情報と、カメラから得られる画像からの画像認識の結果を組み合わせて成り立っています。* 

と書いてあります。

つまり、**ARKitはカメラ画像だけではなくiPhoneの加速度センサやジャイロセンサを用いた自己位置推定も行なっている**ということです。

ARKitが内部のセンサを使って自己位置推定を行なっていることは実験してみるとわかります。

一度ARKitのsessionを起動して辺りを見回した後に、カメラを一旦隠してデバイスを移動させてもARKitは現在地を覚えているので復活が可能です。

しかし内部センサだけで自己位置推定を行なっている訳ではなく、一度置いたオブジェクトを正しく表示するためにはもう一度しっかりカメラを使って辺りを見回す必要があります。このバランス感は開発しているAppleのみぞしるテクノロジーなところでしょう。

<img width="1028" alt="スクリーンショット 2018-12-01 14.45.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/67eb11c7-f7a3-a40a-5f8e-1ea2e2070fc0.png">

[ARrrrrgh](https://itunes.apple.com/jp/app/id1299548311)というARKitを使ったアプリ宝探しアプリが、この辺をうまく使っています。同じデバイスを使って、一人が宝を地面に埋めて、一旦カメラを隠した後(ARKitのsessionは止めないまま)、再びカメラを表示して宝探しをすることができます。

しかし問題もあります。電車だと加速度センサが反応しちゃってうまく認識できないことです。


<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">走ってる電車でARは難しいという学びがあった。 <a href="https://twitter.com/hashtag/ARKit?src=hash&amp;ref_src=twsrc%5Etfw">#ARKit</a> <a href="https://t.co/U3qURVN8gZ">pic.twitter.com/U3qURVN8gZ</a></p>&mdash; sakusan393 (@sakusan393) <a href="https://twitter.com/sakusan393/status/910665775458873345?ref_src=twsrc%5Etfw">2017年9月21日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


ということで、デメリットはありつつも**ARKitはカメラ情報と内部センサ情報をいい感じに使ってARを実現していること**が理解できたでしょうか？

## SLAMとVIO

前述の通り、AppleはARKitは**VIO(Visual Inertial Odometry)**というテクノロジーを使ってARを実現しているとしています。

しかし似たようなAR技術にSLAMというものがあり、むしろこちらの方が有名です。(記事も多い)

ということで、**ARKitはSLAMを使っている訳ではないのか？そもそもSLAMとVIOって何が違うの？**というところを整理して今記事を締めくくりたいと思います。

### SLAMとは

SLAM（Simultaneous Localization and Mapping）はカメラで撮影された映像から環境の3次元情報とカメラの位置姿勢を同時に推定する技術です。

![kudan](http://www.arreverie.com/blogs/wp-content/uploads/2017/05/kudan-arreverie.jpg)

モバイルでSLAM技術を使ってARを実現しているのが[Kudan](https://www.xlsoft.com/jp/products/kudan/kudan.html
)です。最近東証マザーズ上場しました。

### VIOとは

Appleは、ARKitに**VIO(Visual Inertial Odometry)**を使っているとドキュメントで述べています。

ちなみに、「**Visual Inertial Odometry**」でググってみると、「**Visual Odometry**」に関する記事や論文が多く引っかかります。真ん中に**Inertial**があるかないかの違いですが、位置づけとしては「**Visual Odometryの中にVisual Inertial Odometryが含まれている**」です。

英語ですが、[wikipedia](https://en.wikipedia.org/wiki/Visual_odometry#Visual_Inertial_Odometry)の記事はわかりやすいです。

- VOはカメラ画像から位置と角度を決定する処理
- VIOはその中でも**IMU(Inertial measurement unit)** (3軸のジャイロと3方向の加速度を計測する装置)を使って画像だけよりも更に強力な自己位置推定を行う処理

と説明されていて、先に紹介したAppleのドキュメントが「**iOSデバイスのジャイロと加速度センサを使っている**」という話と一致します。

### SLAMとVOの違い

SLAMとVIOを直接比較することはできません。SLAMに対してIMUを組み合わせる手法もあるためです。そのためIMUを除いたSLAMとVOの比較をしたいと思います。

[ARの教科書](https://amzn.to/2FH38OF)で読んだ内容では、VOはSLAMの前身で、時系列としてはVOが先に生まれて、そのあとにSLAMが生まれたという関係性になります。

また、RMIT大学の研究者のKhalid Yousifさんの記事 [An Overview to Visual Odometry and Visual SLAM: Applications to Mobile Robotics](https://link.springer.com/article/10.1007/s40903-015-0032-7)がわかりやすかったので紹介します。

下図の(a)がVOで、(b)がSLAMです。SLAMの方が何度も補正が入ることがわかります。

![slamvio](https://media.springernature.com/lw785/springer-static/image/art%3A10.1007%2Fs40903-015-0032-7/MediaObjects/40903_2015_32_Fig1_HTML.gif)

>The main difference between **VO** and **SLAM** is that **VO** mainly focuses on local consistency and aims to incrementally estimate the path of the camera/robot pose after pose, and possibly performing local optimization. Whereas **SLAM** aims to obtain a globally consistent estimate of the camera/robot trajectory and map. Global consistency is achieved by realizing that a previously mapped area has been re-visited (loop closure) and this information is used to reduce the drift in the estimates.
https://link.springer.com/article/10.1007/s40903-015-0032-7#Sec1

上記の文章は、**VOはローカル最適化、SLAMはグローバル最適化に焦点を当てている**と要約することができます。つまり、SLAMの方がより広い範囲を認識してARすることができる点で優れている一方、計算量が多いという欠点があります。

>Its advantage over standard (global) bundle adjustment is a great reduction of computational complexity, which allows real-time performances with a similar accuracy.
https://ieeexplore.ieee.org/document/5206824

「ローカル最適化はグローバル最適化に比べて計算の複雑性を排除している点で優れていて、同じような正確性でリアルタイムで高いパフォーマンスを出すことができる」と述べている論文もあります。

### なぜARKitはVOなのか

ここからは僕の考察です。

なぜARKitがSLAMではなくVOを使っているかと言えば、SLAMの計算処理は重くてモバイルのARに対してはオーバースペックだったからだと予想されます。

現にARKitを長い時間使うとデバイスが熱くなってフレームレートが落ちるように制限されてしまいますが、デバイス制約がある中で、iPhoneやiPadのセンサを生かしつつ、より少ない計算量で空間認識することができるVIOを選択したのだと考えられます。

## まとめ
- ARKitはジャイロセンサや加速度センサとカメラ画像を使ってARを実現している
- ARKitの使うその技術はVIO(Visual Inertial Odometry)と呼ばれている。
- VIO(Visual Inertial Odometry)はVO(Visual Odometry)の種類の１つ
- SLAMは広範囲最適化されるが計算量が多い、VOは狭範囲最適化しかされないが計算量が少ない
- KudanはSLAM, ARKitはVO