Search Unity

Question OpenXR -- Is it no longer possible to get descriptive device names?

Discussion in 'VR' started by colinleet, Feb 4, 2021.

?

Does your code need to know headsets your player is using?

  1. Yes

    240 vote(s)
    92.3%
  2. No

    16 vote(s)
    6.2%
  3. I liked how thing were in 2020.

    3 vote(s)
    1.2%
  4. Oh cool the hacked here might be actually work great for me!

    1 vote(s)
    0.4%
  1. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    I'm struggling with how to get descriptive device names in OpenXR -- this is specifically to identify which HMD the player is using to load the correct visual controller models for their headset.

    With OculusSDK this code would return a useable name:

    Code (CSharp):
    1.  
    2. // Get Headset Name
    3. UnityEngine.XR.InputDevice headDevice = InputDevices.GetDeviceAtXRNode(XRNode.Head);
    4. string hmdName = headDevice.name;
    5.  
    I know there isn't really any good method out there to find out what each headset's manufacturer internally names their piece of hardware -- making discovering all of the names for a headsets a major headache unless you already own all of them. From a variety of sources I was able to gather this list which worked well before I switched to OpenXR:

    Code (CSharp):
    1.  
    2. /// <summary>
    3. /// Static utility class contains the names of all the HMDs (I know of).
    4. /// </summary>
    5. public static class KnownHMDNames {
    6.     // Strings may slightly differ, e.g. "Vive. MV" or "Vive MV.", and not just per OS
    7.     public const string model_vive = "Vive MV";
    8.     public const string model_vive_pro = "VIVE_Pro MV";
    9.     public const string model_lenovoExplorer = "Lenovo Explorer";
    10.     public const string model_hpWindowsMixedReality = "HP Windows Mixed Reality Headset";
    11.     public const string model_samsungOdyssey = "Samsung Windows Mixed Reality 800ZAA";
    12.     public const string model_acer = "Acer AH100";
    13.     public const string model_rift_cv1 = "Oculus Rift CV1";
    14.     public const string model_rift_s = "Oculus Rift S";
    15.     public const string model_quest = "Oculus Quest";
    16.     public const string model_quest_2 = "Quest";
    17. }
    18.  
    Now whenever I run the same command as above this is what I get back (for the CV1 and Quest2):

    "Head Tracking - OpenXR" ผ(•̀_•́ผ) ( ఠ ͟ʖ ఠ) ( ͡ಠ ʖ̯ ͡ಠ) .... Ugh ...

    Anyone have a better method for finding out what device is attached in OpenXR?

    Or even in the XRManagement parent plugin?

    Being hardware agnostic is fantastic and all but this is taking it too far.

    Am I up a creak without a paddle here? ... This can't be a rare thing to need to know.
     
    AJMHPC likes this.
  2. Cloudwalker_

    Cloudwalker_

    Joined:
    Jan 3, 2014
    Posts:
    140
    bump
     
    AJMHPC likes this.
  3. soleron

    soleron

    Joined:
    Apr 21, 2013
    Posts:
    582
    I understand the whole idea about OpenXR is that this is not necessary. Every maker has made sure that at least their newer devices and latest version of their platforms are somewhow OpenXR compliant. OpenXR does the matching/translation.
     
  4. StayTalm_Unity

    StayTalm_Unity

    Unity Technologies

    Joined:
    May 3, 2017
    Posts:
    182
    Outside of the VivePro, the headsets arn't as easily identifiable. They run totally independent of the Input APIs, and while you can check the Runtime (Windows or Oculus or SteamVR), I don't think there is a guaranteed way to get headset model. I could be wrong, happy to be corrected, it's a long, changing spec.

    Since it sounds like you are using this to detect controller model, you can still identify the controller type (well, potentially simulated controller type, because of how OpenXR works). The names are ripped right out of this section: https://www.khronos.org/registry/Op...rspec.html#semantic-path-interaction-profiles
    You may need to be flexible but here are some examples: "Oculus Touch Controller OpenXR", "Windows MR Controller OpenXR", "Index Controller OpenXR", "HTC Vive Controller OpenXR". Do a code search for kDeviceLocalizedName in the package and you can find the others ones currently available (all based on the public OpenXR specification).

    You can use InputDevice.GetDevices to get an initial list on startup of connected devices, and then register to InputDevices.deviceConnected to get updates to catch controllers that connect late. Keep in mind a device like the Quest, where the user can switch between hands and controllers at any time, so be ready to drop the current model selection and move to a new one.

    Here is a quick example using the InputDevices API.

    Code (CSharp):
    1.         void OnEnable()
    2.         {
    3.             InputDevices.deviceConnected += DeviceConnected;
    4.             List<InputDevice> devices = new List<InputDevice>();
    5.             InputDevices.GetDevices(devices);
    6.             foreach(var device in devices)
    7.                 DeviceConnected(device);
    8.         }
    9.  
    10.         void OnDisable()
    11.         {
    12.             InputDevices.deviceConnected -= DeviceConnected;
    13.         }
    14.  
    15.         void DeviceConnected(InputDevice device)
    16.         {
    17.             // The Left Hand
    18.             if ((device.characteristics & InputDeviceCharacteristics.Left) != 0)
    19.             {
    20.                 //Use device.name here to identify the current Left Handed Device
    21.             }
    22.             // The Right hand
    23.             else if ((device.characteristics & InputDeviceCharacteristics.Right) != 0)
    24.             {
    25.                 //Use device.Name here to identify the current Right Handed Device
    26.             }
    27.         }
    I want to push people to use the Input System, it's more complex, but also more flexible and powerful. In that case there are similar APIs, such as InputSystem.GetDevice(CommonUsages.LeftHand) and InputSystem.onDeviceChange for a callback on device state changes. Input System devices also have a .name property, and also have a class type, so you can do
    if(device is MixedRealityController)
    type coding to identify actual device types.

    Hopefully this gets you back up and working.
     
  5. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    This looks good for differentiating fully separate brands of headsets, but it doesn't resolve the issue of determining within brands, e.g. the Oculus Rift CV1 controller from Quest2 / RiftS in OpenXR, as the controller are all named "Oculus Touch Controller OpenXR".
     
    Last edited: Feb 21, 2021
  6. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    For raw vr specific inputs and outputs (like vibration) yes, but that's it.

    You'll still need models for each controller if you'll want them in your game. Plus the logic for how to pose the player's avatar hands correctly for those controllers generally differs with the varying inputs on different controller/where that input is located. OpenXR minimized duplicate functionality, it can't necessarily eliminate it.

    Another area which having deceptive full headset name is useful is automatically picking which microphone is for the connected HMD (especially if several mics/webcams/hmds are connected).
     
  7. StayTalm_Unity

    StayTalm_Unity

    Unity Technologies

    Joined:
    May 3, 2017
    Posts:
    182
    In OpenXR, this information is purposely obscured, even from us. It's unfortunate, but the Oculus Touch Gen 1 & 2 are the only controllers in the spec currently that cannot be identified uniquely. However, from a quick scan it looks like all other commercial controllers (that I am aware of at least) can be identified by their name, or by going direct to the OpenXR APIs and getting the active interaction profile path. And there are continually new extensions adding new controllers that can be used. The new action based input patterns used in OpenXR have some good intentions behind them. It helps enable accessibility features and user customization without extra developer work, as well as reducing dev costs in porting to different platforms. But that added abstraction makes it more difficult to 100% identify exactly what hardware is being used.

    When it comes to controller models keep an eye on this: https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_MSFT_controller_model
    This is coming to the general OpenXR standard, and as it gains traction amongst other vendors will provide a consistent way for the runtime to give you the controller model instead of trying to discern it. Since we expose most of the underlying OpenXR APIs and handles, a smart user may be able to beat us to the punch on implementing the standard as listed.
     
    glenneroo, Threeyes and colinleet like this.
  8. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    Omg that is going to be useful and amazing... "Downloading" the controller models directly from the plug-in API at runtime...

    I had read on a few posts about the old Oculus SDK (pre XR management plugins) people signing up and using the omnibus Oculus package just to get controller models "showing up and running" in a few lines of code...

    1) Do you happen to know if that was the case?

    It never made any sense to me so I ignored it... I had only every used the package it when just the Rift 1 was released like 4 years ago, back then they already provided a fully animated and rigged controller model in the SDK... Which is why I was kinda shocked when they didn't release something of similar completeness/quality for the later controllers.

    (Just a model w/o animations for the Rift 2/Quest 1. And for the Quest 2 just a model with a single animation you have to cut apart into dozens of clips and then restitched back together in an animator to make it useful...)

    2) Is there any place that describes how those models are provided (model file formats/object setups/animator controller scripts)?

    I would imagine something like an asset bundle would be necessary, but that wouldn't work between various other engines. It would have to be in a standard format like fbx... But I haven't heard of any system that can export controlling scripts for "Animator" like controllers cross engines... Just animations and skeletons/meshes.
     
    Last edited: Oct 20, 2021
  9. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    Ok I think I've found a way of determining Rift 1 vs 2, it's not a huge difference but the aspect ratio of the per eye resolution for Rift 1 is 0.9 (1080 / 1200) while the aspect ratio for the Rift 2 is 0.8889... (1280 / 1440).

    Edit (June 2021): Ok using the resolution aspect ratio has other problem I had not encountered when I originally wrote this, see AndreasWang's post below for details.

    I think that plus the above method for using device controller type should (95%?) fix the identifying HMD problem for me.
     
    Last edited: Jun 14, 2021
  10. Incode

    Incode

    Joined:
    Apr 5, 2015
    Posts:
    78
    At least for Oculus devices it may be possible to differentiate models using OVR. The below code should differentiate between Quest and Quest 2.

    Code (CSharp):
    1. OVRPlugin.SystemHeadset headset = OVRPlugin.GetSystemHeadsetType();
    2. if(headset==OVRPlugin.SystemHeadset.Oculus_Quest){
    3. // Quest 1 stuff here
    4. }else if (headset==(OVRPlugin.SystemHeadset.Oculus_Quest+1)){
    5. // Quest 2 stuff here
    6. }
     
  11. Akravator

    Akravator

    Joined:
    Aug 8, 2017
    Posts:
    19
    just want to track this forum
     
  12. JudahMantell

    JudahMantell

    Joined:
    Feb 28, 2017
    Posts:
    476
    This is really frustrating because I need the actual controller models, not goofy looking hands for my application, and it seems like there's no way to show the proper controllers!
    My other thought-of solution is to create a generic-looking controller that shows the common buttons and inputs across all controller models (touchpad/thumbstick, primary button, trigger, grip), but I can't think of a design that would work.
    Any ideas?
     
  13. AndreasWang

    AndreasWang

    Joined:
    Jul 31, 2019
    Posts:
    23
    I've attempted to use aspect ratios based on XRSettings.eyeTextureWidth and XRSettings.eyeTextureHeight as a means to identify the different types of oculus controllers, but it has its fair share of issues. The output of those two variables will change depending on the amount of supersampling that the user has applied through SteamVR (or other runtimes). It also seems like the scaling isnt quite uniform so you end up with slightly different aspect ratios for the same headset as the user changes their resolution multiplier.

    You could potentially have a threshold that you use to test for specific aspect ratios but this feels like a very shaky solution that could result in an incorrect HMD type choice as it would need to be used for several vendors. If there is some way to fetch the base resolution of HMD instead of scaled ones then that might have helped.

    Without the ability to determine the controller type, we cannot implement things like custom controller models (for example rift/quest controllers without the tracking rings at the front) and controller specific tooltips which is an requirement in my case :(
     
    Akravator and colinleet like this.
  14. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    Bumping to see if anyone has any workarounds to figure out device type, is an important feature for us.
     
  15. AndreasWang

    AndreasWang

    Joined:
    Jul 31, 2019
    Posts:
    23
    I've given up on attempting to automatically figure out controller/hmd type for now and instead opted to give the user a desktop dropdown where they choose the controller type. It's far from ideal, but it's better than nothing while we wait for the controller model related extensions to be implemented into the OpenXR spec. Hopefully it will get a bit easier to work with whenever that happens :)
     
    colinleet likes this.
  16. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    This is the exact same thing I've fallen back to doing.
     
  17. Dark-Table

    Dark-Table

    Joined:
    Nov 25, 2008
    Posts:
    315
    Turns out the HP Reverb G2 controllers report themselves to OpenXR as "Oculus Touch Controller OpenXR." Is there a way to determine the current OpenXR runtime in use? At least that way if you knew you were in a Windows Mixed Reality OpenXR session you'd know to load the Reverb G2 model.

    Otherwise, I'll have to resort to the hack of measuring the distance between the grip pose and the aim pose (yeah). This doesn't work to distinguish Oculus controllers apart, as far as I can tell, but the Reverb G2 has a different aim pose from the "real" Oculus Controllers.
     
  18. Dark-Table

    Dark-Table

    Joined:
    Nov 25, 2008
    Posts:
    315
    I just need to get a little rant out of my system.

    With the above hacks I can fairly reliably determine that the OpenXR device is an Oculus device. I can make an educated guess that it's a Quest 2 or not, based on the display's aspect ratio. BUT you have to remember that the HP Reverb G2 also claims it has Oculus Touch controllers. So if the screen's aspect ratio > 0.925 and < 0.975 it's PROBABLY an Oculus Quest. Larger than 0.975 it's PROBABLY an HP Reverb G2. If the screen's aspect ratio is < 0.925 it's PROBABLY a Rift S or Quest 1.

    BUT if Pico (for example) releases an OpenXR runtime, dollar to donuts it's going to report its controllers as Oculus Touch. Now you've got to figure out some quirk in the reported specs that let you uniquely identify the Pico. Maybe it's aim pose is also a little different from the Quest's?

    Further, since you can run OpenXR apps in SteamVR with any of the above headsets, you need yet another way to identify the headset/controllers, because now you can't just rely on the name of the current OpenXR runtime and the name of connected controller.

    If OpenXR is the future interface for the whole AR/VR industry, how are we going to deal with this moving forward? Say for example, I want to load low res assets for the Quest 1 and higher res assets for the Quest 2 (this isn't just about displaying correct controller models for everyone) how do I reliably handle that with OpenXR in its current state?

    This idea that developers don't need to know about the device their application is running on is bananas.

    This would be like if the people developing the JavaScript spec decided that nobody needs access to the userAgent string anymore. Any browser-specific quirks now have to be solved by browser vendors implementing extensions. So if div tag alignment is a little off in Microsoft Edge, just send a support request to Microsoft and they'll consider it for a fix in a future version of their browser, or not.

    OpenXR simply needs to give us access to a string that tells us device model, the system its running on, and let developers get work done.
     
  19. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    Have you reported this as a bug yet?

    It might take them forever to fix it but that sounds like a really easy bug to address for whoever coded it.

    Swapping the controllers in and out actually isn't too bad, I do it using the addressable system and it can swap out the controllers in a fraction of a second with no noticeable frame jitter.

    It's basically just spawning in a new visual model which I then set as a child of a "empty holder" which I have spawning in as the "visual controller" in the standard action based controller. (I'm actually using a slightly customized one in this photo since I use my own abstraction layer on top multiple of Unity's default input processing system.)

    Customized Action Based Controller With Blank Model Prefab.jpg

    At runtime I just check a user setting I have for which controller model is selected then I spawn in the controller like this:

    Controller In Hierachy With Spawned In Conroller For Quest 2.jpg

    For me I've decided that it's not work weeks for my time of try to hack something better together when the solution can just be addressed by a single dropdown menu.

    <3.

    Um.... A really good solution which doesn't use the names is listed above, I wasn't sure if you read it or not, see:

    That might not get you the exact headset model or runtime, but it should get you the correct type of controller in most cases.
    (Note: I haven't tested this yet.)
     
  20. Dark-Table

    Dark-Table

    Joined:
    Nov 25, 2008
    Posts:
    315
    The problem is this isn't a bug. This is intentional. It looks like every XR controller that has ab/xy button layout with two joysticks is supposed to describe itself to OpenXR as an "Oculus Touch" controller so the running application knows how to map inputs. I think there are probably more controllers that do this, like the Vive Cosmo and Pico Neo 3, but I don't have those headsets to test with.
     
  21. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    Ah that makes perfect sense from an input point of view.
     
  22. ickydime

    ickydime

    Joined:
    Nov 20, 2012
    Posts:
    110
    This is insanely complex
     
    colinleet likes this.
  23. fherbst

    fherbst

    Joined:
    Jun 24, 2012
    Posts:
    802
    @StayTalm_Unity I think its incorrect that OpenXR doesn't provide device/vendor details.

    Looking at OpenXR Explorer (https://techcommunity.microsoft.com.../introduction-to-openxr-explorer/ba-p/2733927), all the data is there –
    xrGetSystemProperties contains systemName, vendorId, and even some info when e.g. running Oculus via SteamVR.

    upload_2021-10-26_14-41-9.png

    upload_2021-10-26_14-41-43.png

    Could this please be added to Unity's OpenXR implementation? Also, is there a workaround to get these values with the current OpenXR dll? From a cursory glance at the source it looks like (some) of the extern calls seem to be implemented but not on the C# side.
     
  24. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    @StayTalm_Unity
    I was just wondering what your thoughts are about what @fherbst posted above, if you've had any time to look it over yet.
     
  25. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    You don't even have that, you have the button layout. See this above:

     
  26. LeFx_Tom

    LeFx_Tom

    Joined:
    Jan 18, 2013
    Posts:
    88
    fherbst likes this.
  27. StayTalm

    StayTalm

    Joined:
    Jul 18, 2017
    Posts:
    2
    Somebody found my personal account :)

    Unfortunately for you, I've moved on from Unity. When I left, I believe @the_real_apoxol was the most knowledgeable for that sort of question. So I tagged him in.

    Best of Luck!
     
  28. hschulte

    hschulte

    Joined:
    Oct 2, 2018
    Posts:
    12
    Thank you for bringing this to the point. It is an unbearable situation. Relying on resolution, refresh rates or other magic values to identify your connected hardware is absolutely nuts! There is no good reason to lock developers out from the most basic information only for the sake of abstraction.

    In our application, we have hardware-specific controller models that we spawn according to the connected hardware. However, the HP Reverb 2 and Vive Focus 3 are both displayed as "Oculus Touch Controller OpenXR". For the Reverb, I was able to identify the device (roughly) using
    OpenXRRuntime.name == "Windows Mixed Reality Runtime"
    which is good enough for my purpose.
    For the Vive Focus 3 this does not work because the runtime is "SteamVR/OpenXR" which all SteamVR devices have in common. So I have to check against the device resolution hoping that no other headset uses the same hardware resolution as the Focus. As far as I can tell, the Focus cannot even be easily distinguished from the OpenXR Explorer.

    upload_2022-2-14_16-17-55.png
     
  29. SuperScience

    SuperScience

    Joined:
    Feb 10, 2016
    Posts:
    17
    Dark table is 100% correct. Sure IN THEORY you shouldn't have to know, but not all controllers are the same!

    Case in point: Despite Meta's dominance, Vive is still about 12% of the market.
    1. Meta and Index controllers have 2 additional buttons per hand.
    2. The Meta Quest's grip button has almost no resistance and can be pressed accidentally very easily. (I think it is moreso a ham-handed attempt to gauge how firmly you're holding the controller.) While for Vive its a functional and useful feeling button that you consciously press.
    3. The Quest's trigger doesn't have a nice break point. Like the grip, the Quest's trigger is simply too loose, so what feels "good" as a hair trigger on the Vive can be pressed almost accidentally on the Quest. So you need to set the "hair trigger' pressure to like 80% while for Vive its like 40%.
    These things mean that - frankly - we need to have branching code paths to make our games equally satisfying using different controllers. If there were some kind of manufacturing standard, where they all had to have the same buttons and the same weights on grips and triggers... then, sure, we wouldn't need to detect. But in this rapidly evolving space, its going to be some time before the "XBox Controller" of the VR world is settled-upon. Until then, we need to make code that can adapt to the peripherals, and to do that, we need to know what peripherals you're using.

    If someone has a surefire solution, please let me know. Until then I guess I'll just have to ask my player at the start of the game and save their choice in settings...
     
    colinleet likes this.
  30. Daniiii

    Daniiii

    Joined:
    Nov 13, 2013
    Posts:
    24
    Bump, currently also struggling with getting the HMD name. At this point, I'm considering just switching back to the SteamVR OpenVR plugin where this was no effort. (as it should be)

    It's insane that we cannot get a simple device name here.
     
  31. fherbst

    fherbst

    Joined:
    Jun 24, 2012
    Posts:
    802
    hschulte, ROBYER1 and Krollr like this.
  32. Javernandez

    Javernandez

    Joined:
    Feb 4, 2014
    Posts:
    5
  33. AfonsoNascimentoVL

    AfonsoNascimentoVL

    Joined:
    Dec 7, 2021
    Posts:
    2
  34. SvenMatusek_CMC-Kiesel

    SvenMatusek_CMC-Kiesel

    Joined:
    Sep 10, 2021
    Posts:
    1
  35. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254
    The reality is that this information is specifically hidden to limit user fingerprinting and empower futureproofing.
    • Fingerprinting, in an app is really a moot point as C# can just read the MAC address, and current windows user name..
    • Futureproofing on the other hand is a valid concern as coding to a specific model means that each time a new VR device is added, you will need to update your app to specifically support that new device or risk it not working.

    While it's nice to show the user their actual equipment, the 'correct' (how dare you want to do something that Khronos says is bad) way of doing it is to iterate the connected device's inputs and dynamically assign event handlers. Unless your Microsoft who managed to add the corporate named XR_MSFT_controller_model to the spec.

    What's needed is a Khronos driven spec change for the MSFT extension to be changed in favor of common vendor support. Granted I don't trust individual vendors to offer appropriately optimized/skin-able models, and the spec doesn't support LOD's for the returned model data.

    That said, @fherbst indicates is that the naming data is avaliable, through the OpenXR Explorer at least so is this a Unity or Khronos group issue.

    ---

    While it sucks for OpenXR, be glad that you don't have to develop for the WebXR offshoot of OpenXR where they specifically call out 'Fingerprinting' as a code smell, and go even further to codify identifiers out as best as they can to limit browser fingerprinting.

    WebXR Spec
    https://www.w3.org/TR/webxr/#fingerprinting-security
     
  36. hschulte

    hschulte

    Joined:
    Oct 2, 2018
    Posts:
    12
    This is a valid point. I would actually be happy being future proof in terms of hardware. However, the data I get from different VR Controllers is not uniform enough to give people a consistent experience right now.

    For example, in our app we have custom controller models for Vive and Oculus-like controllers. But because the spatial data we receive for each device corresponds to a different pose in respect to the real word controller, we have to apply individual offsets for every type of hardware. Otherwise controller models are completely off which is breaking immersion and overall feels low-quality. Maybe I'm missing something obvious here?

    Another example is that every hardware controller has a different interpretation of haptic feedback pulses. What feels right for Oculus might be completely overblown for WMR. Therefore, we have to scale frequency and amplitude values specifically for each device.

    There must be a proper way to deal with these kinds of issues.
     
  37. fherbst

    fherbst

    Joined:
    Jun 24, 2012
    Posts:
    802
    The idea isn't to get the device name to enable functionality in the first place, it's to improve the default, cross-platform, device-agnostic experience when the device is known, for example by tuning color representation and post effects towards known display characteristics.

    Regarding @hschulte 's concerns: if you're getting these hardware differences in OpenXR it would actually be bugs in Unity's OpenXR implementation or the respective vendors platform support – I believe the explicit goal of OpenXR is to abstract exactly these kinds of differences away and give you a reliable pose + haptics, besides other things. (you shouldn't need to know the device names to get matching poses + haptics)

    The way I see it would be that app developers must assume not knowing anything about the device, thus fully staying future-proof, but can (not must, not should) implement device-specific improvements.

    The information is available from OpenXR, it's just Unity not passing it through.
     
  38. thep3000

    thep3000

    Unity Technologies

    Joined:
    Aug 9, 2013
    Posts:
    400
    This is actively being worked on within the OpenXR working group. I don't have a timeline - it's getting pretty close but getting everyone to agree on standards takes a long time.

    This is definitely an area that is under-specified with OpenXR right now - and an area the working group has expressed interest in addressing. I'll try to revive that conversation.

    Rest of the feedback in this thread is all good info for the OpenXR working group for cases where developers feel like they need to know the specific controller - I'll try to get it in front of them. Reality is, the runtime may tell us that the user is using X controller profile but it can be rebound to any piece of hardware under the hood.

    @fherbst Regarding exposing more / missing runtime information - we do expose the instance runtimeName via https://docs.unity3d.com/Packages/c...html#UnityEngine_XR_OpenXR_OpenXRRuntime_name

    While we don't currently expose the other fields you posted from OpenXR explorer - mostly because using them for the usecases described here is an anti-pattern with OpenXR's future-proofing goals - I get that there are holes that OpenXR has which you need to work around. It is possible to get the data by authoring an OpenXR feature. There's a sample shipped with the openxr package called InterceptFeature which can intercept any openxr call - you can follow this pattern to intercept xrGetSystemProperties or any other function and expose the data to c#. https://docs.unity3d.com/Packages/c...tures.html#intercepting-openxr-function-calls. Hope this can help unblock you.
     
    colinleet and hschulte like this.
  39. dsmeathers

    dsmeathers

    Joined:
    Jun 12, 2013
    Posts:
    7
    This is exactly the reason we need it. The displays on different headsets can vary a lot so being able to tune the colour per display is necessary if you really care about visual quality. Of course you'll have a sensible default profile (so future proofing isn't a problem) but being able to detect the most common headsets to present the game in the best possible way is really important.

    This information is being provided by OpenXR, so don't blame them! It's Unity that is deciding not to expose it. You're really not helping us by blocking off parts of the API.

    I've written an OpenXR feature to work around this, and it's identifying my Quest 2 ok. Hopefully it's of use to someone else.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System;
    4. using UnityEngine.XR.OpenXR.Features;
    5. using System.Runtime.InteropServices;
    6. using System.Text;
    7.  
    8. #if UNITY_EDITOR
    9. [UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "Get System Info",
    10.     BuildTargetGroups = new[] { BuildTargetGroup.Standalone },
    11.     Company = "Fireproof Studios",
    12.     Desc = "Feature extension for getting system info.",
    13.     DocumentationLink = "https://docs.unity3d.com/Packages/com.unity.xr.openxr@0.1/manual/index.html",
    14.     Version = "0.0.1",
    15.     FeatureId = featureId)]
    16. #endif
    17. public class OpenXRFeatureSystemInfo : OpenXRFeature
    18. {
    19.     /// <summary>
    20.     /// The feature id string. This is used to give the feature a well known id for reference.
    21.     /// </summary>
    22.     public const string featureId = "com.unity.openxr.feature.example.getSystemInfo";
    23.  
    24.     // delegate for xrGetInstanceProcAddr() https://registry.khronos.org/OpenXR/specs/1.0/man/html/xrGetInstanceProcAddr.html
    25.     unsafe private delegate ulong GetInstanceProcAddrDelegate(ulong instance, StringBuilder procName, IntPtr* procAddr);
    26.     // delegate for xrGetSystemProperties() https://registry.khronos.org/OpenXR/specs/1.0/man/html/xrGetSystemProperties.html
    27.     unsafe private delegate ulong GetSystemPropertiesDelegate(ulong instance, ulong systemId, void* properties);
    28.  
    29.     // XrSystemProperties structure https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrSystemProperties.html
    30.     unsafe struct XrSystemProperties
    31.     {
    32.         public ulong type;      // 64 bit
    33.         public void* next;      // 64 bit
    34.         public ulong systemId;  // 64 bit
    35.         public int vendorId;    // 32 bit
    36.         public fixed byte systemName[XR_MAX_SYSTEM_NAME_SIZE];
    37.         public XrSystemGraphicsProperties graphicsProperties;
    38.         public XrSystemTrackingProperties trackingProperties;
    39.     };
    40.  
    41.     // XrSystemGraphicsProperties structure https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrSystemGraphicsProperties.html
    42.     struct XrSystemGraphicsProperties
    43.     {
    44.         public uint maxSwapchainImageHeight;
    45.         public uint maxSwapchainImageWidth;
    46.         public uint maxLayerCount;
    47.     };
    48.  
    49.     // XrSystemTrackingProperties structure https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrSystemTrackingProperties.html
    50.     struct XrSystemTrackingProperties
    51.     {
    52.         public uint orientationTracking;
    53.         public uint positionTracking;
    54.     };
    55.  
    56.     // https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrStructureType.html
    57.     private const int XR_TYPE_SYSTEM_PROPERTIES = 5;
    58.     private const int XR_MAX_SYSTEM_NAME_SIZE = 256;
    59.  
    60.     private static string SystemName = null;
    61.     private static ulong XrInstance = 0;
    62.     private static ulong XrSystem = 0;
    63.  
    64.     protected override bool OnInstanceCreate(ulong xrInstance)
    65.     {
    66.         XrInstance = xrInstance;
    67.         return base.OnInstanceCreate(xrInstance);
    68.     }
    69.  
    70.     protected override void OnSystemChange(ulong xrSystem)
    71.     {
    72.         XrSystem = xrSystem;
    73.         base.OnSystemChange(xrSystem);
    74.     }
    75.  
    76.     public static string GetHeadsetName()
    77.     {
    78.         if (SystemName == null
    79.             && XrInstance != 0
    80.             && XrSystem != 0
    81.             && OpenXRFeature.xrGetInstanceProcAddr != IntPtr.Zero)
    82.         {
    83.             GetInstanceProcAddrDelegate getInstanceProcAddr = Marshal.GetDelegateForFunctionPointer<GetInstanceProcAddrDelegate>(OpenXRFeature.xrGetInstanceProcAddr);
    84.             unsafe
    85.             {
    86.                 // call xrGetInstanceProcAddr() to get the address of the xrGetSystemProperties() function
    87.                 IntPtr xrGetSystemPropertiesAddr;
    88.                 ulong result = getInstanceProcAddr(XrInstance, new StringBuilder("xrGetSystemProperties"), &xrGetSystemPropertiesAddr);
    89.  
    90.                 GetSystemPropertiesDelegate getSystemPropertiesAddr = Marshal.GetDelegateForFunctionPointer<GetSystemPropertiesDelegate>(xrGetSystemPropertiesAddr);
    91.                 if (xrGetSystemPropertiesAddr != null)
    92.                 {
    93.                     // call xrGetSystemProperties()
    94.                     // the properties structure needs to have the type initialised otherwise xrGetSystemProperties() fails
    95.                     XrSystemProperties properties;
    96.                     properties.type = XR_TYPE_SYSTEM_PROPERTIES;
    97.                     result = getSystemPropertiesAddr(XrInstance, XrSystem, &properties);
    98.  
    99.                     // convert the name from an array of bytes to a c# string
    100.                     SystemName = "";
    101.                     for (int charIndex = 0; charIndex < XR_MAX_SYSTEM_NAME_SIZE; charIndex++)
    102.                     {
    103.                         if (properties.systemName[charIndex] == 0)
    104.                         {
    105.                             break;
    106.                         }
    107.                         SystemName += ((char)properties.systemName[charIndex]);
    108.                     }
    109.                 }
    110.             }
    111.         }
    112.         return SystemName;
    113.     }
    114. }
    115.  
    116.  
    117.  
    It uses unsafe code so it's best to put it in an assembly by itself so you don't need to enable unsafe code on your main assembly. You'll need to enable the feature in Project Settings -> XR Plug-in Management -> OpenXR -> Tick "Get System Info". Then you can just call
    OpenXRFeatureSystemInfo.GetHeadsetName() to get the system name reported by OpenXR.
     
  40. thep3000

    thep3000

    Unity Technologies

    Joined:
    Aug 9, 2013
    Posts:
    400
    Color space info is definitely a gap right now - meta made an extension to get color space info but only their runtime supports it right now.

    Good point. I'll bring this logic back to the team - and I'll bring the feedback to the working group for the reasons why you need this info. Hopefully we can start closing some of these gaps (and also get you the info you need in an easier way in the short term). Thanks for writing the feature to unblock others.
     
    areepen and Dr-Nick like this.
  41. dsmeathers

    dsmeathers

    Joined:
    Jun 12, 2013
    Posts:
    7
    Thanks for the info. It's not just the color space though, some displays suffer from smearing with low brightness so we choose to remap the color to avoid these issues. We're not particularly technical about it, we just provide tools so that the color can be tweaked per headset and then let the artists adjust it by eye. I imagine whether you would want to do that would depend on the content, smearing is usually only a problem in dark or high contrast scenes.

    This is what we're getting at: although it would be amazing if everything worked perfectly across all headsets without us having to worry about it, that's just not the reality. Unfortunately we do sometimes need to know what headset is being used, and so it's frustrating when that information is hidden. It's also impossible for Unity or OpenXR to anticipate and fix any issues that might arise for any headset ahead of time, especially if some of these issues are dependent on the content.

    Thanks for pointing us in the right direction.
     
  42. zezba9000

    zezba9000

    Joined:
    Sep 28, 2010
    Posts:
    992
    This may be of value if you want to know the OpenXR hardware "UnityEngine.XR.OpenXR.OpenXRRuntime.name".
    Reports Oculus on Rift S for example.
     
  43. hhoffren

    hhoffren

    Joined:
    Dec 16, 2012
    Posts:
    3
    I was finally able to differentiate Quest 1 from Quest 2 with SystemInfo.deviceName. Not sure what other devices give with that, though.
     
  44. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254

    This is great, thank you. I 've tried adding it to it's own assembly using an asmdef as suggested, but when I do I loose the editor entry for the feature. Any insight is appreciated.

    Edit - Figured it out
    To make dsmeathers feature function as it's own assembly, you need to not only follow unity's tutorial on adding an asmdef file, but also need to manually define Unity.XR.OpenXR and Unity.XR.OpenXR.Editor as assembly definition references.

    To add these references, uncheck 'Use GUIDS' on your asmdef assembly file and add two entries. Next drag and drop he two previously named assemblies from your Packages > OpenXR Plugin > Runtime, and Packages > OpenXR Plugin > Editor folders.

    Edit 2 - Sadly
    Looks like 'they' khronos nuked the ability to use device properties. When querying the OpenXR API directly I get the following, less than useful information. (I don't have enough unique devices to generate a meaningful matrix of system and vendor Id's)
    ===================
    SteamVR - Vive Pro
    ===================
    systemId: 1152980740795793747
    vendorId: 10467
    systemName: "SteamVR/OpenXR : lighthouse"

    ======================
    SteamVR + WMR - HP G2 - Crashes SteamVR
    ======================
    systemId: 1152967477936783641
    vendorId: 10462
    systemName: "SteamVR/OpenXR : holographic"

    ======================
    WMR - HP G2
    ======================
    systemId: 1
    vendorId: 1118
    systemName: "Windows Mixed Reality"
     
    Last edited: Oct 3, 2022
  45. jackjansen

    jackjansen

    Joined:
    Apr 4, 2019
    Posts:
    22
    Bother, this is really bad for my use case.

    I am doing user experiments on visual quality (among other things), and we use various headsets in addition to varying various other parameters (to compare the quality).

    It is essential that we record the headset used in our output data, because if we publish results they should be repeatable, and if someone distrusts our measurements in five years I need to be able to show that I have recorded all the essential parameters.
     
    BenMonaghan likes this.
  46. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254
    I have noted that the OpenXR interaction profiles for each device do supply a name when InputSystem.RegisterLayout is called, but that name is at the pure whim of whoever last created the profile, and seems to change between packages.

    You could modify the device profile file for each device you include to give you more useful device names, then extract that device name from the currently assigned InputActions profile.

    Some profile files are located in your project directory after adding the OpenXR package. (Library\PackageCache\com.unity.xr.openxr@1.4.2\Runtime\Features\Interactions)

    An Example, using the HP Reverb G2 WMR device profile:
    Code (CSharp):
    1.  //com.microsoft.mixedreality.openxr
    2. //\Runtime\FeaturePlugins\HPMixedRealityControllerProfile.cs
    3.  
    4. //Around line #47
    5.  private const string kDeviceLocalizedName = "HP Reverb G2 Controller OpenXR";
    6.  private const string kDeviceDisplayName = "HP Reverb G2 Controller (OpenXR)";
    7.  
    8. //Around Line 273
    9.  ActionMapConfig actionMap = new ActionMapConfig()
    10.             {
    11.                 name = "hpmixedrealitycontroller",
    12.                 localizedName = kDeviceLocalizedName,
    13.                 desiredInteractionProfile = profile,
    14.                 manufacturer = "HP",
    15.                 serialNumber = "",
    16.  
    It's not perfect as unity makes an educated guess as to which profile to load, but may help with your inernal device testing regime.
     
  47. ArminRigo42

    ArminRigo42

    Joined:
    Oct 29, 2022
    Posts:
    4
    Just a reminder that the SteamVR OpenVR plugin is up-to-date on the asset store, and seems to work in Unity 2021.3. "OpenVR Loader" just shows up as another option in the "XR Plug-in Management" tab of project settings. As author of an application that supports a range of headsets and controllers that were always well-supported by SteamVR, this is definitely the best solution for me.
     
    jackjansen likes this.
  48. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    Well I ran into this issue as well. The Vive controllers and Oculus controllers have different angles and I need to know what angle to set the player's hands at. If there is no way to figure out what controller is being used, this is gonna be a pain in the butt.
     
  49. chrpetry

    chrpetry

    Joined:
    Mar 7, 2018
    Posts:
    65
    Any news on this?
    Especially on Pico 4 there is no info that I could use to detect controllers...
     
  50. colinleet

    colinleet

    Joined:
    Nov 20, 2019
    Posts:
    189
    For me today after upgrading to 2022.2.2f1 with all of the automatic package upgrades, this script has stopped working for me and I had to disable it. The new changes which were introduced with the automatic upgrade from 1.5.3 to 1.6 (xr.openxr) should not be considered safe with the current workaround.