今回から、しばらくの間、Unlimited Handのドライバから取得できるセンサーの値を中心にブログを書いていこうと思います。
まずは、Photo-Reflectorから。

名称からPhoto-Reflectorで感知した照度(単位不明)のようなものを通知していると思われます。

腕を動作させることで、Photo-Reflectorと腕の間の隙間が変わり、Photo-Reflectorで感知された値に変化が発生することで、アプリ側で腕の動きを予測できると考えていると思われます。

なので、この値を読み取るだけで、腕がどのような状態になっているかを判断できるというわけではないようです。
ただ、どのPhoto-Reflectorがどんなユーザアクション時に反応するかの指針がH2L社より提示されています。ただし、Unlimited Handを巻いている(左右)腕によって異なりますので、アプリから感知するときは、ユーザにどちらの腕に巻いているかを提示してもらう必要が出てきそうです。

Photo-Reflectorのポイント(チャンネル)手の動き
チャンネル 0, 1, 2, 3指を曲げる動き
(右手と左手の場合で異なります)
チャンネル 4, 7手首の動き
(右手と左手の場合で異なります)
チャンネル 5, 6手を開く動き, 手首の動き(拡張)
※ H2L社のHP「Input Tech (フォトリフレクタと加速度ジャイロセンサ)」より抜粋

上記のチャンネル番号は以下の写真の番号の部分になります。

Photo-ReflectorでキャリブレーションのサンプルアプリをH2L社が公開していますが、バイナリのみ公開されています(2017.04.10現在)。

キャリブレーションのサンプルアプリはバイナリしか公開されていないので、どのような計算を行っているか不明ですが、「Super Simple Sample Project --Gunshot--」でも指の動きを多少ハンドリングしているので、参考になりそうです。
キャリブレーションを実施している箇所のスクリプトコードを確認したところ、以下のようになっています。
Assets/Scripts/Scripts_RFPSP/Player/InputControl.cs
void Update () {
    /****  Additional Code for UnlimitedHand  ********************************/
    //During the Calibration
    if (PRVARSum == 0) {
        thresholdGuiObj.GetComponent<TextMesh> ().text = "Please lower down your forearm for the calibration.: "+ calibCount + " to 3";
    }  
    //When finished the Calibration of the Sensors for the Hand Movements
    else{
        //thresholdGuiObj.GetComponent<TextMesh> ().text = "Fire Threshold : " + FIRE_THRESHOLD.ToString () + "\nKEY PRESS\'o\':-10 \'p\':+10 to change the Fire Treshold\nFinger Movement SUM: " + PRVARSum.ToString ();
    }


    if(FPSPlayerComponent && !FPSPlayerComponent.restarting){
        //When finished the Calibration of the Sensors for the Hand Movements
        if (angleFlatAve > 30) { 
            selectWeap2Press = true;
            PRCalib = false;
            uhand.updateAngleFlg = false;
            uhand.updatePhotoSensorsFlg = true;
        } 
        //During the Calibration
        else if( 30 >= angleFlatAve ){
            selectWeap2Press = false;    
            uhand.updateAngleFlg = true;        //update the forearm angle values
            uhand.updatePhotoSensorsFlg = true;    //update the sensors' values of the hand movements
            handAngle[0] = uhand.UHAngle[0];    //get the forearm angle values
            handAngle[1] = uhand.UHAngle[1];
            handAngle[2] = uhand.UHAngle[2];

            //calc the average of the forearm angle values
            for(int i =1;i<10;i++){angleFlat[i-1] = angleFlat[i];}
            angleFlat[9] = handAngle [0];
            angleFlatAve = 0;
            for(int i =0;i<10;i++){angleFlatAve += angleFlat[i];}
            angleFlatAve = angleFlatAve/10;
        }


        uPR = uhand.readPhotoSensors();            //read the sensors' values of the hand movements

        //During the Calibration of the sensors' values of the hand movements
        if (PRCalib) {
            for (int i = 0; i < 8; i++) {
                uPRSum [i] += uPR [i];
                uPRAve [i] = uPRSum [i] / count;
            }
            count++;

            if (30 < count) {//reset the count
                for (int i = 0; i < 8; i++) {
                    uPRSum [i] = uPRAve [i];
                }
                count = 1;
                calibCount++;
            }
        } 
        //When finished the Calibration of the Sensors for the Hand Movements
                        : 以下、キャリブレーションの結果を元にゲーム内のプレイヤーを制御している箇所のため省略
        /****  End of the Additional Code for UnlimitedHand  **********************/
                        : 以下、キャリブレーションの結果を元にゲーム内のプレイヤーを制御している箇所のため省略
    }
}

参照しているセンサーのデータはPhoto-Reflectorと角度となります。
銃を発射するときの腕の構えとして、腕の角度が地面から上に30度以上傾けた状態のPhoto-Reflectorの値を平均化し、それを基準値とするキャリブレーションのようです。
以下の箇所で過去10回の腕の傾きの平均を算出(10回以上測定していないときは、傾きは0℃して扱われる)しています。腕の傾きの平均値が30度を超えるまでキャリブレーションを継続します。
        //When finished the Calibration of the Sensors for the Hand Movements
        if (angleFlatAve > 30) { 
            selectWeap2Press = true;
            PRCalib = false;
            uhand.updateAngleFlg = false;
            uhand.updatePhotoSensorsFlg = true;
        } 
        //During the Calibration
        else if( 30 >= angleFlatAve ){
            selectWeap2Press = false;    
            uhand.updateAngleFlg = true;        //update the forearm angle values
            uhand.updatePhotoSensorsFlg = true;    //update the sensors' values of the hand movements
            handAngle[0] = uhand.UHAngle[0];    //get the forearm angle values
            handAngle[1] = uhand.UHAngle[1];
            handAngle[2] = uhand.UHAngle[2];

            //calc the average of the forearm angle values
            for(int i =1;i<10;i++){angleFlat[i-1] = angleFlat[i];}
            angleFlat[9] = handAngle [0];
            angleFlatAve = 0;
            for(int i =0;i<10;i++){angleFlatAve += angleFlat[i];}
            angleFlatAve = angleFlatAve/10;
        }

上記の箇所でキャリブレーションと判断された場合、各Photo-Reflector(⓪~⑦)毎に平均化していきます。
        uPR = uhand.readPhotoSensors();            //read the sensors' values of the hand movements

        //During the Calibration of the sensors' values of the hand movements
        if (PRCalib) {
            for (int i = 0; i < 8; i++) {
                uPRSum [i] += uPR [i];
                uPRAve [i] = uPRSum [i] / count;
            }
            count++;

            if (30 < count) {//reset the count
                for (int i = 0; i < 8; i++) {
                    uPRSum [i] = uPRAve [i];
                }
                count = 1;
                calibCount++;
            }
        } 

キャリブレーションで得たuPRAveをそれぞれのPhoto-Reflectorで取得した値から減算した結果を使用して、ある程度の指の動きが発生したことをハンドリングしています。
ただし、H2L社が公開しているキャリブレーション向けのサンプルアプリは手を閉じた状態、開いた状態、何かをつまんでいる状態とそれぞれ取得しているので、より詳細に指の動きを見る場合は、より細かく取得してあげる必要があるようです。
ただし、実際にUnlimited Handを使用すると分かりますが、ジェルパッドが汚れてくると、粘着性が弱くなり腕を動かすとPhoto-Reflectorと腕の隙間の変化量が違ってくるので腕を固定した状態で指の動きをハンドリングするぐらいが確実かも。。。

コメントの投稿