HoloLens 2 × Pixel 3 / iPhone XS で Spectator View を試してみた ( Azure Spatial Anchors )

# はじめに
みなさん、こんにちは。神戸デジタル・ラボの堀尾 (@Futo_Horio）です。
今回は、先月神戸にて開催した Kobe HoloLens Meetup! val.2 内のセッション 「 __HoloLens 2 × Pixel 3 / iPhone XS で Spectator View を試してみた ( Azure Spatial Anchors )__ 」 について、Unityプロジェクト設定手順、検証時に詰まったポイント等についてご紹介したいと思います。個人的に、サンプルプロジェクトを実機デプロイ、動作検証を行うまでに __丸2日程度ハマった__ ので、エラーが発生した際のトラブルシューティングも交えながら、書き進めたいと思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/344939d3-dae0-7d81-f996-6e401675a714.png" width="600">

- [Kobe HoloLens Meetup! val.2](https://arkobe.connpass.com/event/160284/) ( Connpass )

# なぜ Spectator View を試したかったのか..
HoloLens 2 が届いて数多くの方にデモを体験してもらったのですが、周りで見ている人たちは何をやっているのか？さっぱり分からない状況でした。せっかく凄いAR体験をしているのに、その凄さや驚きをリアルタイムに周りの聴衆と共有できないという点に非常に大きな課題を感じていました。Miracast や MRC (Mixed Reality Capture) を使ってユーザー視点 (一人称) をリアルタイムで共有することはできますが、傍観者が能動的なAR体験ができていない。この状況を打破するために、Spectator View for Mobile を試してみることにしました。今までも一眼レフカメラを使えば Spectator View を実現できていましたが、必要な機材を準備するのにコストがかかり、実現することができていませんでした。これが Spectator View for Mobile を使えば、手持ちの端末で気軽にAR体験を共有できると分かり、試してみようと思ったのが今回の取り組みのキッカケです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/92c09872-4f69-4bd4-71bb-f76a7b8e0880.png" width="700"> 

出典 : [Spectator View for HoloLens and HoloLens 2](https://docs.microsoft.com/ja-jp/windows/mixed-reality/spectator-view)

上図のようなイメージで、手軽に複数人でAR体験を共有することができるプロダクトが __「Spectator View」__ です。

# What's Spectator View for Mobile !?
__Spectator View は、HoloLens を通じて実現される AR ( 拡張現実 ) 体験をその他のデバイス ( HoloLens, Android, iOS ) に共有するプロダクトです。__ Spectator View を利用すれば、HoloLens ( User ) から モバイル端末 ( Spectator ) に対して <font color="red">__Unidirectional ( 単一方向 ) へのコンテンツ同期__</font> を実現することが可能です。SpectatorView システムには、以下2つの役割が存在します。


| SpectatorView システム上の役割 | 対応デバイス |
| --- | --- |
| コンテンツ配信元 (User) | HoloLens のみ (1st gen含む) |
| コンテンツ配信先 (Spectator) | HoloLens, Android, iOS | 
   

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/35f2290b-414f-c652-85de-00bd7c8dc1b0.png" width="800">

# Spectator View : コンテンツ共有のアーキテクチャ
Spectator View は、HoloLens ( User ) と モバイル ( Spectator ) 間で、ソケット通信 ( TCP ) を行い、各プラットフォーム上で取得した空間情報を共有後、モバイル側のカメラ位置を調整し、HoloLens から モバイル に向かってコンテンツ更新情報 (オブジェクト位置、ポインター位置 etc.. ) を送り続けることで実現されています。

__【 アプリケーションの動作フロー 】__

0. HoloLens 側でアプリケーションを起動し、特定のポートをリッスン状態としておく。
1. モバイル端末でローカルアプリケーションの起点となる空間座標のトラッキングを開始する (ARkit, ARCore)
2. モバイル端末から HoloLens に対して、ソケット通信を行います。
3. モバイル端末と HoloLens のローカルアプリケーションの起点となる空間座標を共有します。  
 ( <font color="red">__Spatial Alignment Strategy__</font> )
4. モバイル端末は 3. で取得した HoloLens の空間座標を元に、カメラ位置の変換を行います。
5. HoloLens 側からモバイル端末側にUnityシーンの更新情報を送信し、  
 これらの情報を元にモバイル端末上のコンテンツを更新します。

詳細は、「[__Application Flow__](https://github.com/microsoft/MixedReality-SpectatorView/blob/master/doc/SpectatorView.Architecture.md#application-flow)」 をご覧ください。

# <font color="black">Spatial Strategy Alignment</font>
HoloLens とモバイル端末で取得した空間位置座標を共有する仕組みは、「__Spatial Alignment Strategy__」 と呼ばれており、以下3種類の方法が存在します。
 
| No. | Spatial Alignment Starategy | 概要 |
| :--- | :--- | :--- |
| 1 | <font color="black">__Azure Spatial Anchors (ASA)__</font> | <font color="black">__ポイントクラウド ( Point Cloud ) から特徴点のみを抽出、アンカー ( ユニークID ) として登録、座標共有する方法__</font> |
| 2 | QR Code Detection | OSレベルのQRコード認識機能を使用し、座標共有する方法 |
| 3 | ArUco Marker Detection | OpenCVライブラリを使用したQRコード認識機能を使用し、座標共有を行う方法 | 

__各プラットフォームによってサポートされている Spatial Alignment Strategy が異なるので、
アプリケーションの使用条件、サポートする端末等を配慮した上、
Spatial Alignment Strategy を選択することをお勧めいたします。__ 


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/8e0b7fd2-3e3e-2473-18fc-e8f45cc689d9.png" width="500">


- [Spatial Alignment Strategy Dependencies](https://github.com/microsoft/MixedReality-SpectatorView/blob/master/doc/SpectatorView.Setup.md#spatial-alignment-strategy-dependencies)



# 検証環境
今回、SpectatorView の動作検証に使用した環境は以下の通りです。

- __Windows PC__ ( ``Windows 10 Pro / OSビルド : 1903`` )
 - Windows SDK ( ``10.0.18362.0`` )
 - Unity ( ``2018.4.3f1`` ) 
 - Visual Studio Community 2017 ( ``Version 15.9.8`` )

- __Mac__ ( ``macOS : Mojave / バージョン 10.14.6`` )
 - Xcode ( ``11.3.1`` ) 

- __HoloLens 2__ ( ``OSビルド : 10.0.18362.1005`` )
- __Pixel 3__ ( ``Android : 9.0 pie`` )
- __iPhonex XS__ ( ``iOS : 13.3`` )

※ Spectator View の動作環境 「Software & Hardware Requirements」は [公式ページ](https://github.com/microsoft/MixedReality-SpectatorView/blob/master/doc/SpectatorView.Setup.md#software--hardware-requirements) をご確認ください。


# 検証内容

__Microsoftが公開している MixedReality-SpectatorView リポジトリのサンプルプロジェクト (Build2019DEMO.unity) を3つのプラットフォーム(HoloLens, Android, iOS)で動作検証を行うこと。__こちらのリポジトリ自体、MITライセンスでの提供されているので、誰でも簡単にご自身の Unityプロジェクト に SpectatorView を実装することが可能です。( ※ARkitのMITライセンスではないソースコードが含まれるので、ご注意ください。)


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/81dae0d1-d923-072a-bbfa-0fbf79c85d17.png" width="800">

- [microsoft/MixedReality-SpectatorView](https://github.com/microsoft/MixedReality-SpectatorView) ( GitHub )

今回、動作検証に使用するサンプルプロジェクトは、examples/ 配下に格納されています。

__ちなみに、Unityのサンプルプロジェクトは以下の2種類となります。__

- __SpectatorView.Example.Unity__ ( Spatial Alignment Strategy : QR Code Detection )
- __Build2019DEMO.unity__ ( Spatial Alignment Strategy : Azure Spatial Anchors )

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/51485f58-175f-0d93-211d-1e0095e86463.png" width="600">

検証に使用する「Build2019DEMO.untiy」は、昨年の MWC ( HoloLens 2 の発表があったイベント ) にて HoloLens 2 のデモを担当された Julia さんが、Microsoft Build 2019 にて紹介されていたデモコンテンツになります。実際、シアトルに行ってリアルタイムでデモの様子を見ていたので、そのコンテンツが自分でも手軽に試せるとはテンションが上がりますね :sunglasses: !
 
# Spectator View セットアップ方法
それでは、早速 Spectator View のセットアップを行っていきたいと思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/4738175d-dc54-c07f-cabe-9727eb05c11b.png" width="800">

__「1.サンプルを検証する場合」__ 、__「2.既存プロジェクトに組み込む場合」__ で手順が異なります。( ※既存プロジェクトにSpectatorViewを組み込む場合には SpectatorViewリポジトリ をサブモジュール (``git submodule``) として管理する必要があります。) 

## 01. ソースコードの準備

今回は、サンプルプロジェクトをセットアップし、各プラットフォームにデプロイするだけなので、``git clone``してきます。

```cmd
$ git clone https://github.com/microsoft/MixedReality-SpectatorView
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/be07ddb2-7367-3ece-6a34-0b7d0619765f.png" width="600">


次に ``master`` ブランチ から 最新リリース版の ``release/1.1.0`` ブランチに切り替えます。

```cmd
$ cd MixedReality-SpectatorView
$ git fetch origin release/1.1.0    <----- release/1.1.0 ブランチをダウンロード
$ git checkout release/1.1.0        <----- release/1.1.0 ブランチをチェックアウト (ブランチ切り替え)
```

続いて、<font color="red">__管理者権限__</font>でコマンドプロンプトを開き、以下コマンドを実行します。

```cmd
$ tools\Scripts\SetupRepository.bat  
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/25de4587-d432-6403-2de4-cfbcfc1713d9.png" width="600">


バッチファイルを実行すると、SpectatorViewの動作に必要なライブラリ (MRTK, ARCore, Azure-Spatial-Anchors-Samples) がexternalディレクトリ配下にダウンロードされ、各Unityサンプルプロジェクトから参照できるようにシンボリックリンクを生成してくれます。 <font color="red">__※この際、ARkit-Unity-Plugin はダウンロードされないので、iOSで動作させる場合は手動でダウンロードする必要があります。__</font>

#### __[【 release/1.1.0 ブランチを使用する際の注意点 】](https://github.com/microsoft/MixedReality-SpectatorView/blob/master/doc/SpectatorView.Setup.md#software--hardware-requirements)__
> SpectatorView release/1.1.0 ブランチは ARFoundation ( ARCore と ARKit のラッパーライブラリ ) に対応しておらず、ARCore に限って言うと、ARCore v1.7.0 のみテストを行い、それ以外では動作テストを行っていないとの注意書きがあったので、検証される際はご自身の判断でお願い致します。
>
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/8f5dd67c-ba1e-7295-6758-d3401823c9ee.png)

## 02. Azure Spatial Anchors の Account ID, Primary Key の取得
「Build2019DEMO.unity」では、Spatial Alignment Strategy に Azure Spatial Anchors を使用するので、アカウントを用意します。Azure の ポータル画面にアクセスし、「Spatial Anchors Accounts」を選択します。 (下図のように「Spatial Anchors Accounts」が表示されていない場合は、グローバルメニューの検索バーから検索してみてください。)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/1aa62e40-8af3-9784-558d-13bde23143d5.png" width="600">

続いて、「Add」ボタンを押下し、アカウントを作成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/a05d05ec-1708-da5b-2333-fe91435945c2.png" width="600">

[Resource Name]、[Subscription]、[Resource group]、[Location] を入力し、「Next」ボタンを押下します。
(※Location ですが、現在は East US 2 [米国東部2] しか選択できないようです。) 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/82d76b4e-716a-a997-476f-7ee5bbc76861.png" width="600">

新規アカウントをデプロイするまで少し時間がかかります。
(下図、デプロイ中のポータル画面)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/7b6a6acc-1df6-fd76-b70a-8d14266e66df.png" width="600">

デプロイが完了すると、「Go to resource」ボタンが表示されるので、こちらのボタンを押下します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/2d7fc31e-b55e-efd1-e79e-987437f17433.png" width="600">

アカウントの作成が完了したので、__[Account ID]__ と __[Primary Key]__ をメモしておきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/3d9fab93-1e2f-d77f-7f23-2ecf0d69a5e0.png" width="600">

「Access Keys」ボタンを押下すると、__[Primary Key]__ を確認することができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/a29d1e52-fbb5-4b5a-07b8-275565eaf170.png" width="400">

__こちらでメモをした [Account ID] と [Primary Key] は、Unity の Inspector 上での手順で使用します。__


## 03. Unity プロジェクトのセットアップ ( HoloLens 2 )
ここからは Unity を起動し、各プラットフォームごとの設定を追加していきます。
各プラットフォームごとに少し設定方法が異なるので、注意してください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/74e11695-6f2b-9d91-d2a0-83b6d4dffd11.png" width="800">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/2e79992d-531b-3e18-00af-856e2b9f3c6e.png" width="800">

コンテンツの個別同期の方法は、「[__Performance Settings__](https://github.com/microsoft/MixedReality-SpectatorView/blob/master/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/StateSynchronization/README.md#performance-settings)」 をご覧ください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/9ad6045e-d86d-88a3-d11c-b6d5b52d0afd.png" width="800">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/e684adb4-7095-9033-6f3b-fcc6d6492e1c.png" width="800">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/58d6306f-4047-1c38-df77-3adc45f06cbf.png" width="800">

## 04. Unity プロジェクトのセットアップ ( Android )
Android 端末へのビルド方法は以下の通りとなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/8332971e-d510-6668-9629-44b48d35f44a.png" width="1200">

## 05. Unity プロジェクトのセットアップ ( iOS )
iOS 端末へのビルド方法は以下の通りとなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/7cfca4e9-05ad-0317-fefc-2ee7aa8820a9.png" width="1200">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/c511d525-e276-fac3-ab2b-44d47b31aab1.png" width="1200">

もし上記エラーが発生し、端末へデプロイができない際は、「[__Convert the Xcode project to xcworkspace containing Azure Spatial Anchors references__](https://docs.microsoft.com/en-us/azure/spatial-anchors/quickstarts/get-started-unity-ios#convert-the-xcode-project-to-xcworkspace-containing-azure-spatial-anchors-references)」 をご覧ください。詳しいトラブルシューティング方法が記載されております。

以上にて、各プラットフォームへのデプロイ作業は完了となります。


## 実際に動作させた際の様子 ( 動画 )
以下、実際にサンプルプロジェクトを動かしてみた動画です。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Spectator View for Mobile<br>HoloLens 2 × Pixel 3 で動かしてみた。<br><br>ずっと1人で検証していたので<br>やっぱり複数人で対話しながら<br>操作出来る体験は最高でした！<a href="https://twitter.com/hashtag/HoloLens2?src=hash&amp;ref_src=twsrc%5Etfw">#HoloLens2</a> <a href="https://twitter.com/hashtag/SpectatorView?src=hash&amp;ref_src=twsrc%5Etfw">#SpectatorView</a><a href="https://twitter.com/hashtag/MRTK?src=hash&amp;ref_src=twsrc%5Etfw">#MRTK</a> <a href="https://twitter.com/hashtag/ARCore?src=hash&amp;ref_src=twsrc%5Etfw">#ARCore</a> <br><br>(Special Thanks <a href="https://twitter.com/torisankanasan?ref_src=twsrc%5Etfw">@torisankanasan</a> ) <a href="https://t.co/YOCDBEZLFk">pic.twitter.com/YOCDBEZLFk</a></p>&mdash; Futo Horio (@Futo_Horio) <a href="https://twitter.com/Futo_Horio/status/1221729958776541185?ref_src=twsrc%5Etfw">January 27, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# SpactatorView ( Prefab ) について
Spectator View は、基本的には SpectatorView ( Prefab ) を追加することで実装することが可能です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/75cbdccf-59e6-7b82-2923-d16916248bfa.png" width="1200">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/a3896dd1-d89b-640e-9c73-42dc3604bd23.png" width="1200">



# SpectatorView パフォーマンスのモニタリング方法
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/1312bf18-37a5-2933-4afe-1756c21bf82f.png" width="1200">

パフォーマンスモニタリングの詳細手順は、「[__Performance Monitoring__](https://github.com/microsoft/MixedReality-SpectatorView/blob/master/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/StateSynchronization/README.md#performance-monitoring)」 をご覧ください。

# その他トラブルシューティング ( まとめ )
私が検証をする際に、ハマった点をいくつかご紹介いたします。

## 既存プロジェクトへの組み込み時の注意点

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/35caa8a6-d6f4-6cb1-0371-1879843daffb.png" width="1200">

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/cf05aa7a-fc8d-a9e9-5fa9-e23ad5244b18.png)


- [issue: MRTK v2.2.0 seems to generate issues for WINDOWS_UWP macros in custom code](https://github.com/microsoft/MixedRealityToolkit-Unity/issues/7106)


## QR Code Detection ( HoloLens 2 ) を使う際の注意点

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/558a5f7a-1682-6a5b-e83e-8749a4e4ba88.png)


##

# まとめ
以下、箇条書きで思ったことをまとめました。

__1. Spectator View for Mobile は 低コスト でコンテンツ同期が可能なので良い！__
　__( ただしすべてのコンテンツで有効とは限らない )__
__2. User ( コンテンツ配信元 ) として使えるデバイスは HoloLens のみ__
__3. Spectator ( コンテンツ配信先 ) はコンテンツの操作は行えない ( 単一方向への同期 )__
__4. SpectatorView のサンプルで使用されている MRTKブランチは__
　__mrtk_development ブランチ ( ※ MRTK v2.2.0 と組み合わせる際はバグで詰まる可能性大 )__
__5. iOSへの実機デプロイには CocoaPods というiOS/Mac向けのライブラリ管理ツールのインストールが必要__
__6. エラーが出た際は、Google より HoloDevelopers (グローバルMRコミュニティSlack) で検索がお勧め！__
__7. モバイル端末側を先に起動すると、コネクション接続に失敗するので HoloLens 側を先に立ち上げる__
__8. Azure Spatial Anchors を使用して空間位置合わせを実施するとズレる場合があるので、何回か試してみるべし__

実は、先週末大阪で開催された「HoloLens 2 ハッカソン」でも、[蜜葉さん](https://twitter.com/mitsuba_yu) のハッカソンプロジェクトに Spectator View を適用してみました。（ 下図、HoloLens上で見たアプリケーション動作イメージ ）

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">時代は「追いプロジェクション」 <a href="https://twitter.com/hashtag/Hololens2?src=hash&amp;ref_src=twsrc%5Etfw">#Hololens2</a> <a href="https://twitter.com/hashtag/holohack?src=hash&amp;ref_src=twsrc%5Etfw">#holohack</a> <a href="https://t.co/zyobAv3WeA">pic.twitter.com/zyobAv3WeA</a></p>&mdash; 蜜葉 (@mitsuba_yu) <a href="https://twitter.com/mitsuba_yu/status/1226093952224227328?ref_src=twsrc%5Etfw">February 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

- [SpectorViewは魔法でもなければ、銀の弾丸でもなかった。](https://c-mitsuba.hatenablog.com/entry/2020/02/12/003859)

__結論から言うと、こういったシナリオの場合、Spectator View を活用することで UX が向上することは見込まれませんでした。__ですが、個人的に Spectator View ( Build2019DEMO.unity ) を体験した時に、凄い感動したという思いがあるので、このUXの違いは何が要因なのだろうと、ハッカソンから帰ってきてから、自分の検証した「Build2019DEMO.unity」との違いを考えていたのですが、そこで僕が出した答え<font color="red">__「Spectator View が有効に機能するシナリオの必要条件」__</font>は、以下3つです。

- __表示するCGとユーザーの距離が近いこと (1~2m範囲内)__
- __表示するCGがモバイル端末側で周り込める程度の大きさであること__
- __HoloLens 側での操作によって、コンテンツがインタラクティブに動作すること__

この3つの条件が揃わなければ、Spectator View で UX を向上させることはできないのではないかと推測しています。とは言え、個人的に Spectator View は素晴らしい機能だと思うので、今後も有効なシナリオでUXを向上させるために使用できればと思います。長い記事となりましたが、最後までお読みいただき、ありがとうございました。

# 参考文献 ..
- [SpectatorView](https://docs.microsoft.com/ja-jp/windows/mixed-reality/spectator-view) ( GitHub )
- [SpeackerDeck](https://speakerdeck.com/futo23/kobe-hololens-meetup-val-dot-2-hololens-2-guan-xi-shang-lu-ji-nian-mian-qiang-hui) ( 登壇資料 )
- [Medium](https://medium.com/@kdlhorio/hololens-2-pixel-3-iphone-xs-%E3%81%A7-spectator-view-%E3%82%92%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F-6e31e777de6e) ( Medium 記事 )