ValveSoftware / openvr

OpenVR SDK
http://steamvr.com
BSD 3-Clause "New" or "Revised" License
6.06k stars 1.27k forks source link

Need help on OpenVr Driver #1644

Open inlet511 opened 2 years ago

inlet511 commented 2 years ago

Sorry to post this here, but I can't find another proper place to ask for help.

My question in short

How to properly setup a driver for a custom single device on steamVR platform?

Backgrounds

What have I done

https://github.com/inlet511/OpenVr_DriverTest I wrote a simple driver for testing, the driver has only one controller, which contains two groups of components, joystick and trackpad. In RunFrame of controller driver, I randomly set x position of joystick and trackpad to -0.5f and 0.5f, y position is always 0.95f, click and touch are both always true.

Questions in Detail:

The code seems to be straight forward, however I have so many questions about input profile and legacy bindings. For simplicity, I am focusing on these three questions for now:

  1. In the page "SteamVR->Devices->Controller Settings->Manage Controller Bindings", there's a Active Controller field, the value of this field seems to depend on which controller steamVR detects first, if so , how can I set up for my device if steamVR detects other device first?
  2. Now I can see my controller in "TEST CONTROLLER" page of SteamVR, but I failed to get my controller working in any vr game. What can I do to make it work in games?
  3. I tried to set my controller's ETrackedControllerRole to TrackedControllerRole_Treadmill and TrackedControllerRole_OptOut which seems to be fair, but in both of these cases, the "TEST CONTROLLER" page doesn't show the input correct(There's some screenshots in my git repository). Am I doing it wrong? Now I have to set it to TrackedControllerRole_LeftHand (or RightHand), but this seems to be conflicting the original controllers.....

I'll be very grateful if someone gives me some ideas, this openvr driver has been torturing me for weeks...thank you very much.

danwillm commented 2 years ago

TrackedControllerRole_Treadmill is the correct controller type for what you're describing. If you've set up the device correctly in openvr (along with the appropriate input profile configuration), then you should see an additional option in the bindings interface to set your device inputs due to being a treadmill.

inlet511 commented 2 years ago

TrackedControllerRole_Treadmill is the correct controller type for what you're describing. If you've set up the device correctly in openvr (along with the appropriate input profile configuration), then you should see an additional option in the bindings interface to set your device inputs due to being a treadmill.

Thank you for replying, I felt TrackedControllerRole_Treadmill would be proper for my device, Then there must be something wrong with my input profile configuration, maybe legacy bindings too. Would you mind take a look at my configurations? I'm posting it below.

inlet511 commented 2 years ago

Additional Info:

Controller Driver's Activate function:

EVRInitError ControllerDriver::Activate(uint32_t unObjectId)
{
    driverId = unObjectId; //unique ID for your driver

    PropertyContainerHandle_t props = VRProperties()->TrackedDeviceToPropertyContainer(driverId); //this gets a container object where you store all the information about your driver

    VRProperties()->SetStringProperty(props, Prop_InputProfilePath_String, "{example}/input/controller_profile.json"); //tell OpenVR where to get your driver's Input Profile
    VRProperties()->SetInt32Property(props, Prop_ControllerRoleHint_Int32, ETrackedControllerRole::TrackedControllerRole_Treadmill); //tells OpenVR what kind of device this is
    VRProperties()->SetBoolProperty(props, Prop_NeverTracked_Bool, true);
    VRProperties()->SetStringProperty(props, Prop_SerialNumber_String, "example_controler");
    //VRProperties()->SetInt32Property(props, Prop_Axis0Type_Int32, k_eControllerAxis_TrackPad);
    //VRProperties()->SetInt32Property(props, Prop_Axis2Type_Int32, k_eControllerAxis_Joystick);
// 
    VRDriverInput()->CreateBooleanComponent(props, "/input/anything/x", &boolHandle);

    VRDriverInput()->CreateScalarComponent(props, "/input/joystick/x", &joystickXHandle, EVRScalarType::VRScalarType_Absolute, EVRScalarUnits::VRScalarUnits_NormalizedTwoSided);
    VRDriverInput()->CreateScalarComponent(props, "/input/joystick/y", &joystickYHandle, EVRScalarType::VRScalarType_Absolute,EVRScalarUnits::VRScalarUnits_NormalizedTwoSided); 
    VRDriverInput()->CreateBooleanComponent(props, "/input/joystick/touch", &joyStickTouchHandle);
    VRDriverInput()->CreateBooleanComponent(props, "/input/joystick/click", &joyStickClickHandle);

    VRDriverInput()->CreateScalarComponent(props, "/input/trackpad/y", &trackpadYHandle, EVRScalarType::VRScalarType_Absolute,EVRScalarUnits::VRScalarUnits_NormalizedTwoSided);
    VRDriverInput()->CreateScalarComponent(props, "/input/trackpad/x", &trackpadXHandle, EVRScalarType::VRScalarType_Absolute,EVRScalarUnits::VRScalarUnits_NormalizedTwoSided); 

    VRDriverInput()->CreateBooleanComponent(props, "/input/trackpad/touch", &trackpadTouchHandle);
    VRDriverInput()->CreateBooleanComponent(props, "/input/trackpad/click", &trackpadClickHandle);

    return VRInitError_None;
}

controller_profile:

{
  "jsonid": "input_profile",
  "controller_type": "example_controller",
  "legacy_binding": "{example}/input/legacy_bindings_example.json",
  "device_class" : "TrackedDeviceClass_Controller",
  "input_bindingui_mode": "single_device",
  "input_bindingui_left": {
        "image": "{example}/icons/game_controller.svg"
  },
  "should_show_binding_errors": true,
  "input_source": {
    "/input/joystick": {
      "type": "joystick",
      "click": true,
      "touch": true,
      "binding_image_point": [0,0]
    },
    "/input/trackpad" : { 
        "type" : "trackpad",
        "binding_image_point" : [ 0, 0 ],
        "force" : false,
        "click" : true,
        "touch" : true
    }
  }
}

Legacy Binding json:

{
   "bindings" : {
      "/actions/legacy" : {
      "haptics" : [
         ],
     "poses" : [
     ],
     "sources" : [
        {
           "inputs" : {
              "position" : {
                 "output" : "/actions/legacy/in/left_axis0_value"
              },
              "click":{
                  "output" : "/actions/legacy/in/left_axis0_press"
              },
              "touch":{
                  "output" : "/actions/legacy/in/left_axis0_touch"
              }
           },
           "mode" : "trackpad",
           "path" : "/user/hand/left/input/trackpad"
        },
        {
           "inputs" : {
              "position" : {
                 "output" : "/actions/legacy/in/left_axis0_value"
              },
              "click" :{
                  "output": "/actions/legacy/in/left_axis0_press"
              },
              "touch":{
                  "output" : "/actions/legacy/in/left_axis0_touch"
              }
           },
           "mode" : "joystick",
           "path" : "/user/hand/left/input/joystick"
        }
     ]
      }
   },
   "category" : "legacy",
   "controller_type" : "example_controller",
   "description" : "Legacy mapping for example",
   "name" : "Legacy_Binding_Example",
   "options" : {
      "mirror_actions" : false,
      "returnBindingsWithLeftHand" : true,
      "simulated_controller_type" : "none"
    }
}
MichauCorp commented 1 year ago

Hello, I might be late but I wanted to ask if you managed to solve it.

I am currently working on a very similar project of my own, featuring a locomotion device, and I am struggling to make it work properly.

I used this driver as a template: https://github.com/finallyfunctional/openvr-driver-example I only slightly modified it to get input from a port, and move the joystick accordingly.

Currently, it works perfectly for legacy binding games like vrchat, but anything else just doesnt move. Since virtually our drivers are identical in how they output, i was hoping you might have some way to solve this, cause if you do it would be an enormous help.

thx in advance :)