ValveSoftware / openvr

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

Games attaching Controllers to treadmill role #1077

Open kaplat opened 5 years ago

kaplat commented 5 years ago

Hello,

I am working on a custom driver for a treadmill device and my driver is working fine for a bunch of games.

In PavlovVR I have a problem though. In my opinion the game assigns the first two devices that are of type vr::TrackedDeviceClass_Controller to the left and right hand. This is a problem for my driver, as my treadmill (vr::TrackedDeviceClass_Controller with treadmill role) always registers before the vive controllers and therefore the treadmill is assigned to one of the hands. Now my questions:

1) Is my binding of the treadmill false? 2) I use alwaysActive=true and that is why my treadmill is always assigned before the controllers. Is there a way to activate the treadmill after the controllers? Is there a way to activate the treadmill without using alwaysActive=true at all? 3) Has anybody else had this problem and can point me in the right direction to fix it? Or is it a game problem?

Thanks in advance for all answers. I would really appreciate the help.

peroht commented 5 years ago

Yes, you are not alone :)

This is a problem with applications written in Unreal. The implementation of openvr in Unreal is lagging behind. I am not an Unreal developer but from what I see there is no support for other controller types than this, (I have not accessed the source code, only looking at the api docs on the homepage):

http://api.unrealengine.com/INT/API/Plugins/SteamVR/ESteamVRTrackedDeviceType/index.html

enum ESteamVRTrackedDeviceType { Controller, TrackingReference, Other, Invalid, }

while openvr defines these classes and types:

https://github.com/ValveSoftware/openvr/blob/823135df1783009cb468d0fc4190816254f7687d/headers/openvr_driver.h#L189

enum ETrackedDeviceClass { TrackedDeviceClass_Invalid = 0, // the ID was not valid. TrackedDeviceClass_HMD = 1, // Head-Mounted Displays TrackedDeviceClass_Controller = 2, // Tracked controllers TrackedDeviceClass_GenericTracker = 3, // Generic trackers, similar to controllers TrackedDeviceClass_TrackingReference = 4, // Camera and base stations that serve as tracking reference points TrackedDeviceClass_DisplayRedirect = 5, // Accessories that aren't necessarily tracked themselves, but may redirect video output from other tracked devices TrackedDeviceClass_Max };

https://github.com/ValveSoftware/openvr/blob/823135df1783009cb468d0fc4190816254f7687d/headers/openvr_driver.h#L203

/* Describes what specific role associated with a tracked device / enum ETrackedControllerRole { TrackedControllerRole_Invalid = 0, // Invalid value for controller type TrackedControllerRole_LeftHand = 1, // Tracked device associated with the left hand TrackedControllerRole_RightHand = 2, // Tracked device associated with the right hand TrackedControllerRole_OptOut = 3, // Tracked device is opting out of left/right hand selection TrackedControllerRole_Treadmill = 4, // Tracked device is a treadmill TrackedControllerRole_Max = 4 };

From my experiences many Unreal games filter out controllers based on index - just like you say. The problem here is that since the treadmill driver is of the type "controller" internally there is no way to distinguish between the hand controller and the treadmill controller - unless the game developer has used some logic to filter out on e.g. device manufacturing strings. Thus your treadmill device driver might get an index of 1 and then the game belives that the device with an index 1 should be the hand controller - and then you have the problem you describe. Sadly.

If you follow some earlier threads you'll find that it was possible to overwrite values on one device from another devices. But the official way forward is to do exactly as you do; write a device driver and the the user use the SteamVR Input UI to remap controllers/buttons as they want.

From my experiments the Vive pucks correspond to the class TrackedDeviceClass_GenericTracker while a treadmill device is of the class TrackedDeviceClass_Controller (same as the hand controllers). Related to the ETrackedControllerRole I see no such corresponding definition in Unreal.

Maybe you have more knowledge and access to the source code and can dig deeper?

kaplat commented 5 years ago

Hi Peter,

thanks for your reply. I am also not an Unreal developer, so i have no access to the source code.

I worked on my driver a bit more though and some things changed. I am now able to register the controllers to the hands first and then add the treadmill. So in Pavlov i have the two controllers registering to the hands and my treadmill is separate. Movement still does not work though, as it does not take any input of my treadmill. Is Pavlov working for your treadmill device if you dont mind me asking?

peroht commented 5 years ago

Thats nice you got it working. Yes I've got it running with e.g. Pavlov by making sure our device is not added until after the normal controllers have been powered on and have numbers assigned to them.

Have you managed to set the correct properties for the buttons you need in your driver (similar to how you set your string properties such as device manufacturer/serial nr)? Also did you enable scalar components for the trackpad axis?

CybershoesVR commented 5 years ago

Hi kaplat,

the workaround we currently use (in DoomVR) is to start SteamVR by pushing the Menu Button on each Wand. So when SteamVR shows up the wands are already there and are assigned lower device numbers. Our driver waits for several seconds before registering the treadmill device.

It would be nice to somehow guarantee that either the treadmill device will always receive a higher 'tid' than the wands or that the wands will always have lower 'tid's.

Maybe there are other workarounds that work better.

peroht commented 5 years ago

I believe there is no way for us developers to assign specific numbers/higher number to the drivers/devices. This is handled by the system itself. So for now it seems to be a case thta we have to ensure the wands have been started before enabling the driver. This seems to be very sensitive at the moment for applications built with Unreal Engine.

peroht commented 4 years ago

@kaplat @CybershoesVR have anyone of you looked into using this yet?

static const char * const k_pch_Driver_LoadPriority_Int32 = "loadPriority";

CybershoesVR commented 4 years ago

Nope, but this sounds like a nice hint! Assuming this works for you... thanks!

kaplat commented 4 years ago

I have also not looked at this.

peroht commented 4 years ago

I have not looked into it either, just wondered if you've tried it and if it made any magic in your setups :) Since having to do the workaround of starting the wands always first is a source of error.

I hope to give it a try in a couple of weeks.

nickos64252 commented 3 years ago

Hello,

I am working on a driver for a treadmill (KatWalk Mini). I tried to use the sample driver from openvr git. It worked, but I do not know what to modify to use a treadmill (or just not use a hmd). It looks if I delete the hmd part, the controller only is not showing.

Could someone provide me basic code for (generic) treadmill (I will do the connection to my treadmill) ? Or at least give me some hint, some of you have already created a treadmill driver from what I see.

Thank you

Nicolas

nickos64252 commented 3 years ago

Hello @peroht @kaplat and @CybershoesVR ,

@kaplat How did you manage to register your treadmill after the controllers.

I created a driver for a treadmill. I used TrackedDeviceClass_Controller with a right or left hand role. I can see data are updated (in SteamVR Controller test window), but, as you said, my treadmill driver is connected first then take the place of one of the controllers.

If I use a treadmill role, my device appears in SteamVR at right. But in the SteamVR Controller Test window, my data (trackpad) is not updated.

I created a trackpad and update values in RunFrame function. I can see with any role, this function is called and my data are read, but they not appear in SteamVR.

Have you used a treadmill role ? When I change the role, is there something in a json to change ?

Hope you could help as you all developped treadmill driver.

Thanks

Nicolas

andreaskern commented 3 years ago

@nickos64252 I wait one second before registering the treadmill device. It's a workaround but it does work for Doom.

For the other issues you have mentioned, you should create separate issues for each of them.

nickos64252 commented 3 years ago

@nickos64252 I wait one second before registering the treadmill device. It's a workaround but it does work for Doom.

For the other issues you have mentioned, you should create separate issues for each of them.

How do you wait one second ? I tried adding a Sleep in Init of CServerDriver but it waits . Have you done a thread ?

Regards

Nicolas