スタンプ型デバイス(5) ~VuforiaとHoloLens2~

####まえがき
[前回](https://qiita.com/T170521/items/7ccf437b561199c0d42a)，HoloLens2とデバイスの連携に成功した．
理想としてHoloLens2以外のデバイスでも利用できるようにしたいと考えていたが，
このデバイスをBletoothKeyboradとして扱うことで，Android，iOS，Vive，PCなどでも利用可能となった．

今回はデバイスをトラッキングする手法を考えることにした．
・**~~Bluetoothを利用した位置調整~~** 
　→ Bluetoothでは数cm単位での同期ほぼ不可能
・**~~画像処理，機械学習による識別(python)~~**
　→ python勉強中
・~~**NuGetForUnityを用いたQRコードトラッキング**~~
　→ 試したがうまくいかなかった
・**Vuforia**
　→ Androidで触ったしいけそう！

ということで以前利用したことがあるVuforiaを使用することにした．
HoloLens1・2用のAssetがstoreにあったので，まずはHoloLens2でDemoを作ることにした．

####本題
HoloLens2でデバイスを活用したARコンテンツのデモを作成する

#####機器概要
・Windows10 Laptop
・Unity 2019.3.2f1
・HoloLens2
・Visual Stadio 2019
・Arduino IDE
・スタンプ型デバイス(M5StickC)

####準備
Vuforiaを利用するにはアカウントを作成する必要があります．
1. [Vuforia Developer Portal](https://developer.vuforia.com/)にアクセス
2. Register」からアカウントを作成，ログイン
License Managerへ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/b03f5c48-ea6f-038e-ff9c-917086e27f05.png)
3. Get Development KeyでLicense Keyを発行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/aca98600-54a1-681d-8869-3dff7613d6c8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/9b7da290-e89c-5c8b-24a2-ae943e418885.png)
※License Key(赤枠で塗りつぶしたところ)はUnityの画面で使用する
4.Target Managerからマーカーを登録する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/9fc26cab-c1e1-cc3a-eeeb-cf273d99c7d3.png)
Add Databaseをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/bf860053-d8ff-716c-2945-ba6be5409750.png)
TypeはDeviceでCreate
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/8b8dfe3c-2273-3ed8-e606-a310443a34da.png)
Add Targetをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/418040ee-f3c6-ccc9-44b7-747a27d5e97a.png)
**Type**：マーカーにしたい形状を選択，今回は平面
**File**：マーカーとする画像を選択，今回は特徴点がわかりやすいQRコードを使用
**Witdth**：マーカーのサイズを指定，1=1mなので今回は0.01=1cmを指定

Addするとマーカーが追加される
Ratingは特徴点の多さ，認識のしやすさ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/88d19f6e-03a6-689d-ad9c-1033a759de1e.png)

Unity内で利用するためには，`Download Database`をクリック
必要なtargetを選択して，.unitypackageファイルをDL
これをプロジェクト内にImportすることで利用可能となる

####手順
#####1. Unityでプロジェクトを作成

#####2. HoloLens2用の設定に変更する
・Universal Windows PlatformにSwitch Platformをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/f8578803-790b-8bf6-4c06-909a9b901f55.png)
・MRTK Project ConfiguratorでApplyをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/fc6a20f0-a3a0-aa6d-e070-6da10c90acd1.png)
・TextMeshProでImport TMP Essentialsをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/7a8e527a-81b3-26fc-81ae-ce9dda55374e.png)
・PlayerのXR Settingsを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/30f46402-3aae-c12d-20f1-5f4f50833059.png)
 

#####3. Asset Storeから`Vuforia Hololens 1+2 Sample`をimport
※バージョンが違うかもしれないが構わず，Install/Upgrade
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/a4144e01-01a4-0827-7d31-23e5b11c7cbd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/720acdde-2547-afd0-3216-d03a31b4813d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/4e163c8c-2c9e-c9b5-609b-c329cece559f.png)
エラーも無視でOK(たぶん)

#####4. Sampleシーンを試してみる
HoloLens2でVuforiaが動くことを確認する
`Assets/SampleResources/Scenes`を開くとサンプルがあるのでこれらをビルド
出てきたファイルをVisual StadioからHoloLens2にビルド
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">HoloLens2でVuforia使ってみた<a href="https://twitter.com/hashtag/HoloLens2?src=hash&amp;ref_src=twsrc%5Etfw">#HoloLens2</a> <a href="https://twitter.com/hashtag/Vuforia?src=hash&amp;ref_src=twsrc%5Etfw">#Vuforia</a> <a href="https://twitter.com/hashtag/Unity?src=hash&amp;ref_src=twsrc%5Etfw">#Unity</a> <a href="https://t.co/YBRgX42D37">pic.twitter.com/YBRgX42D37</a></p>&mdash; ゆーま (@sagirin262) <a href="https://twitter.com/sagirin262/status/1306501972925640704?ref_src=twsrc%5Etfw">September 17, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#####5. 自作のシーンを作成
まず自作のマーカーを利用するためには発行したLicense Keyを入力する
`Assets/Resources/VuforiaConfiguration`を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/87278333-c0cc-b77b-ab2c-3a398a76c247.png)
`App License Key`にLicense Keyをコピペ
これでLicenseが認証される

次にDLした自作したマーカーを入れる
パッケージをimportする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/ecea887e-3675-2326-1bbe-abb1794984fa.png)
これで後述の`Database`や`Image Target`から選択できるようになる

デモ用のシーンを作成する
・0.Menu
・1.Scene1
・2.Scene2
・3.Scene3

必要なものをSampleから持ってくる
※`MixedRealityToolKit`と`MixedRaaliyPlayspace`はそれぞれのシーンで新たに作成した方が良い
　作成の仕方は`MixedReality/Add to Scene and Configure...`をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/1f21dcb6-5ca3-da93-a988-9defeb961a34.png)

**Menu**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/0b4b0035-b278-714e-084e-67f907cf335f.png)
・`SpeechInputHandler` ← 音声認識に関するもの
・`Lights` ← 光源
・`UIContent` ← Menuのオブジェクト，シーン遷移ができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/8316abcc-6db5-e978-dd9b-6d4f14dc7025.png)
`Button`の`FrontPlate`にそれぞれ`Scene Loader`というscriptがアタッチされている
この変数を変更することでどのシーンに移行するか変更できる(例では3)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/f7c41443-3a16-a0ac-1caa-e0d5a909115c.png)
シーンの番号はBuild Settingsを参照
ビルド対象に選択した順に0から番号を振られる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/c59ce51f-fffb-0a34-430e-dc0d8258d7aa.png)
また,Buttonのテキストは`SectionTitle`の`TextMeshPro-Text`，マークは`Quad`の`Mesh Render`の`Materials`から変更可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/447dcb4e-2dee-f425-be18-9016f5fd2f53.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/3f05f689-c115-a599-ff18-82257a8806a5.png)

**Scene1,2,3**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/b8742e70-e6c8-0143-3ba6-4666150c47dc.png)
・`SpeechInputHandler` ← 音声認識に関するもの
・`Lights` ← 光源
・`UIContent` ← 説明のパネル(Homeボタン付き)，Menuへの遷移ができる
・`VuforiaContent` ← ARtargetと出現するobject
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/dc102fd2-52b9-5ec3-7776-aefcd2452e6d.png)
`VuforiaContent`にはImageTargetが入っている．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/8e405edf-b4ac-5522-4787-7cd0181b9fdd.png)
`ImageTarget`には`Image Target Behaviour`というscriptがアタッチされている
この内容を変更することでARマーカーとなる画像等を変更することが可能である
**Type**：Vuforiaに登録したDatabaseを利用するので`From Database`
**Database**：自分の作成したDatabase
**Image Target**：登録したTarget

`ImageTarget`の下にAR表示させたいobjectを配置することでマーカーを認識したときにobjectが表示される

#####6. プログラムを作成
今回作成したいものはマーカーをトラッキングして，その位置にobjectを配置するプログラムである

次にマーカーを配置
マーカーとなるobjectは`Create/Vuforia Engine/Image Taget`で作成できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/8cdad8dc-83d8-0959-2f29-3b8440f3a13b.png)
マーカーの設定は`Image Target Behaviour`から行う

マーカーの下に，位置を伝える`Position_Maker`と認識したことがわかるように`Plane`を置く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/899c5773-52f7-39a0-f776-f5bc6a8a2711.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/fcf8ad36-b72a-c497-b756-731d360d1203.png)

初期位置の調整用のscriptを作成

```C#:Tracking.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tracking : MonoBehaviour
{
    public GameObject imageTarget;
    //初期の位置を設定
    public float x = 0.0f;
    public float y = 0.0f;
    public float z = 0.0f;
    private void Start()
    {
        Vector3 target_Pos = new Vector3(x, y, z);
        this.GetComponent<Transform>().localPosition = target_Pos;
    }
}
```
`Plane`と`Position_Maker`にアタッチ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/e482046b-9c5f-5889-66c9-595ca1ac7a22.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/11acebca-8031-2ab3-0e2e-aebb2c8765c2.png)

デバイスの入力処理，マーカーのPositionを認識してそのy=0の位置にオブジェクトを配置するscript
スイッチで生成，ButtonAで種類変更，ButtonBで出したオブジェクトを全消し

```C#:Device_Controller.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Device_Controller : MonoBehaviour
{
    public GameObject[] Stamp;
    private int num = 0;
    public float tall_down = 0;
    private void Update() {
        if(Input.GetKeyDown(KeyCode.LeftControl)){
            //マーカーの位置を取得
            Vector3 Maker = GameObject.Find("Position_Maker").transform.position;
            // Debug.Log("Device: " + Maker);

            //マーカーの位置の下(y=0)にスタンプ
            Maker.y = -1.0f * tall_down;
            // Device_Pos.transform.position = Maker;
            // Transform Pos = Device_Pos.transform;
            // Pos = Vector3(Maker.transform.position.x, 0 , Maker.transform.position.z);
            Vector3 Pos = Maker;
            Instantiate(Stamp[num], Pos, Quaternion.identity);
        }
        else if(Input.GetKeyDown(KeyCode.Tab)){
            num++;
            if(num >= 3) num = 0;
        }
        else if(Input.GetKeyDown(KeyCode.Escape)){
            // GameObject型の配列targetsに、"stamp"タグのついたオブジェクトをすべて格納
            GameObject[] targets = GameObject.FindGameObjectsWithTag("stamp");

            // GameObject型の変数targetに、targetsの中身を順番に取り出す。
            // foreachは配列の要素の数だけループします。
            foreach (GameObject target in targets) {
                // 消す！
                target.GetComponent<Destroy>().OnDestroy();
            }
        }
    }
}
```

`Event`を作成してアタッチ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/538a56e6-7cba-3ef3-8e95-0a5fc04a0957.png)

出現させるobjectに自分を消すscriptをアタッチ(多くなりすぎると処理落ちする可能性があるため)

```C#:Destroy.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Destroy : MonoBehaviour
{
    public void OnDestroy()
    {
        Destroy(this.gameObject);
    }
}

```

`stamp`というtagを作成して，出現させるobjectを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/d59a2ee5-89c1-45dd-4889-fc41cd445051.png)

これで完成
ビルドして，VisualStadioからHoloLens2にビルドする．

####実行例
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">QRコードをトラッキングしてスタンプできる😁<a href="https://twitter.com/hashtag/HoloLens2?src=hash&amp;ref_src=twsrc%5Etfw">#HoloLens2</a> <a href="https://twitter.com/hashtag/Vuforia?src=hash&amp;ref_src=twsrc%5Etfw">#Vuforia</a> <a href="https://twitter.com/hashtag/Unity?src=hash&amp;ref_src=twsrc%5Etfw">#Unity</a> <a href="https://t.co/FlAgvUQCfK">pic.twitter.com/FlAgvUQCfK</a></p>&mdash; ゆーま (@sagirin262) <a href="https://twitter.com/sagirin262/status/1308688604051337216?ref_src=twsrc%5Etfw">September 23, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

####トラブルシューティング
主に詰まったところを載せておく
・**2回目以降のVisualStadioのビルドがうまくいかない**
Unityで同じフォルダにビルドした際にVisualStadioで配置完了してもうまくいかない場合がある．
おそらく他の設定ファイルとごっちゃになってしまう場合である．
そんな時はビルド先のフォルダを新たに作成すると良い．(APP，Demo等)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/60691291-1002-1e74-0043-581487407cc6.png)

・**HoloLens2で同じアプリとして認識され，上書きされる(設定でアプリ名を変更しても)**
別のアプリとして認識させたいときは別のプロジェクトでビルドしましょう．
ちなみにUnityのアプリとVuforiaのアプリは別もの扱いされる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563922/73e40c99-e459-de6d-3daa-14cea8847bc6.png)

####あとがき
QRコードで位置をトラッキングできたのでデバイスに張り付ければ使えそう！！(なおサイズ...)
VuforiaはAndroid,iOS,HoloLens2では使えそうだし,汎用性高い😊(Viveはカメラ占有されて？無理とか聞いた)
とりあえずできたので良かった．
分からないことやトラブル，エラーなどがあれば気軽にどうぞ．

####参考
**Nuget**
・[QR コードの追跡](https://docs.microsoft.com/ja-jp/windows/mixed-reality/qr-code-tracking)
・[Hololens2とQRコードについて学ぶ](https://bibinbaleo.hatenablog.com/entry/2020/04/13/203400)
**Vuforia**
・[Unity での Vuforia Engine の使用](https://docs.microsoft.com/ja-jp/windows/mixed-reality/vuforia-development-overview)
・[HoloLensでVuforiaを、一歩ずつ進めながら、確実に動かす](https://qiita.com/Feel-Physics/items/b7fef686f1e8c571d541)
・[HoloLensでVuforiaを使う (Unity&MRTK 2017世代)](https://yotiky.hatenablog.com/entry/2018/08/15/HoloLens%E3%81%A7Vuforia%E3%82%92%E4%BD%BF%E3%81%86_%28Unity%26MRTK_2017%E4%B8%96%E4%BB%A3%29)
・[【Unity】Vuforiaを使ってARを表示する手順（2019年版）](https://nn-hokuson.hatenablog.com/entry/2018/08/28/192028)
・[UnityとVuforiaで始めるAR開発](https://www.slideshare.net/ssuserc0d7fb/unityvuforiaar-149068313)