HoloLens2×WebRTC×Raspberry Pi Zero Wを使ってRaspberry Pi Zero Wでのカメラ映像をHoloLens2に表示する

# 概要

WebRTCを使ってRaspberry Pi Zero Wからのカメラ映像をHoloLens2に投影することにより、別の視点からの状況を同時に見れたりすることが出来たりする。今回記事にしたのは環境構築に非常に手間取ったためである。
結論としては、dllをビルドした時の対象アーキテクチャを合わせてあげる必要があった。
使ったハードと技術並べてタイトルにしただけなのになろう系みたいな長文タイトルになってしまった。


# はじめに

HoloLens2の背面にカメラを載せて、車のバックモニターみたいな機構を作れないか調べてたらWebRTCと呼ばれる技術が使えそうだということで、実際に簡単なプロジェクトを作ってみることにした。


# 環境構築

以下の環境、ライブラリを使用した。

* Windows 10 Home
* Unity 2019.4.13f1
* Visual Studio 2019
* Raspbian GNU/Linux 10
* Microsoft Mixed Reality Toolkit 2.5.0
* MixedReality-WebRTC 2.0.0-preview.1
* MixedReality-WebRTC Samples 2.0.0-preview.1
* MixedReality-WebRTC-ayame
* WebRTC シグナリングサービス Ayame Lite
* WebRTC Native Client Momo
* Newtonsoft.Json 12.0.3
* SuperSocket.ClientEngine
* WebSocket4Net v0.15


# プロジェクト作成

## Raspberry Pi Zero W編
1. OSはデフォルトのRaspberry Pi OSを使用。[スイッチサイエンス社](https://www.switch-science.com/catalog/3561/)からOSがプリインストールされているキットが販売されていたため、OSのインストールは割愛する。
2. WebRTCクライアントの[WebRTC Native Client Momo](https://github.com/shiguredo/momo)を配置する。Raspberry Pi Zero W用のバイナリが提供されているのでそれをダウンロードする。
3. 実行方法は[SETUP_RASPBERRY_PI.md](https://github.com/shiguredo/momo/blob/develop/doc/SETUP_RASPBERRY_PI.md)を参照。
シグナリングキーとルームIDはHoloLens2側と合わせること。

## HoloLens2編

### ビルドサポート追加

HoloLens2はUWP環境らしいので以下のようにUWPのビルドサポートを追加する。
![28afba3da4a3f6b36c1db373f7cbbbec.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104310/ed6625f5-0bff-2785-d6fb-0c5fa8492389.png)


### ライブラリ追加

#### [MixedReality-WebRTC](https://github.com/microsoft/MixedReality-WebRTC)
プロジェクトフォルダ/Packages/manifest.jsonファイルに以下のように追記をする。

```json
  "scopedRegistries": [
    {
      "name": "Microsoft Mixed Reality",
      "url": "https://pkgs.dev.azure.com/aipmr/MixedReality-Unity-Packages/_packaging/Unity-packages/npm/registry/",
      "scopes": [
        "com.microsoft.mixedreality"
      ]
    }
  ],
  "dependencies": {
    "com.microsoft.mixedreality.webrtc": "2.0.0-preview.1",
    "com.microsoft.mixedreality.webrtc.samples": "2.0.0-preview.1",
```
ライブラリがインポートされるとWindowタブ > Package Managerに追加される。
![d97b8859613242f2179b95fc7d5d0c7b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104310/b6e0ed43-36a8-8694-3ea3-64d1fd28cb5d.png)


#### [MixedReality-WebRTC-ayame](https://github.com/tarukosu/MixedReality-WebRTC-ayame)
[GithubのReleases](https://github.com/tarukosu/MixedReality-WebRTC-ayame/releases)からMixedReality-WebRTC-ayama-x.x.x.unitypackageをダウンロードし、インポートする。
README.mdにはWebSocket4Net、SuperSocket.ClientEngine、Newtonsoft.Jsonのdllをインポートすると書いてあるので、それらもインポートする。

#### [WebSocket4Net](https://github.com/kerryjiang/WebSocket4Net)
v0.15ブランチを使用する。
WebSocket4Net.slnを開き、ビルドタブからWebSocket4Net.Net45のビルドを選択しdllファイルを作成する。作成されたWebSocket4Net.dllをプロジェクト内に配置してInspectorからPlatform settingsでUWPでの設定を変更する。
![71be80959f39031b89e92200db311adc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104310/50978a0e-0dd7-6c05-becf-f9b86042eaec.png)
SDKをUWPに、ScriptingBackendをIl2Cppに変更している。


#### [SuperSocket.ClientEngine](https://github.com/kerryjiang/SuperSocket.ClientEngine)
WebSocket4Netのビルド時にWebSocket4Net.dllと同じディレクトリにSuperSocket.ClientEngine.dllが作成されているので、それをWebSocket4Net.dllと同じようにプロジェクト内に配置してInspectorからPlatform settingsでUWPでの設定を変更する。

#### [Newtonsoft.Json](https://www.newtonsoft.com/json)
[Newtonsoft.Json](https://www.newtonsoft.com/json)のサイトからビルド済みのものをダウンロードできる。
netstandard2.0ディレクトリ内にあるNewtonsoft.Json.dllファイルを同様に、プロジェクト内に配置してInspectorからPlatform settingsでUWPでの設定を変更する。

#### [Microsoft Mixed Reality Toolkit](https://github.com/microsoft/MixedRealityToolkit-Unity)
[GithubのReleases](https://github.com/microsoft/MixedRealityToolkit-Unity/releases)からMicrosoft.MixedReality.Toolkit.Unity.Foundation.x.x.x.unitypackageをダウンロードし、インポートする。

### シーン作成

MixedReality-WebRTC-ayameにシグナリングサーバーに[ayame](https://github.com/OpenAyame/ayame)を用いたサンプルシーンがあるのでそれを流用する。今回はRaspberry Pi Zero WからHoloLens2に一方的に映像を送るのでHoloLens2から送る処理は取り除く。
AyameSignalerのシグナリングキーなども設定する。この時、Raspberry Pi Zero Wと同じシグナリングキーとルームIDを設定する。

後々使うかもしれないのでMicrosoft Mixed Reality Toolkitもシーンに追加する。
Mixed Reality ToolkitタブからAdd to Scene and Configure...を選択してオブジェクトを追加する。

### ビルド

Build SettingsとPlayer Settingsを設定しビルドを行う。
![131fefc23a8b1a292a1f0b86707b2d30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104310/261288bc-ed6a-2daa-1424-e8690b6afba1.png)
![38eae218e728d335c29e82f3ad090be0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104310/8e4a2781-ff72-7d1a-d913-8bbedc567a36.png)


### 実機確認

https://youtu.be/g7vfVKh0KTQ

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="und" dir="ltr"><a href="https://t.co/SVcvROjEaE">pic.twitter.com/SVcvROjEaE</a></p>&mdash; 夏野すぐる (μ兵装) (@fuyunosuguru) <a href="https://twitter.com/fuyunosuguru/status/1323938799697604609?ref_src=twsrc%5Etfw">November 4, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>