DEV Community

kurohuku
kurohuku

Posted on

Get controller device index without GetTrackedDeviceIndexForControllerRole()

Overview

  • GetTrackedDeviceIndexForControllerRole() and GetControllerRoleForTrackedDeviceIndex() are deprecated.
  • This guide is for those who want to get the controller's Device Index using another method.
  • Get the controller's Device Index from a Pose action by IVR Input (SteamVR Input).

Deprecated Functions

In a previously SteamVR Overlay tutorial, , I used GetTrackedDeviceIndexForControllerRole() to get the controller's Device Index like this:

var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
Enter fullscreen mode Exit fullscreen mode

However, GetTrackedDeviceIndexForControllerRole() is marked as deprecated in the header file's comment. So, this I try to get the Device Index using IVRInput (SteamVR Input).
Although it's deprecated, it's still used within OpenVR's own code, so personally, I don't see any immediate issues with continuing to use it.

Reference:
https://github.com/ValveSoftware/openvr/blob/master/headers/openvr.h

Create Unity Project

Create a new project. I'm using the following environment:

  • Unity 6.1
  • URP Template

Delete all objects from the scene to make it empty.

Instlal SteamVR Plugin

Install the SteamVR Plugin via the Package Manager.

https://assetstore.unity.com/packages/tools/integration/steamvr-plugin-32647

Controller Binding

Follow these steps to bind controller Poses to actions:

  • Window -> SteamVR Input
  • Select NO fro "Copy Examples"
  • For "ActionSet Name", enter "DeviceIndex" (any name is fine). Select "per hand" mode.
  • Create two Actions: LeftHandPose and RightHandPose.
  • Set the Type of both to "pose".

  • Click "Save and generate".
  • Click "Open binding UI".
  • Click "Create New Binding".

  • Click the "Poses" button.

  • Assign the LeftHandPose and RightHandPose actions to Left Hand Raw and Right Hand Raw respectively.

  • Click "Replace Default Binding" to save it as the default.

If the "Poses" button is not shown

Regarding the "Poses" button mentioned above, I've not investigated details, but it sometimes doesn't appear.
It should appear if a pose action is defined in actions.json, but I've encountered cases where it didn't show up after several attempts.

If it's not showing, try restarting SteamVR, creating the actions.json file directly, or bringing in actions.json from another app. You might need to try various things.

Script Creation

Create a script named GetControllerDeviceIndex.cs.
Here, we'll get the Device Index for the left-hand controller.

For details on how to get actions and other code specifics, please refer to this tutorial.
The important part starts from where controllerOriginInfo is obtained further down in Update().

using System;
using Valve.VR;
using UnityEngine;

class GetControllerDeviceIndex : MonoBehaviour
{
    ulong actionSetHandle = OpenVR.k_ulInvalidActionSetHandle;
    ulong actionHandle = OpenVR.k_ulInvalidActionHandle;

    void Start()
    {
        var error = OpenVR.Input.SetActionManifestPath(Application.streamingAssetsPath + "/SteamVR/actions.json");
        if (error != EVRInputError.None)
        {
            Debug.LogError("Failed to set action manifest path: " + error);
            return;
        }

        error = OpenVR.Input.GetActionSetHandle("/actions/DeviceIndex", ref actionSetHandle);
        if (error != EVRInputError.None)
        {
            throw new Exception("Failed to get action set /actions/DeviceIndex: " + error);
        }

        error = OpenVR.Input.GetActionHandle("/actions/DeviceIndex/in/LeftHandPose", ref actionHandle);
        if (error != EVRInputError.None)
        {
            throw new Exception("Failed to get action /actions/DeviceIndex/in/LeftHandPose: " + error);
        }
    }

    void Update()
    {
        var actionSetList = new VRActiveActionSet_t[]
        {
            new VRActiveActionSet_t()
            {
                ulActionSet =  actionSetHandle,
                ulRestrictedToDevice = OpenVR.k_ulInvalidInputValueHandle,
            }
        };

        var activeActionSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRActiveActionSet_t));
        var error = OpenVR.Input.UpdateActionState(actionSetList, activeActionSize);
        if (error != EVRInputError.None)
        {
            throw new Exception("Failed to update action state: " + error);
        }

        var result = new InputPoseActionData_t();
        var poseActionSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(InputPoseActionData_t));
        error = OpenVR.Input.GetPoseActionDataForNextFrame(actionHandle, ETrackingUniverseOrigin.TrackingUniverseStanding, ref result, poseActionSize, OpenVR.k_ulInvalidInputValueHandle);
        if (error != EVRInputError.None)
        {
            throw new Exception("Failed to get pose action data: " + error);
        }

        // Passing the action's activeOrigin to GetOriginTrackedDeviceInfo() to get the device that originated the action.
        var controllerOriginInfo = new InputOriginInfo_t();
        var inputOriginInfoSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(InputOriginInfo_t));
        error = OpenVR.Input.GetOriginTrackedDeviceInfo(result.activeOrigin, ref controllerOriginInfo, inputOriginInfoSize);
        if (error != EVRInputError.None)
        {
            Debug.LogError("Failed to get left controller origin info: " + error);
            return;
        }

        // Get the Device Index of the obtained device.
        var deviceIndex = controllerOriginInfo.trackedDeviceIndex;
        Debug.Log($"Left Controller Device Index: {deviceIndex}");
    }
}
Enter fullscreen mode Exit fullscreen mode

Execution

Create an empty Game Object in the scene, add the above component to it, and run the scene.
The Device Index of the left-hand controller will be displayed in the console.

After obtaining the Device Index from the action in this manner, you can use it by passing it as an argument to SetOverlayTransformRelative(), for example.

Top comments (0)