Leap Motion は手指の位置や姿勢をセンシングするデバイスです.両手と10本の指の動きを独立してリアルタイム計測することができます.フリスク程度の大きさです.USB ケーブルでパソコンと接続することで,ジェスチャを利用したインタフェースを構築することができます.ここでは JavaScript を使って,ジェスチャに反応するウェブページをつくります.
Leap Motion の開発者向けページから "V2 Tracking" の SDK をダウンロードしてください.解凍すると dmg ファイルが見つかりますので,それをダブルクリックしてインストールしてください.数十秒で終るはずです.Leap Motion を USB 3.0 でパソコンと接続したら,Launchpad から Leap Motion を起動します.メニューバーに Leap Motion らしきアイコンが表示されますので,そこから Visualizer... を選択すると,ページ冒頭(右側)にあげたような動作確認用アプリが起動します.この Visualizer はいつ起動・終了しても,JavaScript による Leap Motion の動作には影響しませんので,いつでも自由に使ってください.
つぎに,こちらの「テストページ1」を開いてください.Leap Motion の上に手をかざすと,手の位置や姿勢といった情報がブラウザ上にリアルタイム表示されるはずです.これが動作すれば準備完了です.
上で表示させた「テストページ1」は,以下のような HTML ファイルです.赤字と青字の部分が,Leap Motion に関するスクリプト部分です.青字の部分が JavaScript のプログラムとなっています.
<html> <head> <title>test1</title> <script type="text/javascript" src="leap-0.6.3.js"></script> <script type="text/javascript"> <!-- // フレームごとに呼び出す関数 var leapFunc = function(frame) { var outputString = ""; for (var i = 0; i < frame.hands.length; i++) { var hand = frame.hands[i]; outputString += "手の番号:" + hand.id + "<br />" + " 種類 :" + ((hand.type == "right")? "右手": "左手") + "<br />" + " X座標:" + Math.round(hand.palmPosition[0]) + "<br />" + " Y座標:" + Math.round(hand.palmPosition[1]) + "<br />" + " Z座標:" + Math.round(hand.palmPosition[2]) + "<br />" + " ロール:" + Math.round(hand.roll ()*180/Math.PI) + "<br />" + " ピッチ:" + Math.round(hand.pitch()*180/Math.PI) + "<br />" + " ヨー :" + Math.round(hand.yaw ()*180/Math.PI) + "<br />" + " つまみ:" + Math.round(hand.pinchStrength * 100) + "<br />" + " にぎり:" + Math.round(hand.grabStrength * 100) + "<br />" } output.innerHTML = outputString; } // 関数 leapFunc を仕込む Leap.loop(leapFunc); --> </script> </head> <p> 【手をかざしてください】 </p> <body style="font-family: sans-serif; font-size: 20px;"> <div id="output"></div> </body> </html>
Leap Motion のプログラミングは,frame を引数とする関数を定義し,それを Leap.loop() で登録することが基本となります.上の例では,function(frame){...} という無名関数を定義し,それを leapFunc という変数に代入しています.関数の内部では,Leap Motion から得られる手指データ(frame)を処理し,ウェブページ上に何らかの出力を書き出すようになっています.このような関数(leapFunc)を Leap.loop() で登録することで,フレームごとの手指データを引数として leapFunc() が呼び出されるようになります.
上のプログラムを見ると,frame データには hand データの配列が含まれていて,frame.hands[i] で読み出せることがわかります.配列の要素数は frame.hands.length で知ることができます.また,hand データには,type や palmPosition などのデータが含まれていて,type は文字列("left", "right"),grabStrength は数値(にぎり具合: 0〜1),palmPosition は3つの数値からなる配列(3次元座標)となっています.roll() は手のひらの Z 軸まわりの回転,pitch は X 軸まわりの回転,yaw は Y 軸まわりの回転で,これらはメソッド(関数)の形をとっています.
なお,各軸は Leap Motion の中心で直交し,正面(LED の面)から見て右向きが X 軸,上向きが Y 軸,手前向きが Z 軸となります.
「テストページ2」は,すべての指について,先端・第1関節・第2関節などの各関節の位置を,リアルタイムで読み取る例です.hand データや finger データの内容(おもなもの)を下にあげておきます.より詳しい情報は,Leap Motion の "JavaScript SDK Documentation" を参照してください.
- hand データ(frame.hands[i])
- type(右手なら "right",左手なら "left")
- palmPosition[3](手のひらの中心位置)
- palmVelocity[3](手のひらの移動速度 [mm/s])
- palmNormal[3](手のひらの法線方向の単位ベクトル [mm/s])
- stabilizedPalmPosition[3](安定化された palmPosition)
- direction[3](手のひらから指先への単位ベクトル)
- pinchStrength(親指といずれかの指で「つまむ」度合い [0〜1])
- grabStrength(「にぎる」度合い [0〜1])
- sphereCenter[3](手のひらの丸みを表す曲率中心)
- sphereRadius(手のひらの丸みを表す曲率半径)
- timeVisible(連続して見えている時間 [s])
- pitch()(手の X 軸まわりの回転角度 [rad])
- yaw()(手の Y 軸まわりの回転角度 [rad])
- roll()(手の Z 軸まわりの回転角度 [rad])
- fingers[5](finger データの配列)
- fingers.length(fingers の要素数)
- finger データ(frame.hands[i].fingers[j])
- type(0 なら親指,1 なら人差し指,...,4 なら小指)
- tipPosition[3](指先の位置)
- tipVelocity[3](指先の速度 [mm/s])
- dipPosition[3](第1関節の位置)
- pipPosition[3](第2関節の位置)
- mcpPosition[3](指のつけ根の位置;ナックルあたり)
- carpPosition[3](中手骨のつけ根の位置;手首あたり)
- stabilizedTipPosition[3](安定化された tipPosition)
- direction[3](指がさす方向の単位ベクトル)
- extended(指が伸びていたら true,そうでなければ false)
- timeVisible(連続して見えている時間 [s])
「テストページ3」は,4つの基本ジェスチャを読み取る例です.基本ジェスチャとは,サークル(指で空中に円を描くこと),画面タップ(空中で前方をつつくこと),キータップ(空中で下向きに指タップすること),スワイプ(ある方向にすばやく指を動かすこと)の4つです.
ジェスチャの読み取りには,まず leapFunc() を仕込むときに {enableGestures: true} を第1引数として Leap.loop() に与える必要があります.こうすることで,gesture データの配列 frame.gestures[i] を受け取ることができます.gesture データの中身は,およそ以下のとおりです.より詳しい情報は,Leap Motion の "JavaScript SDK Documentation" を参照してください.
- gesture データ(frame.gestures[i])
- type("circle", "keyTap", "screenTap", "swipe" のいずれか)
- state("start" 開始, "update" 途上, "stop" 終了のいずれか)
- type が "circle" の場合
- center[3](描いた円の中心位置)
- radius(描いた円の半径)
- type が "keyTap" または "screenTap" の場合
- position[3](ジェスチャの位置)
- direction[3](ジェスチャの方向)
- type が "swipe" の場合
- position[3](ジェスチャの位置)
- direction[3](ジェスチャの方向)
- speed(ジェスチャの速さ)
「テストページ4」は,画面に向かって手を差し入れるごとに,クロスフェードで写真が入れ替わるというものです.jQuery を使っています.さらに「テストページ5」では,画面に向かって手を差し入れと先に進み,グーにして手前に引くと元に戻ります.