測域センサーのUnity連携

測域センサー(レーザー・レンジ・スキャナー)を使うと壁や床をタッチパネルのようにすることができます。

有名なものとしては、チームラボさんの「未来の遊園地」があります。

弊社でも去年やったイベント「ジョジョウォール」で、測域センサーを使用しています。

測域センサーは北陽電機さんのURGセンサーを使用しています。

 

ジョジョウォールでは、センサー値の取得から映像表現まで全てopenFrameworksを使用しています。

そこらへんの中身についての記事はコチラ

そこで、この記事ではopenFrameworksではなく、Unityと連携してみることにしました。

実は測域センサーとUnityの連携については、上述のチームラボの斎藤 康毅さんのブログで丁寧に書かれています。とても参考になりました。ありがとうございます。

この記事では、センサー値をUnityで受け取るまでを実装レベルでみていきたいと思います。

 

諸々のバージョンなどの開発環境は以下の通りです。

【環境】

UST-10LX(測域センサー)

Mac OS X Ysemite 10.10.5

Xcode Version 7.2 (7C68)

Unity version 5.3.1f1

Apple LLVM version 7.0.2 (clang-700.1.81)

URG library v1.2.0

oscpack v1.1.0

UnityOSC v1.2

OpenCV v2.4.12

 

まずは、北陽電機さんのドキュメントに従ってURGセンサーのライブラリをインストールします。

c/c++、c#、javaの3種類がありますが、Macなので、環境を作るのが一番楽なc/c++を使いました。

とりあえず、この段階でちゃんと動くか試してみます。

今回使っているセンサー(UST-10LX)は、インターフェースがEthernetになっていて、センサーを電源に繋いで、PCのEthernetのとこに挿した後にネットワーク環境設定でIPアドレスを設定することで、センサーからの値をPCで受け取れるようになります。

センサーは初期設定ではIPが192.168.0.10になっているので、192.168.0の部分を同じにして、10の部分は1~254のうちの10以外の値を適当に設定します。

スクリーンショット 2016-03-30 16.46.10

 

ライブラリに入っているc++のサンプル、get_distanceを動かしてみました。

Ethernetなので、実行時の引数に -e を指定します。

センサーから値が取得できました。

 

このサンプルに手を加えて、Unityと連携させます。

その前にせっかくMacなので、Xcodeを使いたいと思います。

Xcodeを起動してコンソールアプリケーションのプロジェクトを作成します。

スクリーンショット 2016-03-30 16.57.48

Build Settings -> Search Paths -> Header Search Paths にURGセンサーのライブラリのパスを設定します。

ライブラリインストール時に特に何もしていなければ、パスは /usr/local/include/urg_cpp です。

次に Build Phases -> Link Binary With Libraries のところに /usr/local/lib/liburg_cpp.a をドラッグ&ドロップします。

そして、get_distance.cppの中身をmain.cppにコピペするか、main.cppを消してget_distance.cppを入れるかすればOKです。

最後に実行時に引数として -e を指定するために、Edit Scheme -> Run -> Argumetnts Passed On Launch に -e を設定して、実行する準備完了です。

 

get_distance.cppの22行目のフラグを0にして、前方だけではなく、全てのデータを取得するようにしましょう。

URGセンサーから取得できる値は、30°の方向の距離1,300mmといった極座標で値が取れるので、三角関数を用いてX-Y 座標系に変換する必要があります。

詳しくは北陽電機さんのチュートリアルで丁寧に記載されています。

 

センサーからのX-Y座標が取得できたので、次はこの値にホモグラフィ行列をかけて、Unity側の座標の位置に対応させます。

ホモグラフィ行列を求めるにはopenCVを使うのが簡単で、

URGセンサーを使って反応させたい範囲の四隅の値と、Unityの中での四隅の値を引数にして、以下のように求めることができます。

以下では、200mm×400mmのURGセンサーの範囲を、Unityの座標における500×1,000に対応させるようにしています。

センサーから取得できた値を3×1の行列にして、上記で得られたホモグラフィ行列をかけてあげれば、Unityでの座標が求まります。

 

 

Unityでの座標が求まったので、次はそれをOSCを使ってUnityに送信します。

c/c++でOSCを扱うにあたって、シンプルで使いやすそうだったoscpackというライブラリを使いました。

今回は自分のPCのUnityアプリに送信するので、127.0.0.1にして、適当に8,000番ポートにしています。

 

そして、ようやくここから、Unityです。

UnityにはOSCを扱うのにUnityOSCというライブラリがGithubにあるので、それを使います。

マニュアルもあるのですが、このマニュアル通りだと、OSCのメッセージが最後の1つしか受け取れません。

ググると同じ問題にあたっている方がいましたので、参考にさせて頂きました。ありがとうございました。

 

 

適当にUnityでプロジェクトを作成して、見えやすいように500×1,000の青いQuadをおいて、

受信したOSCメッセージから得られた座標にSphereを生成してみました。

スクリーンショット 2016-03-30 19.34.06

下の白い四角がセンサーの位置です。自分の指を反応させてみました。(右上の部分の白い点)

 

今回使用したURGセンサーは、 センサーの周り270°の計測範囲があり、単純に取得すると1081ものが値が取れます。

計測範囲を指定したり、一定距離以上の値は無視するなどして、Unityに送る前にフィルターをかけてあげた方が良いと思います。

今回は、計測範囲を-90°〜90°にして、半径200mm以内の値のみOSCで送るようにしました。

しかし、単に指を反応させただけでも、21個も値が取れています。(距離が近いのもありますが。)

どんなものを作るかによりますが、取得した値の平均を求めて、それだけOSCで送信するなどしたら良いかもしれませんね。

●この記事を書いた人