たるこすの日記

たるこすの日記

リアルからバーチャルへ、バーチャルからリアルへ

Wii リモコンを HoloLens コントローラとして使ってみる

はじめに

こんにちは、たるこすです。

ついに、Wii リモコンを HoloLens のコントローラとして使えるようになりました。

この記事では、デモ動画と実装の仕組みを紹介します。

デモ動画

まずはデモ動画をご覧ください。

Wii リモコンを向けた方向にカーソルが移動し、Wii リモコンの B ボタン(背面のトリガー)を押すことでオブジェクトを選択できるようになりました。

環境、ライブラリ

仕組み

全体の構成

以下のサイトの Prerequisites 欄に書かれていますが、2011年11月以降に製造された Wii リモコン は Microsoft 標準の Bluetooth ドライバでは接続できません。

touchmote.net

手元にあった Wii リモコンは Wii U を買ったときについてきた新しいものなので、HoloLens と直接接続することはできませんでした。古い Wii リモコンであればもしかしたら接続できるかもしれないので、もし持っている方は試してみてください。

今回は、Wii リモコンは PC と接続し、PC 側で値を読み取って HoloLens に送ることにしました。

Wii リモコンからのデータ

以下の記事にもまとめましたが、Wii リモコンはセンサーバー(実際にはセンサーではなく両端に赤外線 LED がついているもの)と組み合わせることで、Wii リモコンを向けている位置を取得することができます。

tarukosu.hatenablog.com

今回は、Wii リモコンのポインタ位置と A,B ボタンの入力を PC で受け取って HoloLens に送っています。

PC側: Unity での Wii リモコンの値の読み取り

PC と Wii リモコンを接続し、値を読み取るところまでは以下の記事にまとめています。

tarukosu.hatenablog.com

上記記事で利用している Unity-Wiimote のサンプルシーンをベースにして、変更を加えていきます。

HoloLens へのデータの送信は、HoloToolkit の Sharing を使っています。HoloToolkit に Prefab として入っている Sharing をシーンに配置します。

Wii リモコンの値の上記記事で利用している Unity-Wiimote のサンプルシーンに Wii リモコンの値を読み取るコードが入っているので、そちらを参考に以下のスクリプトを作成しました。

また、値の送信用に WiimoteMessages.cs を作成しました。こちらは HoloToolkit に含まれる CustomMessages.cs をベースに変更を加えたものです。

これら2つのコードを空の GameObject にアタッチします。

HoloLens側: Wii リモコンの値の受け取りとカーソル操作

プロジェクトを作成し、MixedRealityToolkit-Unity(HoloToolkit-Unity) と MRDesignLabs_Unity をインポートします。

まずは、 HoloLens, Sharing プレハブを配置します。

Vuforia を利用したモニター位置の認識

Wii リモコンから得られるポインタ位置は、センサーバーをモニターの下に置いた際のモニター上の 2D の位置になります。これを HoloLens で使うためには、HoloLens の座標系での位置に変換する必要があります。そこで、モニターに 2D のマーカー画像を表示し、Vuforia をつかってマーカー位置を認識することでモニターの位置を認識させます。

HoloLens で Vuforia を使う方法については、以下の記事にまとめています。

tarukosu.hatenablog.com

ImageTarget の子要素として、操作対象とするオブジェクトとスクリーン位置を表す Quad オブジェクトを配置しています。モニターに映ったマーカー画像を認識すると、ImageTarget の座標がマーカーの位置に移動し、子要素もそれに合わせて移動します。

Wii リモコンの値の受け取り

空の GameObject を作成し(名前は WiiMote)ReceiveWiimote.cs と WiimoteMessages.cs をアタッチします。

WiimoteMessages.cs は PC 側アプリで使ったものと同じです。

ReceiveWiimote.cs は以下のようなスクリプトで、PC から送られてきた 2D のポインタ位置から、Wii リモコンの位置姿勢を推定し WiiMote オブジェクトの位置姿勢を変更しています。

まず、2D のポインタ位置と 3D のモニターの位置姿勢(Vuforia を使って設定した Quad オブジェクトの位置姿勢)を使って 3D のポインタ位置を計算します。そして、WiiMote オブジェクトの位置は HoloLens の現在位置の 40cm 下に(かなり適当な値ですが)、姿勢は transform.LookAt を使って 3D のポインタ位置を向くようにしています。

カーソルの移動

最後に、先ほど作成した WiiMote オブジェクトの位置姿勢を使ってカーソルを移動させるようにします。WiiMote オブジェクトの子要素として、WiiMoteInput オブジェクト(空の GameObject) を作成し、以下のスクリプトをアタッチします。

作成した WiiMoteInput をカーソルに利用するようにします。

HoloLens > FocusManager > HoloLens Focuser を Inspector で表示し、Input Source に WiiMoteInput を設定します。

次に、MRDesignLabs に含まれる InputSources.cs を編集し、以下のフィールドを付け加えます。

public InputSourceWiiMote wiiMote;

これにより、HoloLens > InputMapping を Inspector で表示したときに、InputShellMap の Input Sources 欄に Input Source Wii Mote が表示されるようになります。

以上で HoloLens 側のアプリは完成です。

アプリの実行

アプリの実行は以下のような手順で行います。

  • PC と Wii リモコンを接続、Touchmote を起動
  • PC で Wii リモコンのデータを受け取るアプリを実行
  • PC で HoloToolkit に含まれる SharingService.exe を実行
  • HoloLens で作成したアプリを実行
  • モニターで 2D マーカーを表示
  • HoloLens でマーカーを認識
  • Wii リモコンを動かすと HoloLens 上でカーソルが移動する

再度デモの映像を貼っておきます。

おわりに

Wii リモコンを使った操作は HoloLens 標準の操作方法 (Gaze, Air-Tap) に比べて直感的で使いやすいと感じました。センサーバーの配置や PC 側の準備が必要だったり、センサーバーがある方向にしか使えないという問題はありますが、展示コンテンツでは十分活用できそうです。

センサーバーの LED の間隔を広くして遠めに配置すれば Wii リモコンを動かして認識される範囲が広くなるはずなので、是非試してみたいと思っています。