I am working with a Vive Pre (devkit) and I have most everything working the way I want it to. However I am wondering how do I refer to or even know which motion controller is which? From what I can tell the headset is ALWAYS assigned first into a list, and the others are seemingly randomly assigned.

So how do I differentiate between the two or refer to one separately?


C++ and OpenVR Solution:

You can use IVRSystem::GetTrackedDeviceProperty for this exact purpose and everything you want to know about a tracked device/controller:

TrackedPropertyError error;
int32_t controllerRole;

for (auto i = 0; i < numTrackedControllers; i++)
    controllerRole = GetInt32TrackedDeviceProperty(i, ETrackedDeviceProperty::Prop_ControllerRoleHint_Int32, &error);

    if (controllerRole == ETrackedControllerRole::TrackedControllerRole_RightHand)
        // right hand controller
    else if (controllerRole == ETrackedCOntrollerRole::TrackedControllerRole_LeftHand)
        // left hand controller
        // neither

Unity and SteamVR Solution:

For the absolute right and left controllers: The SteamVR class has the string GetStringProperty(ETrackedDeviceProperty prop) and string GetStringProperty(ETrackedDeviceProperty prop) methods in addition to the ValveVR methods in the openvr_api.cs file from OpenVR.

For the controllers currently in the right and left hands relative to the HMD using the Unity SteamVR scripts (pardon what may be inaccurate C#):

int rightIndex = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Rightmost);
int leftIndex = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Leftmost);

SteamVR_Controller.Device rightDevice = SteamVR_Controller.Input(rightIndex);
SteamVR_Controller.Device leftDevice = SteamVR_Controller.Input(leftIndex);
  • \$\begingroup\$ Well on the Unity side of things I've done some digging. I found a file called SteamVR_ControllerManager.cs. However I'm not really following how it works entirely. I'm not really seeing how I would refer to (or identify) one controller or the other in code. For example here is my controller script I cooked up with some tutorials. All it does is get the position of a finger on the touch pad. The problem is that I have no way of telling which touch pad is being touched. How would I differentiate the two here? \$\endgroup\$ – Sie Jul 16 '16 at 15:52
  • \$\begingroup\$ Whenever the controller state changes it calls OnTrackedDeviceRoleChanged which calls Refresh which sets the right and left controller indices with leftIndex = system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand); rightIndex = system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand); \$\endgroup\$ – user5665 Jul 16 '16 at 19:10
  • \$\begingroup\$ In your example code it appears you are only using one tracked object. \$\endgroup\$ – user5665 Jul 16 '16 at 19:12
  • \$\begingroup\$ I was thinking. You are right. The script must attach to BOTH controllers. So I suppose I could have a manager script/object somewhere that tracks which controller is which at any given time. Could that work? \$\endgroup\$ – Sie Jul 16 '16 at 19:57
  • \$\begingroup\$ I've just added some code to my answer for finding the positionally right and left controllers using SteamVR_Controller.Device, that you might want to replace your WandController.{device|controller} with to capture both left and right inputs. \$\endgroup\$ – user5665 Jul 16 '16 at 20:09

At the time of writing, the other C++ solution is no longer correct; there is now a dedicated function for this:

vr::ETrackedControllerRole role = GetControllerRoleForTrackedDeviceIndex(device_index);

where role is one of vr::TrackedControllerRole_Invalid, vr::TrackedControllerRole_LeftHand or vr::TrackedControllerRole_RightHand.

Conversely if you want the id for the left or right controller, you can get it with

vr::TrackedDeviceIndex_t device_index = GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);

I'm sure it's the same in other language bindings.

  • \$\begingroup\$ Yes the role based approach is the cleaner way to manage your tracked devices. You can also look at mapping serialnumbers to roles to persist across sessions and manage binding more consistently that way. Take at look at the Vive Input Utility Unity plugin for such a design. \$\endgroup\$ – dljava Dec 5 '17 at 6:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.