ARスイッチで家電操作!


NTTドコモ移動機開発部の田中です。普段の業務ではXR(AR,VR,MR)関連の研究開発を行っています。
AdventCalendar2018では、IoT関連の記事を書かせていただきました。
今回はリアルとバーチャルを絡めた記事を書きたいと思い、ARスイッチを考えついたので、ハンズオン形式で作成する内容とさせていただきました。

はじめに

  • 本記事はプログラミング初級者向けです。ハンズオン形式で実際にARリモコンを作っていきます。
  • 本アプリはUnityで作ります。AR描画機能は簡単化のためVuforia[1]を使い、家電操作にはOSSのDeviceConnect[2]を用います。
  • 家電ですが、何がいいかなと悩みました。皆さんお持ちのスマートフォンを活用できないかなと思い、今回、スマホのライトを照明器具と見立て、ライトのON/OFFを操作するARリモコン(検証アプリ)を作っていきたいと思います。

  • イメージ

補足

  • 本記事を参考にした開発、SDK利用、プログラムの実行については自己責任でお願いいたします。
  • Vuforiaに関しては、2020年12月現在、非商用・開発検証目的であれば無償ライセンスで利用できます。本記事では検証目的でVuforiaを扱います。

ハンズオン(ARリモコンの作成)

  • 作成手順は大きく3ステップです。AR機能実装、デバイス制御実装、AR機能とデバイス制御の結合、の順に作っていきます。
  • 今回は家電=スマホライト、と見立ておりますが、DeviceConnectに対応した家電であれば本当の意味での家電(照明器具など)も操作可能です。

STEP0. 必要なもの

  • 【開発環境】 
    • Unity@開発用PC  (筆者環境は、Unity2019.4.10f1) 
  • 【実機、その他必要なもの】
    • Androidスマートフォン(家電のポジションです)
    • PC用のWebカメラ(もしくは2台目のスマホを用意し、アプリをスマホで動かすでもOKです。)
    • ARマーカ(プリンタで印刷。後ほどサンプルのマーカを記載します。)

STEP1. Vuforiaの設定・実装

  • ※Unity開発環境がある前提で進めます。
  • Unity上で新規シーンを作成いただき、Vuforiaの設定を行います。
  • 以下の手順でVuforiaをUnityにインストールしてください。

    • ①「Window→PackageManager」を選択
    • ②Vuforia Engine ARを選択 ※筆者環境は「Vuforia Engine AR 8.1.12」
    • ③Installを実行
  • 次に、AR表示用のカメラへの切り替えと、マーカオブジェクトの設置を行います。

    • ①Main Cameraは不要なので削除
    • ②「右クリック→VuforiaEngine」から、AR Cameraオブジェクトを選択
  • まずはデフォルトのARマーカを設置します。

    • 「右クリック→VuforiaEngine」から、Imageを選択
    • 「Import Default Image Database」という通知が表示されるので、「Import」を選択。※デフォルトのマーカ画像が登録されます。
  • ARマーカの下に、立方体を置き、実際にAR表示してみます。

    • ①ImageTarget(マーカ)の子オブジェクトとして、右クリック→3D Object→Cubeで立方体オブジェクト(Cube)を仮置き
      • ※箱の大きさと配置は微調整してください。
    • ②デフォルトのARマーカは以下のパスに配置されています。 「Assets→Editor→Vuforia→ImageTargetTextures→VuforiaMars_Images」
  • AR表示をしてみます。

    • 以下のように立方体がマーカ上にAR表示されていれば成功
  • 次に、マーカと3Dオブジェクトをライトのスイッチをイメージしたものに入れ替えます。

  • マーカの入れ替え

    • ※先ほど作成した「Image Target」オブジェクトは非表示にしておいてください。
    • VuforiaのDeveloper portal[1]へ行き、以下の手順でオリジナルマーカを設定します。※アカウント登録が必要です。

      • 「ログイン後、Develop→TargetManager→Add Database」を選択
      • Create Databaseという画面が開くので、Database Nameを「LightSwitch」等で設定し、Createを選択 ※TypeはDeviceのままで良いです。
      • 作成したデータベース「LightSwitch」を選択し、「Add Target」を開く
      • 以下の設定を行い、「Add」を選択

        • Type: SingleImage
        • File: 「Browse...」から任意の画像を設定
          • マーカ画像はなんでも良いですが、スイッチをイメージした以下のイラストを用意したので、ご自由にご利用ください。
          • ちなみにマーカ画像をアップロードすると、特徴点解析が行われ、マーカとしての認識精度が5段階(5つ星)評価されます。本マーカの評価は★2であり、あまり良い画像ではありません。STEP3での実装を見ていただければ分かりますが、マーカをLOSTしやすくするために今回はあえてこのような画像にしました。
        • Width: 1
        • Name: なんでも良いですが、ここでは「light_switch」とします。
      • マーカが登録されますので、「Download Database(All)→Unity Editor→Download」を選択し、Unityパッケージをダウンロードしてください。

      • ダウンロードしたUnityパッケージのファイルをダブルクリックして開き、Unityプロジェクトへインポート

      • 先ほどと同じ手順で「右クリック→VuforiaEngine」から、Imageを選択すると、以下のように入れ替え済みのマーカが表示されるはずです。

      • 最後に、以下手順でライセンスキーの作成と設定を行います。

        • ヒエラルキータブから、「AR Camera」オブジェクトを選択し、インスペクタータブから「Open Vuforia Engine configguration」を開く
        • ブラウザが開き、vuforiaサイトのLicense Managerが開くので、「Get Development Key」を選択
        • 「Add a free Development License Key」が開くので、License Nameを「light_switch」などで設定
        • Vuforiaの規約を確認した上で、チェックボックスにチェックを入れ「Confirm」を選択
        • すると、License Managerが開くので、設定したLicense Name「light_switch」を選択し、ライセンスキーを確認(コピー)
        • ライセンスキーをUnity上の「App License Key」のテキストボックスへコピペし設定
    • 3Dオブジェクト(スイッチっぽいオブジェクト)への入れ替え

      • 以下のようなスイッチをイメージした3Dオブジェクトを適当に作り、大きさと位置を調整します。「ImageTarget」オブジェクトの子オブジェクトとして配置してください。(先ほどの立方体が残っていれば非表示か削除してください。)
    • ここまで実施すると、オリジナルマーカとオリジナル3DオブジェクトでAR表示ができるようになります。

STEP2. DeviceConnectの設定・実装

  • 続いて、DeviceConnectの設定・実装を進めていきます。
  • DeviceConnectの基本的な使い方に関しては、以下の記事をご参照ください。
  • 本記事では、Unity上でDeviceConnectの扱い方についてご説明いたします。
  • 今回、DeviceConnectのHostプラグインを用いてスマートフォンのライトをUnityから制御したいと思います。上記記事を参考に、Hostプラグインの起動まで実施してください。
  • Hostプラグインのlightプロファイルを利用します。デバイス(スマホ)のライトを制御することが可能です。

  • lightプロファイルを開き、まずはスマホ上で以下のAPIを動作確認してください。

POST /gotapi/light/   :ライトを点灯させる
DELETE /gotapi/light/  :ライトを消灯させる
  • POSTを例に簡単に説明します。
    • ①リクエストパラメータの部分にPOSTリクエスト時に追加可能なパラメータが記載されています。
    • ②「Send Request」でライトを点灯させてみましょう。スマホのライトがつくはずです。
    • ③リクエスト内容が記載されているので確認してください。
    • ④レスポンス内容を確認してください。result=0であれば成功です。(ライトもついているはずです。)

  • ライトの消灯に関しては、DELETEリクエストを実行してください。

  • ここまでのライトの点灯(POST)と消灯(DELETE)の処理を、Unityスクリプトの各メソッド処理としてまとめると、以下の参考のようになるかと思います。

  • 【参考】ライトの点灯処理(POST)

    • [スマートフォンのIPアドレス]の部分は、DeviceConnectを導入したスマホIPアドレスを入れてください。ローカルで動作確認する場合は、一般的には「192.168.43.1」だと思います。
    • [各自環境ライトのServiceID]の部分についても、各自の環境で異なりますので、先ほどのリクエストパラメータを参考にServiceIDを記入してください。(「Host」から始まり、「deviceconnect.org」で終わる文字列です。)
    • 今回は簡単化のため、ServiceIDをハードコーディングしていますが、本来はserviceDiscoveryを用いて抽出し自動で挿入するのがスマートですね。
    /* ライトの点灯処理 */
    public void PostLight()
    {
        StartCoroutine(PostLightMethod());//Postメソッド実行
    }

    private IEnumerator PostLightMethod()
    {
        string url = "http://[スマートフォンのIPアドレス]:4035/gotapi/light";

        WWWForm form = new WWWForm();

        //パラメータの設定例
        form.AddField("serviceId", "[各自環境ライトのServiceID]");
        form.AddField("lightId", "0");
        form.AddField("brightness", "1");

        //POSTリクエストの送信
        UnityWebRequest postRequest = UnityWebRequest.Post(url, form);
        yield return postRequest.SendWebRequest();

        //エラー判定
        if (postRequest.isHttpError || postRequest.isNetworkError)
        {
            Debug.Log(postRequest.error);//エラー確認
        }
        else
        {
            Debug.Log(postRequest.downloadHandler.text);//結果確認
        }
    }
  • 【参考】ライトの消灯処理(DELETE)
    • [スマートフォンのIPアドレス]、[各自環境ライトのServiceID]に関しては、POSTリクエストの時の説明と同じです。
    /*  ライトの消灯処理 */
    public void DeleteLight()
    {
        StartCoroutine(DeleteLightMethod());//DELETEメソッド実行
    }

    private IEnumerator DeleteLightMethod()
    {
        string url = "http://[スマートフォンのIPアドレス]:4035/gotapi/light?serviceId=[各自環境ライトのServiceID]&lightId=0";

        //DELETEリクエストの送信
        UnityWebRequest deleteRequest = UnityWebRequest.Delete(url);
        yield return deleteRequest.SendWebRequest();

        //エラー判定
        if (deleteRequest.isHttpError || deleteRequest.isNetworkError)
        {
            Debug.Log(deleteRequest.error);//エラー確認
        }
        else
        {
            Debug.Log(deleteRequest.downloadHandler.text);//結果確認
        }
    }
  • 適当にUnity上でボタンUIを作成し、上記のPOSTメソッドとDELETEメソッドをアタッチし、動作確認をしてみてください。Unity上からスマホライトのON/OFFを制御できるはずです。

STEP3. VuforiaとDeviceConnectの結合

  • ここまできたら、あとはVuforia(AR表示)と、DeviceConnect(ライト制御)の実装を組み合わせるだけです。
  • 「ARマーカから仮想のスイッチが出現し、手で押すとライトが消える」、という演出にしたいので、「マーカがカメラからLOSTしたら、ライト点灯のPOSTメソッドが走る」という処理を考えてみたいと思います。
  • 「ImageTarget」オブジェクトにアタッチされている「DefaultTrackableEventHandler.cs」にマーカ発見時と見失った時の処理が記されています。ここにライトのON/OFFの処理を追加してみたいと思います。
    • (注意事項)今回は簡単化のために直接「DefaultTrackableEventHandler.cs」を変更しますが、一番良いやり方は「DefaultTrackableEventHandler」クラスを継承して実装する形かと思います。例えばVuforiaをアップデートすると、「DefaultTrackableEventHandler.cs」の変更が上書きされる可能性があるため注意が必要です。
  • まず「DefaultTrackableEventHandler」クラスに先ほどのDeviceConnectのPOSTメソッドとDELETEメソッドを追記しましょう。
  • 次に「OnTrackableStateChanged」メソッドの中の処理について確認してみてください。newStatusとpreviousStatusの値からマーカの状態を判定しているので、マーカが見つかったときに「ライトを消灯」、マーカを見失ったときに「ライトを点灯」するように、先ほど作成したメソッドを呼び出すよう追記します。
        if (newStatus == TrackableBehaviour.Status.DETECTED ||
            newStatus == TrackableBehaviour.Status.TRACKED ||
            newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
        {
            Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
            OnTrackingFound();
            DeleteLight();//ライト消灯
        }
        else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
                 newStatus == TrackableBehaviour.Status.NO_POSE)
        {
            Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
            OnTrackingLost();
            PostLight();//ライト点灯
        }
        else
        {
            OnTrackingLost();
        }
  • 以上の実装により、「ARマーカから仮想のスイッチが出現し、手で押すとライトが消える」という実装が出来ました。

デモ

  • 動作確認してみましょう。カメラをかざすと、ライトのスイッチがAR表示されます。AR表示されたスイッチを手で押す(マーカを覆う)と、スマホのライトが点灯するはずです。

まとめ

  • 思ったよりも地味なデモになってしまい、申し訳ありません。笑
  • VuforiaとDeviceConnectを組み合わせることで、何となく考えついたARスイッチを簡単に実装することができました。
  • 今回はスマホのライトを照明器具と見立ててデモを作りましたが、DeviceConnect対応デバイスであれば様々な制御が可能です。(スマホではなく本当の意味での照明器具のON/OFFを制御したり、カメラのシャッターをきったり、ロボットカー制御したり、等)
  • この記事をきっかけに、UnityでのAR開発やデバイス連携技術に興味を持っていただけますと幸いです。ここまで読んでいただき、ありがとうございました。

参考文献