Help us understand the problem. What is going on with this article?

SteamVR1.0のTrackedObjectのindex問題を解決しよう

More than 1 year has passed since last update.

はじめに

SteamVR2.0ではこれしなくてもいいそうです!!!!!!!!!!!!!!!

Unity+SteamVR+FinalIKがあればフルトラなんて簡単に出来るじゃーんと思っていませんか?僕は思っていました。
しかし軽いノリで安請け合いをキメたが最後、無限のねじれと戦う羽目になります。

  • トラッカーと四肢の角度の調整(手首足首がねじれて死ぬ。最悪)
  • トラッカーと四肢の対応(手足がねじれてブエルみたくなって死ぬ。最悪)

僕はこれらの地獄に飲まれて2敗しています。
前者については結構根気が必要なところがありますが、後者についてはSteamVRの仕様が結構な悪さをしてくれちゃってます。
というのも、SteamVRでのオブジェクトとコントローラの対応付けはSteamVRの接続順、となっているらしく、どのトラッカーをどこに割り当てるか?というような対応付けを固定させることがデフォルトでは出来ないみたいです。
というわけで今回は取り敢えずの解決策として、SteamVRの接続順に依存しない、トラッカーのシリアル番号を取得して対応付けを修正する実装を考えてみようと思います。

実装

指定したTrackedObjectに割り当てられたデバイスのシリアルナンバーを取得する

var buffer = new StringBuilder(256);
var error = ETrackedPropertyError.TrackedProp_Success;
SteamVR.instance.hmd.GetStringTrackedDeviceProperty((uint)trackedObject.index, ETrackedDeviceProperty.Prop_SerialNumber_String, buffer, (uint)buffer.Capacity, ref error);
if(error = ETrackedPropertyError.TrackedProp_Success){
    Debug.Log(buffer.ToString());
}

これでbufferにtrackedObjectのserialNumberが格納されます。

指定したTrackedObjectのindexを設定する。

指定したTrackedObjectにindexを割り当てるには、

trackedObject.SetDeviceIndex((int)index);

indexはenumだけどSetDeviceIndexの引数はint指定なので注意です。

これらを組み合わせて特定のデバイスに割り当てられるindexを固定する

全てのTrackedObjectに対しシリアルナンバーを取得し、指定されたシリアルナンバーだったらそのTrackedObjectのindexを指定のものに変更します。

using System.Text;←追加
using Valve.VR;←追加

public SteamVR_TrackedObject[] trackedObjects;//あらかじめすべてのTrackedObjectを入れておく
public string serialNumberTarget;//割り当て固定対象のシリアルナンバー
public SteamVR_TrackedObject targetObject;//割り当て固定対象のオブジェクト
//つまりserialNumberTargetとtargetObjectが対応づけされる
public void AssignTrackedObject(){
    SteamVR_TrackedObject.EIndex tmp;
    var buffer = new StringBuilder(256);
    var error = ETrackedPropertyError.TrackedProp_Success;
    for(int i = 0; i < trackedObjects.Length; i++){
        SteamVR.instance.hmd.GetStringTrackedDeviceProperty((uint)trackedObjects[i].index, ETrackedDeviceProperty.Prop_SerialNumber_String, buffer, (uint)buffer.Capacity, ref error);
        if(error == ETrackedPropertyError.TrackedProp_Success){
            Debug.Log(buffer.ToString());
            if(buffer.ToString() == serialNumberTarget){
                tmp = trackedObjects[i].index;
                targetObject.SetDeviceIndex((int)tmp);
            }
        }
    }

}

こうすることでindexに依らずシリアルナンバーとオブジェクトを対応付けることができます。

おわりに(不具合…?)

UIでシリアルナンバーを書き換えられるコンフィグ画面を用意しておくと捗りそうです。結構面倒ですね…
低頻度でコントローラのトリガーが反応しないときがあります。現在再現が不可能でよくわからないことになっているのでぜひ手掛かりがある人は教えてください。

utvirtual
VRの普及啓蒙と体験創造を理念として、VR作品の制作・展示、勉強会などを行っているインカレサークル
http://utvirtual.tech/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした