Tango Serviceへの接続方法

備忘録を兼ねて、Unityで新規にSceneを作成し、Tangoに接続するまでの設定方法。


## Sceneの構成
"Assets" > "TangoPrefabs"から必要なオブジェクトをHierarchyタブにドラッグ＆ドロップして、Sceneに追加する。

"Tango Manager"、"Tango Camera"はアプリを問わず必須。"Tango Point Cloud"は必要に応じて。
~~Cameraは用途に応じていずれかを選択し、ベースにするとよい。~~

#### Tango Manager
Tango Serviceへの接続を行う。

#### Tango Camera
Tango標準のカメラを配置するプレハブ。
"Tango AR Screen (Script)"をアタッチすることで、ARカメラとなる。

【2017/4/8 追記】
2017年4月に行われたTango SDKのアップデート（Version 1.52：Gankino）で、カメラのPrefabがTango Cameraに統合され、Tango AR Camera、Tango Delta Camera、Tango Simple Cameraは非推奨（Deprecated）となりました。

#### ~~Tango AR Camera~~
~~ARモードでの映像表示に用いる。TangoARScreenにてカメラの映像が表示される。~~

#### ~~Tango Delta Camera~~
~~[Charactor Controller](https://docs.unity3d.com/jp/current/Manual/class-CharacterController.html)がアタッチされており、移動の制御に用いる。~~

#### ~~Tango Simple Camera~~
~~Frustum（カメラの向きや画角を表示）やTrail（カメラの移動軌跡）などが含まれ、カメラの姿勢表示に用いる。~~

#### Tango Point Cloud
点群データが更新されていく。Mesh Rendererを有効にすれば、Scene上で可視化もできる。


## Tango Managerの設定
Hierarchyに追加された"Tango Manager"を選択し、Inspectorタブで設定を行う。

![スクリーンショット 2017-01-16 18.04.44.png](https://qiita-image-store.s3.amazonaws.com/0/153460/129d7bd8-b653-f877-e42a-c1c1ebad7297.png)


#### Auto-connect to Service
チェックを入れると、アプリ起動時に自動的にTangoサービスに接続する。

#### Enable Motion Tracking
Motion Trackingを有効にする。"Auto Reset"にチェックを入れると、`TANGO_POSE_INVALID`になった際に自動でリセットを行う。

参考：
https://developers.google.com/tango/apis/c/c-motion-tracking#lifecycle

#### Enable Area Description
Area Descriptionを有効にする。Modeについては以下。

* Drift Correction  
  ドリフト補正モードを有効にする。
* Learning  
  学習モードを有効にする。
* Load Existing  
  既存のADFを読み込んで、ローカライズを行う。

参考：
https://developers.google.com/tango/apis/c/reference/group/config-params#summary

#### Enable Depth
Depth Perceptionを有効にする。TangoPointCloudが更新される。

#### Enable Video Overlay
Video Overlayを有効にする。Methodについては以下。

* Texture  
 画像データを取得。TangoARScreenが更新される。
* YUV Texture  
 [YUVフォーマット](https://ja.wikipedia.org/wiki/YUV)のデータを取得。
* Raw Bytes  
 生のバイトデータを取得。3DRで使用されている。

他の選択肢（"Texture and Raw Bytes"、"All"など）は、上記の組み合わせ。

#### Enable 3D Reconstruction
3DRを有効にする。パラメータについては以下。

* Resolution(meters)  
  3DRを行う際の解像度。
* Generate Color  
  チェックすると、色情報を生成する。
* Generate Normals  
  チェックすると、[法線ベクトル](https://ja.wikipedia.org/wiki/%E6%B3%95%E7%B7%9A%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB)を生成する。
* Generate UVs  
  チェックすると、[UV](https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%AF%E3%82%B9%E3%83%81%E3%83%A3%E3%83%9E%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0#.E3.83.86.E3.82.AF.E3.82.B9.E3.83.81.E3.83.A3.E5.BA.A7.E6.A8.99)を生成する。
* Space Clearing  
  チェックすると、Depthデータにより障害物のない空間のメッシュをクリアする。3DRを行う際、移動体(通行人など)の影響によるメッシュができてしまうため、それらのノイズを除去する役割と思われる。有効にすると、処理コストは高くなるが、メッシュの品質は向上する。
* Update Method  
  3DRのアルゴリズムを選択する。`TRAVERSAL`の方が`PROJECTIVE`よりも処理コストが高く、精度がややよくなる。
* Mesh Min Vertices  
  メッシュの構成要素が接続すべき最小の頂点数。設定値よりも少ない頂点数の要素はノイズとしてメッシュから除去される。
* Use Area Description Pose  
  Area Descriptionを利用する場合にチェック。

参考：
https://developers.google.com/tango/apis/c/reconstruction/reference/group/config-params#summary
https://developers.google.com/tango/apis/c/reconstruction/reference/group/enums#group___enums_1ga68b9b760afda90cd0c8b0cfdb1ad3fcc


## ScriptによるTangoサービスへの接続
Scriptで接続を行うため、Tango Managerの"Auto-connect to Service"はチェックを外しておく。

"GameObject" > "Create Empty"で新規オブジェクトを作成し、任意の名前に変更。
"Add Component" > "New Script"でスクリプトを作成する。

Tangoに接続するための最小のコードは以下。

```UIController.cs
public class UIController : MonoBehaviour, ITangoLifecycle
{

	private TangoApplication m_tangoApplication;

	void Start () {
		m_tangoApplication = FindObjectOfType<TangoApplication>();

		if (m_tangoApplication != null)
		{
			m_tangoApplication.Register(this);
			m_tangoApplication.RequestPermissions();
		}
	}

	void Update () {
	}

	public void OnTangoPermissions(bool permissionsGranted)
	{
		if (permissionsGranted)
		{
			m_tangoApplication.Startup(null);
		}
	}

	public void OnTangoServiceConnected()
	{
	}

	public void OnTangoServiceDisconnected()
	{
	}
}
```

#### ポイント
* ITangoLifecycleを継承しないと、`RequestPermissions()`を行っても`OnTangoPermissions()`が呼ばれない。

* ITangoLifecycleを継承するには、`OnTangoServiceConnected()`、`OnTangoServiceDisconnected()`を定義しないとビルドエラーになる。

```
error CS0738: `UIController' does not implement interface member `ITangoLifecycle.OnTangoServiceConnected()' and the best implementing candidate `UIController.OnTangoPermissions(bool)' return type `void' does not match interface member return type `void'
error CS0738: `UIController' does not implement interface member `ITangoLifecycle.OnTangoServiceDisconnected()' and the best implementing candidate `UIController.OnTangoPermissions(bool)' return type `void' does not match interface member return type `void'
```

* `TangoApplication.Startup()`を呼び出す際、ADFを利用する場合はAreaDescriptionの情報を渡す。利用しない場合はnull。

参考：
https://developers.google.com/tango/apis/unity/unity-user-permissions

#### 実行結果
`RequestPermissions()`を実行したタイミング（コード例では、アプリ起動直後）にデバイスへのアクセス許可ダイアログが表示される。

![Screenshot_20170117-220400.png](https://qiita-image-store.s3.amazonaws.com/0/153460/ae1687fd-3334-ef24-54e6-7f51e496a3d2.png)

"許可する"を押下すると、`OnTangoPermissions()`が呼ばれ、`TangoApplication.Startup()`が実行される。

以下の画面が表示されればOK！

![Screenshot_20170117-230141.png](https://qiita-image-store.s3.amazonaws.com/0/153460/047b99b8-7958-c9ad-1009-36138cebfe95.png)

接続ができたら、Tango Manegerで有効にした機能のみ、データが更新され、`OnTangoPoseAvailable()`、`OnTangoDepthAvailable()`などのイベントが発生するはずなので、取得したデータを利用する処理を書いていけばよい。