World Locking Tools for Unityの安定した空間をAzure Spatial Anchorsを利用してクロスプラットフォームで共有する

# Overview

広い空間でオブジェクトの位置をできるだけ正確に配置するためのライブラリ「World Locking Tools for Unity」とクロスプラットフォームでアンカーを共有できる「Azure Spatial Anchors」を組合わせたサンプルの動作確認とその解説。

## この記事に記載している事

この記事では以下の事を簡単に整理しています。HoloLensをはじめMixed RealityやAugmented Realityに関するデバイスでの現実空間とデジタルオブジェクト位置関係に関する課題を解決するいくつかのアプローチの1つです。

* World Locking Toolsの概要
* Azure Spatial Anchorsの概要
* なぜWorld Locking Toolsが必要でAzure Spatial Anchorsと組合わせると嬉しいのか

そして内容の理解を深めるためにも実際に動かしたい人への情報提供として、提供されているサンプルのデプロイ手順を紹介します。

* World Locking Tools for UnityとAzure Spatial Anchorsを活用したサンプルを動かすための手順

これにより体験できるととしては、あらかじめ現実空間に正確に位置合わせされたオブジェクトをクロスプラットフォーム下で可視化することができます。サンプルでは以下の体験が可能です。

1. デジタルで描画されたソファを現実空間の任意の位置に設置します。<BR>この際に現実空間と位置合わせをWorld Locking Toolsにより実現しています。
1. World Locking Toolsが設定した現実空間とデジタル空間の位置合わせに関する情報をクロスプラットフォームで共有します。<RB>デバイス間でこの情報を共有するためにAzure Spatial Anchorsを活用します。

## 開発環境と必要なソフトウェア

開発環境として利用したものは以下の通りです。

* Unity 2020.3.8f1
* Visual Studio 2019
* Mixed Reality Feature Tools

ハードウェアについては以下での動作を確認しています。一応iOSも動くはずなのですがサンプルではうまく動かなかったです(調査中)

* HoloLens 2
* XRSDK(AR Foundation)をサポートするAndriodスマートフォン

また、利用するライブラリについては以下になります。

* World Locking Tools for Unity V1.5.7
 * World Locking Tools Core
 * World Locking Tools Tools
 * World Locking Tools Azure Spatial Anchors Module
 * World Locking Tools Samples
 * World Locking Tools Azure Spatial Anchors Samples 
* Mixed Reality Toolkit V2.7.2
* Mixed Reality OpenXR Plugin V1.2.1
* Azure Spatial Anchors SDK for Core
* Azure Spatial Anchors SDK for Windows
* Azure Spatial Anchors SDK for Andriod
* Nuget for Unity v3.0.3
* Microsoft.MixedReality.Unity.FrozenWorld.Engine V1.1.1

## World Locking Toolsの概要

HoloLens 2をはじめ最近のARデバイスはセンサーやデバイスの性能向上もあり非常に高精度に現実空間にデジタルの情報を配置することが可能なりました。これらのデバイスはスタンドアロンデバイスで実現されていることが多く、空間認識はインサイドアウト方式を呼ばれるスタンドアロンデバイスに搭載されたセンサーを活用して行われます。このような方式では外部センサーを要しないため、比較的歩き回るコンテンツの作成が可能です。一方で、センサーの有効範囲内では精度が確保できても、より広い空間でデジタルコンテンツを表示することは苦手です。例えば、10m離れた地点にデジタルコンテンツを表示することを考えてみます。実際に10m先にある物体のところまで歩いて行って鑑賞する場合、インサイドアウト方式では移動時の誤差などが含まれて厳密には10mからずれた地点で描画されることがあります。また、そこから元の地点に戻ると今度はその移動によっても誤差を生じさらに物体の位置関係が崩れることになります。これはドリフトと呼ばれる現象です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/91f4048b-af2e-4f9e-5df5-163caa002ec4.png)

通常このような位置ずれを解消する手段として「world Anchor」といった手段を利用することがあります。広い空間を利用する際に、現実空間の特徴を利用してデジタル上の位置関係を調整するためのAnchorを呼ばれる特殊なオブジェクトを一定間隔で配置することでセンサーの精度範囲内にデジタル上の位置情報を補正する目印を設置するというものです。
ただし、World Anchorの仕組みにも問題がいくつかあります。

* 空間が広い場合、複数のAnchor設置が必要で、その管理が大変
* 物理演算処理が難しくなる。

1点目は広い現実空間内で安定してデジタル情報を管理するためには多くのAnchorの設置が必要になるということです。さらにそのアンカーとデバイス装着者の位置関係に応じて、デジタルコンテンツの位置関係を補正する等非常に細やかな制御が必要になります。
2点目は1点目の影響をうけるものです。たとえな物理演算(Rigidbody等)を利用しようとしてもWorld Anchorの場合、RigidBodyのような物理演算を利用する動的なオブジェクトをコンテンツ内に含めることが難しくなります。
こういった課題を解決するための手段として提供されているものがWorld Locking Toolsです。

### 基本的な考え方と用語

World Locking ToolsはWorld Anchorを利用した現実空間とデジタルコンテンツの座標調整における課題を解消することができます。World Locking Toolsはその空間情報の取扱いにおいて「spongy space」と「World locked space」と呼ばれる2つの空間概念があります。
この2つの概念の中でデジタルコンテンツの扱いを変えることで動的なコンテンツでも現実空間と空間的に位置があった物体を扱うことが可能になります。

#### spongy space
流動的な空間情報を表した用語です。HoloLens等のデバイスは搭載されたセンサーで認識している空間情報とヘッドトラッキング情報を利用します。センサーはリアルタイムで現実空間を分析してデジタルの座標系を構築します。この空間では装着者が動き回ながら、その周辺をトラッキングし常に自己位置と周辺空間の情報を動的に把握しています。こういった流動的に空間情報が変わる領域を「spongy space」と呼びます。
この用語で表現される空間は従来私たちがMRやARコンテンツとして取り扱っているセンサーの精度が十分有効な範囲の座標系です。

#### World locked space
現実空間に対して安定した空間を表した用語です。先ほどのSpongy spaceではヘッドトラッキング情報とその周辺の空間情報をセンサーで認識していますが、これらの情報を利用して現実空間に最適に整合された空間を計算します。このような計算によって構成された「spongy space」よりも広い空間を「World locked space」と定義しています。

#### 「spongy space」と「World locked space」
World Locking Toolsが空間内でデジタルコンテンツの位置関係を表現するために「spongy space」と「World locked space」でデジタルコンテンツの扱いを変えています。これは非常にシンプルですが有効な手段といえます。いわゆる遠くにあるものほど動かさないという考え方です。
先ほどの「spongy space」は流動的な空間情報でヘッドトラッキング情報により空間内移動が発生しコンテンツは動的です。常に情報が流動的になっています。このための現実空間とデジタル空間の座標系を最適化するためのAnchor等の位置関係を調整して補正を行います。一方、「spongy space」よりも遠くにあるコンテンツに対しては「World locked space」で構築された安定した空間の中に固定されます。アンカーに合わせた位置調整を伴わないため空間上に固定されたかのような振る舞いになります。こういった挙動をライブラリ内で制御することでより広い空間でも安定した座標系を持つことが可能になります。

### World Locking Toolsの機能

このようにより広い空間での位置合わせを容易にするライブラリとして以下のような機能が提供されています。詳細はWorld Locking Toolsのドキュメントも併せて参照してください。

https://microsoft.github.io/MixedReality-WorldLockingTools-Unity/DocGen/Documentation/GettingStartedWithWorldLocking.html

* World locked spaceの構築<BR>先に説明したspongy spaceの情報を利用して現実空間に最適化された安定したデジタル空間(座標系)を構築します。
* 永続化<BR>一度構築したWorld locked spaceは永続化が可能です。ライブラリでは自動ロード/セーブやマージといった機能が提供されており、一度構築した情報は同一デバイス内で復元可能です。
* Space Pin/Ray Pin<BR>現実空間にデジタルオブジェクトを固定するために利用でき仕組みです。アンカーとは異なり、デジタル空間での座標系と現実空間の位置関係を合わせるために利用するため、Space Pinを基準にUnityの空間全体が移動します。



## Azure Spatial Anchorsの概要

World Locking Toolsは現実空間とデジタル空間の位置調整を面で実施する機能に対してAzure Spatial Anchorsは現実空間とデジタル空間の位置関係を点で合わせる機能といえます。Azure Spatial Anchorsはその名前が示す通りAnchorをクラウド上で管理するサービスです。そしてそれらを複数のデバイス間で共有することが可能になります。空間の特徴と共にアンカーの情報をクラウドで管理します。必要な時にクラウドからアンカー情報を取得し、現実空間に配置することで、異なるデバイス間でも同じ空間の同じ地点にアンカーを設置することができるようになります。これによって同一の現実空間で共有型コンテンツを作成可能になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/ee1da80d-f300-e0ab-f9c2-6e27fa85166f.png)

Azure Spatial Anchorsについては以前整理した記事がありますのでそちらも作業してください。

https://qiita.com/miyaura/items/2fff0f9fb037efb384d4

https://qiita.com/miyaura/items/f220b87d1df59c1a9ce6

## なぜWorld Locking Toolsが必要でAzure Spatial Anchorsと組合わせると嬉しいのか

「**クロスプラットフォームで共有できるから**」

World Locking Toolsは広い空間でもデジタルコンテンツの位置関係が破綻しない非常に強力なライブラリなのですが、同一デバイス内での利用が基本になります。この情報をAzure Spatial Anchorsを利用して、Hololens同士、もしくはAndriod,iOSといったほかのデバイス間でも共有しようというのが組合わせるメリットになります。
具体的にはWorld Locking ToolsのSpace pinをAzure Spatial Anchorsを利用してアンカーとしてクラウドに管理します。共有したいデバイス間でこの情報を共有し、World Lock spaceをデバイス間で共有します。また、アンカーの取得にはCoarse Relocationという、Bluetoothビーコンや、Wifi、GPSといったセンサー情報を周辺のSpatial Anchorを検索/取得する仕組みを利用します。

## World Locking Tools for UnityとAzure Spatial Anchorsを活用したサンプルを動かすための手順

サンプルは以下のようになります。

なお、手順は公式のドキュメントも用意されています。ドキュメントにはMixed Reality Feature toolを利用してセットアップできるという話になっているのですが、実際にやってみるとセットアップがうまくいかず[World Locking Toolsのgithub](https://github.com/microsoft/MixedReality-WorldLockingTools-Unity/releases/tag/v1.5.7)に公開されているunitypackageを利用します。

https://microsoft.github.io/MixedReality-WorldLockingTools-Unity/DocGen/Documentation/HowTos/Samples/WLT_ASA_Sample.html

https://microsoft.github.io/MixedReality-WorldLockingTools-Unity/DocGen/Documentation/HowTos/WLT_ASA.html

サンプル動作までの手順

1. unitypackageのダウンロード
1. Azure Spatial Anchorsのサービス登録
1. プロジェクトの作成とMixed Reality Toolkitの導入とセットアップ
1. World Locking Toolsとサンプルの導入
1. HoloLensへのデプロイ

Androidもサポートしているので上記環境で作ったものをAndroidで展開します。ただ現時点ではiOSがうまく動作していないです（詳細は不明）。サンプル自体はデプロイできますが、アプリ内の初期設定がうまくいっていないようです。
これらのモバイルデバイスについても手順は記載しておきます。
基本的には上記の公式ドキュメントでも公開されていますので何か手順で不明瞭な場合は確認してみてください(英語ですが)

### サンプル動作手順

ではHoloLens 2にデプロイしてみましょう。上記の通りMixed Reality Feature Toolですべて設定できないので一部はunityPackagesを利用します。

#### 1.unitypackageのダウンロード

以下のunitypackageをダウンロードします。

* [World Locking Tools for Unity V1.5.7](https://github.com/microsoft/MixedReality-WorldLockingTools-Unity/releases/tag/v1.5.7)
 * Microsoft.WorldLockingTools.Unity.ASA_wExamples.unitypackage
 * Microsoft.WorldLockingTools.Unity.CoreEngine.unitypackage
 * Microsoft.WorldLockingTools.Unity.Examples_wMRTKv2.7.2.unitypackage
 * Microsoft.WorldLockingTools.Unity.Tools.unitypackage
* [Nuget for Unity v3.0.3](https://github.com/GlitchEnzo/NuGetForUnity/releases/tag/v3.0.3)

#### 2.Azure Spatial Anchorsのサービス登録

[(MS公式ドキュメント)クイック スタート:Azure Spatial Anchors を使用する Unity HoloLens アプリを作成する - Spatial Anchors リソースを作成する](https://docs.microsoft.com/ja-jp/azure/spatial-anchors/quickstarts/get-started-unity-hololens?tabs=azure-portal#create-a-spatial-anchors-resource)を参考にAzure Spatial Anchorsのサービスを登録します。
登録後は以下の情報を控えておいてください。

* アカウントID
* アカウントドメイン
* アクセスキー

#### 3.プロジェクトの作成とMixed Reality Toolkitの導入とセットアップ

まずはMixed Reality Feature Toolを利用してMRTKとAzure Spatial Anchorsのライブラリをセットアップします。
Unityプロジェクトを作成し、作成後ビルド設定をHoloLens用に変更しておきます。

1. 最初に任意の場所にUnityプロジェクトを作成します。<BR>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/a7e70208-2b85-4bf5-3e06-218eecc946f1.png)
2. メニューから[File]-[Build Setting]選択します。そして以下の通り設定変更後、[Switch Platform]をクリックします。<BR>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/fc7dcf1e-e21f-d855-2075-197fa003ed81.png)
<Table><TR><TD>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/1a12ab6c-12fb-22ac-dc59-a26d6289203a.png)</TD><TD><UL><LI>[Target Device]を[HoloLens] に設定</LI><LI>[Architecture]を[ARM 64] に設定</LI><LI>[Build Type]を[D3D Project]に設定</LI><LI>[Target SDK Version]を[Latest installed]に設定</LI><LI>[Minimum Platform Version]を[10.0.1024.0]に設定</LI><LI>[Visual Studio Version]を[Latest installed]に設定</LI><LI>[Build and Run on]を[USB Device]に設定</LI><LI>[Build configuration]を[Release]に設定</LI></UL></TD></TR></Table>

以上で一旦、Unityプロジェクトの設定が完了します。次にMRTK等の必要なコンポーネントを設定します。

#### Mixed Reality Feature Tool for Unityでのセットアップ

次にMixed Reality Feature Toolで必要なコンポーネントを設定します。アプリケーションの設定などは以下の公式ドキュメントを参考にツールをダウンロードして実行します。

https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/welcome-to-mr-feature-tool

1. アプリを起動し先ほど作成したUnityプロジェクトを選択し、[**Discover Feature**]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/1509ba6b-63b6-fce4-b903-e2d8ee2eba74.png)
2. 必要なコンポーネントを選択し、[**Get Feature**]をクリックします。
必要なコンポーネントは以下の通りです。一部便利なものもあるのでToolsはインポートしていますが任意です。
<Table><TR><TD>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/14fa34d9-4bf2-83e6-6f11-516a7017e99b.png)</TD><TD><UL><LI>Azure Spatial Anchors SDK for Core V2.11.0(必須)</LI><LI>Azure Spatial Anchors SDK for Windows V2.11.0(必須)</LI><LI>Azure Spatial Anchors SDK for Android V2.11.0(Androidで利用の場合必須)</LI><LI>Azure Spatial Anchors SDK for iOS V2.11.0(iOSで利用の場合必須)</LI><LI>Mixed Reality Toolkit Foundation V2.7.2 (必須)</LI><LI>Mixed Reality Toolkit Standard Assets V2.7.2 (必須)</LI><LI>Mixed Reality OpenXR Plugin V1.0.3 (必須)</LI><LI>Mixed Reality Toolkit Tools V2.7.2 (任意)</LI></UL></TD></TR></Table>
3. 依存関係の確認し、問題がない場合は[**Import**]をクリックします。
コンポーネントの依存確認が行われます。依存関係で追加忘れがあると対象を検索してくれます。今回は何もないはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/407c29a2-a18e-67d9-3c32-a77593ded681.png)



以上で、必要なコンポーネントのセットアップが完了しました。
次は再度Unityプロジェクト開いて作業を進めます。

#### OpenXRとMRTKの設定

次のUnityプロジェクトに追加したコンポーネントをセットアップしていきます。
1. [**MRTK Project Configurator**]で[**Unity OpenXR plugin(recommended)**]を選択
Unityプロジェクトを開くと、自動的にパッケージのインポートが実施され、しばらくすると以下のような設定画面が表示されるので、OpenXRの設定を進めていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/63448d65-6c36-5b99-ef44-5e53a72c92f1.png)
OpenXRの設定が実施され問題がなければ以下のようにXRプラグインの設定をするように指示されます。[**Show XR Plug-in Management Settings**]をクリックしてプロジェクト設定を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/10cd209e-d9f1-6088-c108-989a3a3a9b7e.png)
2. XR Plug-in Managementの設定
XR Plug-in Managementの設定を行っていきます。[**Project Settings**]から[**XR Plug-in Management**]を選択します。[**UWP**]タブ（Windowsのアイコン）が選択されている状態で[**Initialize XR on Startup**], [**OpenXR**], [**Microsoft Hololens feature group**]の3つをチェックします。チェックした際に警告（黄色い△）が出ることがありますが、Capability等の設定が不足しているために出てくるようです。クリックして必要な修正を加えてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/804ed30f-1ef5-225b-44bf-dee5a2c65e06.png)
次に[**OpenXR**]の設定を行います。[**Depth**]の設定を[**16bit**], [**Interaction Profiles**]に[**Microsoft Hand Interaction Profile**]を追加します。
![image.png](https://qiitai-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/b66ce24d-cfee-11ae-f79f-084ab473d6c8.png)
上記でOpenXRについての設定は完了です。
3. 設定の反映
最後に設定を適用していきます。上記の作業を進めると[**MRTK Project Configurator**]は以下の様に変更していると思います。まずは左の[**Apply Settings**]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/67a5a400-68d6-1fee-2603-52a6d30439ce.png)
次に[**Next**]をクリックして次の設定画面へ移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/783bc69f-d7dc-2b89-e49f-c7272c44865b.png)
プロジェクトに適用すべき設定が表示されるのですべてチェックされていることを確認して[**Apply**]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/f76cf636-e031-3e83-4292-a462094b05fa.png)
4. Package Nameの変更
最後に忘れがちなパッケージ名を変更します。比較的初期のからありがちな話なのですが、HoloLensにインストールするアプリケーションを内部で一意に管理するためにパッケージ名を使っています。このためUnityプロジェクトを作成した後にパッケージ名を変更せずにいると**「名前(表示名)が違うアプリケーションでもパッケージ名が同じだと同一視」**されてしまいます。[**Project Settings**]-[**Player**]-[**Publishing Settings**]-[**Packaging**]-[**Package Name**]を変更しておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/670114b8-6114-42dd-570c-7b9bde5d7a41.png)

### 4.World Locking Toolsとサンプルの導入

次に、World Locking Toolsを導入します。

#### Nuget for Unity を経由したMicrosoft.MixedReality.Unity.FrozenWorld.Engine V1.1.1の導入

最初にWorld Locking Toolsが利用するライブラリ「Microsoft.MixedReality.Unity.FrozenWorld.Engine V1.1.1」を導入するためにNugetを導入します。
[Assets]-[Import Package]-[Custom Package]を選択し、ファイル選択ダイアログから「NugetForUnity.3.0.3.unitypackage」を選択しインポートします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/e679ecd7-77bb-cb24-e809-20180c196ad0.png)

インポートが正常に終了するとメニューに[Nuget]が追加されます。[Nuget]-[Manage Nuget Package]を選択してNugetパネルを開きます。
[Microsoft.MixedReality.Unity.FrozenWorld.Engine]で検索すると一覧に表示されるので[install]を実施します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/9d5eb806-cc07-81b7-a473-eaedc5ada416.png)

#### World Locking Toolsを導入する

Nugetと同じ要領で以下のunitypackageをインポートします。

* Microsoft.WorldLockingTools.Unity.CoreEngine.unitypackage
* Microsoft.WorldLockingTools.Unity.Tools.unitypackage

#### サンプルを導入する

最後にWorld Locking Toolsのサンプルを導入します。
まず、[Microsoft.WorldLockingTools.Unity.Examples_wMRTKv2.7.2.unitypackage]を導入します。ここで注意なのですが[MRTK]についてはMixed Reality Feature toolで導入済みなのでサンプルのみを選択します。以下の様に不要な部分はチェックを外してインポートします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/06c42669-73fc-aabf-5581-d3016a2b087b.png)

次にWorld Locking ToolsのAzure Spatial Anchorsサンプルを導入します。[Microsoft.WorldLockingTools.Unity.ASA_wExamples.unitypackage]をインポートして必要なモジュールはすべて導入が完了になります。すべてのモジュールが設定完了すると以下のようなプロジェクト構成になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/9c32324e-d4ca-591b-d00f-448d4e2b19e1.png)

#### Azure Spatial Anchorsの設定を行う。

次にサンプルが利用するAzure Spatial Anchorsの接続先に関する情報を定義します。[Hierarchy]から[WorldLocking/SpacePinBinder]を選択します。[Inspector]パネル内の[Spatial AnchorManager]の中にある設定項目に、Azure Spatial Anchorsの各種情報を入力します。

* Authenication Mode : Api Key
* Spatial Anchors Account Id : Azure Spatial Anchors のアカウントID
* Spatial Anchors Account Key : Azure Spatial Anchors のアクセスキー
* Spatial Anchors Account Domain : Azure Spatial Anchors のサービスドメイン名

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/856e43ec-14c4-fccc-4fd6-a22db33c2e73.png)

以上でサンプルを動作させるための設定が完了です。次に各デバイス毎の設定を行います。

### 5.HoloLensへのデプロイ

HoloLens 2にデプロイするためにMRTKのプロファイルを変更します。Build Settingsを開きPlatformがUniversal Windows Platformであることを確認します。
次に[Scenes in Build]に[WorldLocking.ASA.Examples/Scenes/PinTestSofa]を含めてチェックしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/4e294960-aa7e-3de5-6686-939176ae3e12.png)

次に[Hierarchy]パネルの中から[MixedRealityToolkit]を選択し、[Inspector]パネル内のプロファイル設定を[OpenXRConfigutaionProfile]に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/6ea41360-f61a-1ca0-c927-b8655b536990.png)

Unity上でBuildを行いサンプルアプリのVisual Studioプロジェクトを生成します。
最後に、生成されたプロジェクトファイルの中にある[Package.appxmanifest]ファイルにWifiControlのcapabilityを追加します。これはAzure Spatial AnchorsのCoarse Relocationを利用する際にWifiのSSIDなどを利用する為にアクセス権を付与するためです。

```xml:Package.appxmanifest
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4" xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10" xmlns:mobile="http://schemas.microsoft.com/appx/manifest/mobile/windows10" IgnorableNamespaces="uap uap2 uap3 uap4 mp mobile iot" xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10">

...

  <Capabilities>
    ...
    <DeviceCapability Name="wiFiControl"/> ←この行を追加
  </Capabilities>
</Package>
```

あとはHoloLens にデプロイして完了です。

### Andriodの場合

Androidにデプロイする場合はPlatformをAndroidに変更します。次にARFaoundation用の機能を追加するためにメニューから[Mixed Reality]-[Utilities]-[UnityAR]-[Update Scripting Defines]を選択し、コードを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/5adfcda9-9845-60d0-ef90-1d8c42178e0a.png)


次に[Hierarchy]パネルの中から[MixedRealityToolkit]を選択し、[Inspector]パネル内のプロファイル設定を[Xample AR ToolkitConfigurationProfile]に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/e6b19d78-8842-0a9b-d2ec-e4238007c32d.png)

最後にAzure Spatial Anchorsを利用する為の設定を行います。[Project settings]-[Player]-[Other Settings]の以下の項目をチェックします。

* Custom Main Manifest
* Custom Main Gradle Template

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/839728fe-abe9-a739-d777-74227eaae50c.png)

また、[Project Settings]-[XR plug-in Management]を選択し、Androidタブ内の[ARCore]にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/05deeb67-ef84-8131-5fb2-3c6db01770c2.png)

Manifestファイルを開き以下の記述を追加します。

```
  <uses-permission android:name="android.permission.CAMERA" /> 
  <uses-feature android:name="android.hardware.camera.ar" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
  <uses-permission android:name="android.permission.BLUETOOTH"/>
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
```

```xml:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.unity3d.player"
    xmlns:tools="http://schemas.android.com/tools">

<!-- ここから -->
  <uses-permission android:name="android.permission.CAMERA" /> 
  <uses-feature android:name="android.hardware.camera.ar" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
  <uses-permission android:name="android.permission.BLUETOOTH"/>
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- ここまで追加 -->

  <application>
   ....
  </application>
</manifest>

```

mainTemplate.gradleファイルを開き以下の記述を追加します。

    implementation('com.squareup.okhttp3:okhttp:[3.11.0]')
    implementation('com.microsoft.appcenter:appcenter-analytics:[1.10.0]')

```gradle:mainTemplate.gradle
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN

apply plugin: 'com.android.library'
**APPLY_PLUGINS**

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

//ここから
    implementation('com.squareup.okhttp3:okhttp:[3.11.0]')
    implementation('com.microsoft.appcenter:appcenter-analytics:[1.10.0]')
//ここまで追加

**DEPS**}

android {
    compileSdkVersion **APIVERSION**
    buildToolsVersion '**BUILDTOOLS**'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        minSdkVersion **MINSDKVERSION**
        targetSdkVersion **TARGETSDKVERSION**
        ndk {
            abiFilters **ABIFILTERS**
        }
        versionCode **VERSIONCODE**
        versionName '**VERSIONNAME**'
        consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
    }

    lintOptions {
        abortOnError false
    }

    aaptOptions {
        noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
        ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
    }**PACKAGING_OPTIONS**
}**REPOSITORIES**
**IL_CPP_BUILD_SETUP**
**SOURCE_BUILD_SETUP**
**EXTERNAL_SOURCES**
```

最後にAndriodデバイスにデプロイして完了です。

### iOSの場合

調査中...

## サンプルアプリの利用方法

サンプルアプリケーションでは以下の手順でSpacePinをAzure Spatial Anchors上で管理することでWorld Locking Spaceのデバイス間での共有を実現します。

1. 表示されるソファーの端点2つのPinを任意の場所に設置する<BR>この際できればPinの位置を現実空間の目印になる物体を合わせておくと機能を理解しやすくなります。
1. アプリケーションのメニューにある[pushlish]をタップします。これによりソファー端点にある2つのSpacePinがAzure Spatial Anchorsに登録されます。<BR>この際アンカーの情報はPushlish時に利用していたWIFI情報と共に登録されます。
1. 一度アプリを終了するか、別のデバイスで同じアプリケーションを起動します。
1. メニューより[Search]をタップするとAzure Spatial AnchorsからSpacePinの情報を取得します<BR>WIFI情報に基づいて周辺にあるAnchor情報を取得し配置します。
1. 最初に設置した現実空間の位置と等しい場所にSpacePinが設定されWorld Locking Spaceが共有されている事を確認することができます。

## まとめ

インサイドアウト方式による自己位置推定を利用するHoloLensやARデバイスにおける現実空間とデジタルコンテンツの位置をできるだけ正確に合わせるためのライブラリ「World Locking Tools」と「Azure Spatial Anchors」を組合わせたデバイス間でのデジタルコンテンツの共有方法がどういったものか試すためのサンプルの利用方法について紹介しました。
現状iOSがまだうまく実現していないことと、実際のコンテンツでこれらの技術をどう利用するかについては引続き整理していきたいと思います。