Search Unity

Question OpenXR and OpenVR together?

Discussion in 'XR Interaction Toolkit and Input' started by myaydin, May 21, 2021.

  1. myaydin

    myaydin

    Joined:
    Jan 19, 2021
    Posts:
    4
    Unity version; 2020.03 or if you have suggestions?
    I installed XR plugin management.

    I have a project that I need to use HTC VIVE Trackers. VIVE trackers only work with SteamVR. When I install SteamVR SDK (via package manager or GitHub unitypackage doesn't matter), it checks "OpenVR Loader".
    Then I add an object and add the "Steam VR _Tracked Object" component to track VIVE trackers and it tracks the object. That's ok so far.

    Then controllers;
    I add deviced-based XR Rig to my scene. I removed the Ray interactors and add Direct Interactor (because I want to use hands prefabs). I add the prefabs etc.
    I play the project and I can see the controllers, also hands.
    note: I also add collision to controller and selected trigger in collision component

    Then I want to add objects that I can grab. I add a normal object (lets say cube). I add "XR Grab Interactable" component.

    Now I expect to grab the object when I run the app.
    Object is there, controllers are there but I can not interact with the object.

    Then I install OpenXR and check "Open XR" in "XR Plugin Management" settings.
    (At this point Open VR Loader and Open XR selected together)
    And it still doesn't work.
    Then I remove "Open VR Loader"
    Then I can interact with the object, I can grab etc..

    but the problem is, when I de-select Open VR Loader checkbox in the settings, I loose SteamVR and I loose VIVE Tracker (the object I assigned the tracker stays there)
    I also get the warning msg;

    "[SteamVR] Initialization failed. Please verify that you have SteamVR installed, your hmd is functioning, and OpenVR Loader is checked in the XR Plugin Management section of Project Settings."

    I m stuck for 3 days, can anyone give me an idea or path to follow, please?
    What can I do? (VIVE Tracker is a must)
     
  2. the_real_apoxol

    the_real_apoxol

    Unity Technologies

    Joined:
    Dec 18, 2020
    Posts:
    467
    I believe I understand what you are trying to do, and if I understand correctly it isnt possible. When you check multiple items in the XR Management they are not run together but rather it is a list of options to run, so only one will ever run at a time. Does that answer you question?
     
  3. myaydin

    myaydin

    Joined:
    Jan 19, 2021
    Posts:
    4
    I guess you're right. As long as OpenXR will not support HTC VIVE trackers, the thing I want is not doable. I must go with SteamVR and forget about Open XR I guess.
     
  4. the_real_apoxol

    the_real_apoxol

    Unity Technologies

    Joined:
    Dec 18, 2020
    Posts:
    467
    Unfortunately until the vive trackers gets support in an OpenXR runtime that is the case.
     
  5. Daryoont

    Daryoont

    Joined:
    Jun 14, 2021
    Posts:
    5
    hello, i have the same problem as i am renewing my game which is already selling.

    i already spent a month on developing no-vive tracker version. then i found this problem.

    it is critical for my app to support vive trackers on Windows as well as to support Quest Native app.
    i will go to hell if i have to use SteamVR Plugin for Unity + Oculus API to accomplish my specification.

    i am not new to the problem and waited the solution since 2019 Nov.

    i can actually develop but u know the maintenance/testing cost is too high. thats what "Unity" is for. Right?
    Reducing maintenance/testing cost for ongoing multiplatform development.

    how long do i have to wait and keep telling my boss that it's too costly to maintenance such a specification?

    it is really, really have no way out to the problem?? i dont mind spending a week for this if anyone give me any guide.
     
    Threeyes and Immersive-Matthew like this.
  6. the_real_apoxol

    the_real_apoxol

    Unity Technologies

    Joined:
    Dec 18, 2020
    Posts:
    467
    The issue is that HTC/SteamVR does not have support for the Tracker as of yet. There is work being done to support it I believe but no ETA that I know of.
     
    Immersive-Matthew likes this.
  7. Daryoont

    Daryoont

    Joined:
    Jun 14, 2021
    Posts:
    5
    apoxol

    ty for ur answer.
    ik that plugin Management system rely on implementation by the hardware manufacture.

    but instead of saying that its htc problem could u pls contact them and push their plans? i think the World need someone responsible to truely integrate VR inputs.

    thank you
     
  8. the_real_apoxol

    the_real_apoxol

    Unity Technologies

    Joined:
    Dec 18, 2020
    Posts:
    467
    HTC is part of the Khronos OpenXR group and they are actively discussing their plans along with valve for the Vive Tracker. We are not just passing it off on HTC here, but until they have support in a runtime for it and an OpenXR extension that we can reference all we can do is continue to be part of the discussion with them. I would recommend users who want OpenXR support for the tracker continue to make it known to HTC/Valve on their forums as well.
     
  9. ms82119

    ms82119

    Joined:
    Dec 26, 2016
    Posts:
    3
    I've got exactly the same issue as OP and am wondering if anyone has heard any update or timing for when openXR will be able to support the Vive Trackers? I've posted to HTC forums too, to see if anyone there knows the status.

    Until it's supported officially, is there any Unity configuration that people are aware of that might work? I have been using 2020.3 but since that version dropped their prior XR support (whatever that was called), I'm wondering if I go back to earlier versions I might be able to use the OpenXR package for tracking headset and controllers, while simultaneously using OpenVR/SteamVR to just track the tracker? Any suggestions appreciated.
     
  10. Daryoont

    Daryoont

    Joined:
    Jun 14, 2021
    Posts:
    5
    subscribed
     
  11. Daryoont

    Daryoont

    Joined:
    Jun 14, 2021
    Posts:
    5
    i think my time is up. now i have to give up OpenXR or give up Vive Tracker support.
    I cant give up on Unity b/c Unity does unify different APIs and standards for ease of devs.
    I believe in Unity that continuously solve incompatibility issues like this and truely unify all the input.
     
  12. Daryoont

    Daryoont

    Joined:
    Jun 14, 2021
    Posts:
    5
    In August 2021, Khronos defined
    XR_HTCX_vive_tracker_interaction extension.

    SteamVR in Nov released a patch note on "beta" version of steam vr with XR_HTCX_vive_tracker_interaction support
    in OpenXR mode.
    https://store.steampowered.com/news/app/250820/view/3087774682041248729
    some bugs fixed with the latest patch

    im going to shoot this and see if i can get it working
     
  13. the_real_apoxol

    the_real_apoxol

    Unity Technologies

    Joined:
    Dec 18, 2020
    Posts:
    467
    Looking forward to seeing the results, and if you get an OpenXRFeature working I am sure there are a lot of other people who would love to see that.
     
  14. pmem

    pmem

    Joined:
    Aug 4, 2019
    Posts:
    5
    I have created a new "UnityEditor.XR.OpenXR.Features.OpenXRFeature" to make the extension enabled and provide a interaction profile for the tracker.
    I can verify the extension is enabled with success, but I can't seem to find a way for the InputSystem to recognize and surface the InputDevice to the system.

    I believe that the feature should be enough to enable interaction... Just need to figure out how to create the InputDevice or preferably make the OpenXRLoader actually do it.
    Care to look at the code?

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine.Scripting;
    3. using UnityEngine.XR.OpenXR.Input;
    4. using UnityEngine.InputSystem.Layouts;
    5. using UnityEngine.InputSystem.Controls;
    6. using UnityEngine.InputSystem.XR;
    7. using UnityEngine.InputSystem;
    8. using System.Runtime.InteropServices;
    9. using System;
    10.  
    11. #if UNITY_EDITOR
    12. using UnityEditor;
    13. #endif
    14.  
    15. using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
    16.  
    17. namespace UnityEngine.XR.OpenXR.Features.Interactions
    18. {
    19.     /// <summary>
    20.     /// This <see cref="OpenXRInteractionFeature"/> enables the use of HTC Vive Trackers interaction profiles in OpenXR.
    21.     /// </summary>
    22. #if UNITY_EDITOR
    23.     [UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "HTC Vive Tracker Profile",
    24.         BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.WSA },
    25.         Company = "MASSIVE",
    26.         Desc = "Allows for mapping input to the HTC Vive Tracker interaction profile.",
    27.         DocumentationLink = Constants.k_DocumentationManualURL + "features/htcvivecontrollerprofile.html",
    28.         OpenxrExtensionStrings = "XR_HTCX_vive_tracker_interaction",
    29.         Version = "0.0.1",
    30.         Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
    31.         FeatureId = featureId)]
    32. #endif
    33.     public class HTCViveTrackerProfile : OpenXRInteractionFeature
    34.     {
    35.         /// <summary>
    36.         /// The feature id string. This is used to give the feature a well known id for reference.
    37.         /// </summary>
    38.         public const string featureId = "com.massive.openxr.feature.input.htcvivetracker";
    39.  
    40.         /// <summary>
    41.         /// OpenXR user path definitions for the tracker.
    42.         /// See the [OpenXR Specification](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#semantic-path-user) for more intformation.
    43.         /// </summary>
    44.         public static class TrackerUserPaths
    45.         {
    46.             /// <summary>
    47.             /// Path for user left foot
    48.             /// </summary>
    49.             public const string leftFoot = "/user/vive_tracker_htcx/role/left_foot";
    50.  
    51.             /// <summary>
    52.             /// Path for user roght foot
    53.             /// </summary>
    54.             public const string rightFoot = "/user/vive_tracker_htcx/role/right_foot";
    55.  
    56.             /// <summary>
    57.             /// Path for user left shoulder
    58.             /// </summary>
    59.             public const string leftShoulder = "/user/vive_tracker_htcx/role/left_shoulder";
    60.  
    61.             /// <summary>
    62.             /// Path for user right shoulder
    63.             /// </summary>
    64.             public const string rightShoulder = "/user/vive_tracker_htcx/role/right_shoulder";
    65.  
    66.             /// <summary>
    67.             /// Path for user left elbow
    68.             /// </summary>
    69.             public const string leftElbow = "/user/vive_tracker_htcx/role/left_elbow";
    70.  
    71.             /// <summary>
    72.             /// Path for user right elbow
    73.             /// </summary>
    74.             public const string rightElbow = "/user/vive_tracker_htcx/role/right_elbow";
    75.  
    76.             /// <summary>
    77.             /// Path for user left knee
    78.             /// </summary>
    79.             public const string leftKnee = "/user/vive_tracker_htcx/role/left_knee";
    80.  
    81.             /// <summary>
    82.             /// Path for user right knee
    83.             /// </summary>
    84.             public const string rightKnee = "/user/vive_tracker_htcx/role/right_knee";
    85.  
    86.             /// <summary>
    87.             /// Path for user waist
    88.             /// </summary>
    89.             public const string waist = "/user/vive_tracker_htcx/role/waist";
    90.  
    91.             /// <summary>
    92.             /// Path for user chest
    93.             /// </summary>
    94.             public const string chest = "/user/vive_tracker_htcx/role/chest";
    95.  
    96.             /// <summary>
    97.             /// Path for user custom camera
    98.             /// </summary>
    99.             public const string camera = "/user/vive_tracker_htcx/role/camera";
    100.  
    101.             /// <summary>
    102.             /// Path for user keyboard
    103.             /// </summary>
    104.             public const string keyboard = "/user/vive_tracker_htcx/role/keyboard";
    105.         }
    106.  
    107.         /// <summary>
    108.         /// An Input System device based off the <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#_htc_vive_controller_profile">HTC Vive Tracker</a>.
    109.         /// </summary>
    110.         [Preserve, InputControlLayout(displayName = "HTC Vive Tracker (OpenXR)", commonUsages = new[] { "Left Foot", "Right Foot", "Left Shoulder", "Right Shoulder", "Left Elbow", "Right Elbow", "Left Knee", "Right Knee", "Waist", "Chest", "Camera", "Keyboard" })]
    111.         public class ViveTracker : TrackedDevice
    112.         {
    113.             /// <summary>
    114.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the HTC Vive Tracker Profile select OpenXR binding.
    115.             /// </summary>
    116.             [Preserve, InputControl(aliases = new[] { "Secondary", "selectbutton" }, usage = "SystemButton")]
    117.             public ButtonControl select { get; private set; }
    118.  
    119.             /// <summary>
    120.             /// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents information from the <see cref="HTCViveTrackerProfile.squeeze"/> OpenXR binding.
    121.             /// </summary>
    122.             [Preserve, InputControl(aliases = new[] { "GripAxis", "squeeze" }, usage = "Grip")]
    123.             public AxisControl grip { get; private set; }
    124.  
    125.             /// <summary>
    126.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.squeeze"/> OpenXR binding.
    127.             /// </summary>
    128.             [Preserve, InputControl(aliases = new[] { "GripButton", "squeezeClicked" }, usage = "GripButton")]
    129.             public ButtonControl gripPressed { get; private set; }
    130.  
    131.             /// <summary>
    132.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.menu"/> OpenXR binding.
    133.             /// </summary>
    134.             [Preserve, InputControl(aliases = new[] { "Primary", "menubutton" }, usage = "MenuButton")]
    135.             public ButtonControl menu { get; private set; }
    136.  
    137.             /// <summary>
    138.             /// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents information from the <see cref="HTCViveTrackerProfile.trigger"/> OpenXR binding.
    139.             /// </summary>
    140.             [Preserve, InputControl(alias = "triggeraxis", usage = "Trigger")]
    141.             public AxisControl trigger { get; private set; }
    142.  
    143.             /// <summary>
    144.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.triggerClick"/> OpenXR binding.
    145.             /// </summary>
    146.             [Preserve, InputControl(alias = "triggerbutton", usage = "TriggerButton")]
    147.             public ButtonControl triggerPressed { get; private set; }
    148.  
    149.             /// <summary>
    150.             /// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents information from the <see cref="HTCViveTrackerProfile.trackpad"/> OpenXR binding.
    151.             /// </summary>
    152.             [Preserve, InputControl(aliases = new[] { "Primary2DAxis", "touchpadaxes", "touchpad" }, usage = "Primary2DAxis")]
    153.             public Vector2Control trackpad { get; private set; }
    154.  
    155.             /// <summary>
    156.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.trackpadClick"/> OpenXR binding.
    157.             /// </summary>
    158.             [Preserve, InputControl(aliases = new[] { "joystickorpadpressed", "touchpadpressed" }, usage = "Primary2DAxisClick")]
    159.             public ButtonControl trackpadClicked { get; private set; }
    160.  
    161.             /// <summary>
    162.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.trackpadTouch"/> OpenXR binding.
    163.             /// </summary>
    164.             [Preserve, InputControl(aliases = new[] { "joystickorpadtouched", "touchpadtouched" }, usage = "Primary2DAxisTouch")]
    165.             public ButtonControl trackpadTouched { get; private set; }
    166.  
    167.             /// <summary>
    168.             /// A <see cref="PoseControl"/> that represents information from the <see cref="HTCViveTrackerProfile.grip"/> OpenXR binding.
    169.             /// </summary>
    170.             [Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
    171.             public PoseControl devicePose { get; private set; }
    172.  
    173.             /// <summary>
    174.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
    175.             /// </summary>
    176.             [Preserve, InputControl(offset = 26)]
    177.             new public ButtonControl isTracked { get; private set; }
    178.  
    179.             /// <summary>
    180.             /// A [IntegerControl](xref:UnityEngine.InputSystem.Controls.IntegerControl) required for back compatibility with the XRSDK layouts. This represents the bit flag set indicating what data is valid. This value is equivalent to mapping devicePose/trackingState.
    181.             /// </summary>
    182.             [Preserve, InputControl(offset = 28)]
    183.             new public IntegerControl trackingState { get; private set; }
    184.  
    185.             /// <summary>
    186.             /// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for back compatibility with the XRSDK layouts. This is the device position. For the Oculus Touch device, this is both the grip and the pointer position. This value is equivalent to mapping devicePose/position.
    187.             /// </summary>
    188.             [Preserve, InputControl(offset = 32, alias = "gripPosition")]
    189.             new public Vector3Control devicePosition { get; private set; }
    190.  
    191.             /// <summary>
    192.             /// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the device orientation. For the Oculus Touch device, this is both the grip and the pointer rotation. This value is equivalent to mapping devicePose/rotation.
    193.             /// </summary>
    194.             [Preserve, InputControl(offset = 44, alias = "gripOrientation")]
    195.             new public QuaternionControl deviceRotation { get; private set; }
    196.  
    197.             /// <summary>
    198.             /// A <see cref="HapticControl"/> that represents the <see cref="HTCViveTrackerProfile.haptic"/> binding.
    199.             /// </summary>
    200.             [Preserve, InputControl(usage = "Haptic")]
    201.             public HapticControl haptic { get; private set; }
    202.  
    203.             /// <inheritdoc cref="OpenXRDevice"/>
    204.             protected override void FinishSetup()
    205.             {
    206.                 base.FinishSetup();
    207.                 select = GetChildControl<ButtonControl>("select");
    208.                 grip = GetChildControl<AxisControl>("grip");
    209.                 gripPressed = GetChildControl<ButtonControl>("gripPressed");
    210.                 menu = GetChildControl<ButtonControl>("menu");
    211.                 trigger = GetChildControl<AxisControl>("trigger");
    212.                 triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
    213.                 trackpad = GetChildControl<Vector2Control>("trackpad");
    214.                 trackpadClicked = GetChildControl<ButtonControl>("trackpadClicked");
    215.                 trackpadTouched = GetChildControl<ButtonControl>("trackpadTouched");
    216.  
    217.                 devicePose = GetChildControl<PoseControl>("devicePose");
    218.                 isTracked = GetChildControl<ButtonControl>("isTracked");
    219.                 trackingState = GetChildControl<IntegerControl>("trackingState");
    220.                 devicePosition = GetChildControl<Vector3Control>("devicePosition");
    221.                 deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
    222.  
    223.                 haptic = GetChildControl<HapticControl>("haptic");
    224.             }
    225.         }
    226.  
    227.         /// <summary>The interaction profile string used to reference the <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#_htc_vive_controller_profile">HTC Vive Tracker</a>.</summary>
    228.         public const string profile = "/interaction_profiles/htc/vive_tracker_htcx";
    229.  
    230.         /// <summary>
    231.         /// Constant for a boolean interaction binding '.../input/system/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    232.         /// </summary>
    233.         public const string system = "/input/system/click";
    234.         /// <summary>
    235.         /// Constant for a boolean interaction binding '.../input/squeeze/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    236.         /// </summary>
    237.         public const string squeeze = "/input/squeeze/click";
    238.         /// <summary>
    239.         /// Constant for a boolean interaction binding '.../input/menu/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    240.         /// </summary>
    241.         public const string menu = "/input/menu/click";
    242.         /// <summary>
    243.         /// Constant for a float interaction binding '.../input/trigger/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    244.         /// </summary>
    245.         public const string trigger = "/input/trigger/value";
    246.         /// <summary>
    247.         /// Constant for a boolean interaction binding '.../input/trigger/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    248.         /// </summary>
    249.         public const string triggerClick = "/input/trigger/click";
    250.         /// <summary>
    251.         /// Constant for a Vector2 interaction binding '.../input/trackpad' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    252.         /// </summary>
    253.         public const string trackpad = "/input/trackpad";
    254.         /// <summary>
    255.         /// Constant for a boolean interaction binding '.../input/trackpad/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    256.         /// </summary>
    257.         public const string trackpadClick = "/input/trackpad/click";
    258.         /// <summary>
    259.         /// Constant for a boolean interaction binding '.../input/trackpad/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    260.         /// </summary>
    261.         public const string trackpadTouch = "/input/trackpad/touch";
    262.         /// <summary>
    263.         /// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    264.         /// </summary>
    265.         public const string grip = "/input/grip/pose";
    266.         /// <summary>
    267.         /// Constant for a haptic interaction binding '.../output/haptic' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    268.         /// </summary>
    269.         public const string haptic = "/output/haptic";
    270.  
    271.         private const string kDeviceLocalizedName = "HTC Vive Tracker OpenXR";
    272.  
    273.         /// <summary>
    274.         /// Registers the <see cref="ViveTracker"/> layout with the Input System.
    275.         /// </summary>
    276.         protected override void RegisterDeviceLayout()
    277.         {
    278.             InputSystem.InputSystem.RegisterLayout(typeof(ViveTracker),
    279.                         matches: new InputDeviceMatcher()
    280.                         .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
    281.                         .WithProduct(kDeviceLocalizedName));
    282.         }
    283.  
    284.         /// <summary>
    285.         /// Removes the <see cref="ViveTracker"/> layout from the Input System.
    286.         /// </summary>
    287.         protected override void UnregisterDeviceLayout()
    288.         {
    289.             InputSystem.InputSystem.RemoveLayout(nameof(ViveTracker));
    290.         }
    291.  
    292.         /// <inheritdoc/>
    293.         protected override void RegisterActionMapsWithRuntime()
    294.         {
    295.             ActionMapConfig actionMap = new ActionMapConfig()
    296.             {
    297.                 name = "htcvivetracker",
    298.                 localizedName = kDeviceLocalizedName,
    299.                 desiredInteractionProfile = profile,
    300.                 manufacturer = "HTC",
    301.                 serialNumber = "",
    302.                 deviceInfos = new List<DeviceConfig>()
    303.                 {
    304.                     new DeviceConfig()
    305.                     {
    306.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    307.                         userPath = TrackerUserPaths.leftFoot
    308.                     },
    309.                     new DeviceConfig()
    310.                     {
    311.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    312.                         userPath = TrackerUserPaths.rightFoot
    313.                     },
    314.                     new DeviceConfig()
    315.                     {
    316.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    317.                         userPath = TrackerUserPaths.leftShoulder
    318.                     },
    319.                     new DeviceConfig()
    320.                     {
    321.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    322.                         userPath = TrackerUserPaths.rightShoulder
    323.                     },
    324.                     new DeviceConfig()
    325.                     {
    326.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    327.                         userPath = TrackerUserPaths.leftElbow
    328.                     },
    329.                     new DeviceConfig()
    330.                     {
    331.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    332.                         userPath = TrackerUserPaths.rightElbow
    333.                     },
    334.                     new DeviceConfig()
    335.                     {
    336.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    337.                         userPath = TrackerUserPaths.leftKnee
    338.                     },
    339.                     new DeviceConfig()
    340.                     {
    341.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    342.                         userPath = TrackerUserPaths.rightKnee
    343.                     },
    344.                     new DeviceConfig()
    345.                     {
    346.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    347.                         userPath = TrackerUserPaths.waist
    348.                     },
    349.                     new DeviceConfig()
    350.                     {
    351.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    352.                         userPath = TrackerUserPaths.chest
    353.                     },
    354.                     new DeviceConfig()
    355.                     {
    356.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    357.                         userPath = TrackerUserPaths.camera
    358.                     },
    359.                     new DeviceConfig()
    360.                     {
    361.                         characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.None),
    362.                         userPath = TrackerUserPaths.keyboard
    363.                     }
    364.                 },
    365.                 actions = new List<ActionConfig>()
    366.                 {
    367.                     new ActionConfig()
    368.                     {
    369.                         name = "grip",
    370.                         localizedName = "Grip",
    371.                         type = ActionType.Axis1D,
    372.                         usages = new List<string>()
    373.                         {
    374.                             "Grip"
    375.                         },
    376.                         bindings = new List<ActionBinding>()
    377.                         {
    378.                             new ActionBinding()
    379.                             {
    380.                                 interactionPath = squeeze,
    381.                                 interactionProfileName = profile,
    382.                             }
    383.                         }
    384.                     },
    385.                     new ActionConfig()
    386.                     {
    387.                         name = "gripPressed",
    388.                         localizedName = "Grip Pressed",
    389.                         type = ActionType.Binary,
    390.                         usages = new List<string>()
    391.                         {
    392.                             "GripButton"
    393.                         },
    394.                         bindings = new List<ActionBinding>()
    395.                         {
    396.                             new ActionBinding()
    397.                             {
    398.                                 interactionPath = squeeze,
    399.                                 interactionProfileName = profile,
    400.                             }
    401.                         }
    402.                     },
    403.                     new ActionConfig()
    404.                     {
    405.                         name = "menu",
    406.                         localizedName = "Menu",
    407.                         type = ActionType.Binary,
    408.                         usages = new List<string>()
    409.                         {
    410.                             "MenuButton"
    411.                         },
    412.                         bindings = new List<ActionBinding>()
    413.                         {
    414.                             new ActionBinding()
    415.                             {
    416.                                 interactionPath = menu,
    417.                                 interactionProfileName = profile,
    418.                             }
    419.                         }
    420.                     },
    421.                     new ActionConfig()
    422.                     {
    423.                         name = "select",
    424.                         localizedName = "Select",
    425.                         type = ActionType.Binary,
    426.                         usages = new List<string>()
    427.                         {
    428.                             "SystemButton"
    429.                         },
    430.                         bindings = new List<ActionBinding>()
    431.                         {
    432.                             new ActionBinding()
    433.                             {
    434.                                 interactionPath = system,
    435.                                 interactionProfileName = profile,
    436.                             }
    437.                         }
    438.                     },
    439.                     new ActionConfig()
    440.                     {
    441.                         name = "trigger",
    442.                         localizedName = "Trigger",
    443.                         type = ActionType.Axis1D,
    444.                         usages = new List<string>()
    445.                         {
    446.                             "Trigger"
    447.                         },
    448.                         bindings = new List<ActionBinding>()
    449.                         {
    450.                             new ActionBinding()
    451.                             {
    452.                                 interactionPath = trigger,
    453.                                 interactionProfileName = profile,
    454.                             }
    455.                         }
    456.                     },
    457.                     new ActionConfig()
    458.                     {
    459.                         name = "triggerPressed",
    460.                         localizedName = "Trigger Pressed",
    461.                         type = ActionType.Binary,
    462.                         usages = new List<string>()
    463.                         {
    464.                             "TriggerButton"
    465.                         },
    466.                         bindings = new List<ActionBinding>()
    467.                         {
    468.                             new ActionBinding()
    469.                             {
    470.                                 interactionPath = triggerClick,
    471.                                 interactionProfileName = profile,
    472.                             }
    473.                         }
    474.                     },
    475.                     new ActionConfig()
    476.                     {
    477.                         name = "trackpad",
    478.                         localizedName = "Trackpad",
    479.                         type = ActionType.Axis2D,
    480.                         usages = new List<string>()
    481.                         {
    482.                             "Primary2DAxis"
    483.                         },
    484.                         bindings = new List<ActionBinding>()
    485.                         {
    486.                             new ActionBinding()
    487.                             {
    488.                                 interactionPath = trackpad,
    489.                                 interactionProfileName = profile,
    490.                             }
    491.                         }
    492.                     },
    493.                     new ActionConfig()
    494.                     {
    495.                         name = "trackpadTouched",
    496.                         localizedName = "Trackpad Touched",
    497.                         type = ActionType.Binary,
    498.                         usages = new List<string>()
    499.                         {
    500.                             "Primary2DAxisTouch"
    501.                         },
    502.                         bindings = new List<ActionBinding>()
    503.                         {
    504.                             new ActionBinding()
    505.                             {
    506.                                 interactionPath = trackpadTouch,
    507.                                 interactionProfileName = profile,
    508.                             }
    509.                         }
    510.                     },
    511.                     new ActionConfig()
    512.                     {
    513.                         name = "trackpadClicked",
    514.                         localizedName = "Trackpad Clicked",
    515.                         type = ActionType.Binary,
    516.                         usages = new List<string>()
    517.                         {
    518.                             "Primary2DAxisClick"
    519.                         },
    520.                         bindings = new List<ActionBinding>()
    521.                         {
    522.                             new ActionBinding()
    523.                             {
    524.                                 interactionPath = trackpadClick,
    525.                                 interactionProfileName = profile,
    526.                             }
    527.                         }
    528.                     },
    529.                     new ActionConfig()
    530.                     {
    531.                         name = "devicePose",
    532.                         localizedName = "Device Pose",
    533.                         type = ActionType.Pose,
    534.                         usages = new List<string>()
    535.                         {
    536.                             "Device"
    537.                         },
    538.                         bindings = new List<ActionBinding>()
    539.                         {
    540.                             new ActionBinding()
    541.                             {
    542.                                 interactionPath = grip,
    543.                                 interactionProfileName = profile,
    544.                             }
    545.                         }
    546.                     },
    547.                     // Haptics
    548.                     new ActionConfig()
    549.                     {
    550.                         name = "haptic",
    551.                         localizedName = "Haptic Output",
    552.                         type = ActionType.Vibrate,
    553.                         usages = new List<string>() { "Haptic" },
    554.                         bindings = new List<ActionBinding>()
    555.                         {
    556.                             new ActionBinding()
    557.                             {
    558.                                 interactionPath = haptic,
    559.                                 interactionProfileName = profile,
    560.                             }
    561.                         }
    562.                     }
    563.                 }
    564.             };
    565.  
    566.             AddActionMap(actionMap);
    567.         }
    568.  
    569.  
    570.         protected override bool OnInstanceCreate(ulong xrInstance)
    571.         {
    572.             bool result = base.OnInstanceCreate(xrInstance);
    573.  
    574.             if (OpenXRRuntime.IsExtensionEnabled("XR_HTCX_vive_tracker_interaction"))
    575.             {
    576.                 Debug.Log("HTC Vive Tracker Extension Enabled");
    577.             }
    578.             else
    579.             {
    580.                 Debug.Log("HTC Vive Tracker Extension Not Enabled");
    581.             }
    582.  
    583.             return result;
    584.         }
    585.     }
    586. }
    587.  
     
  15. the_real_apoxol

    the_real_apoxol

    Unity Technologies

    Joined:
    Dec 18, 2020
    Posts:
    467
    I dont have a vive tracker that I can test with but the code looks correct at first glance. You may want to check your player log and editor log to see if there are any errors or warnings. I was helping someone else on github trying to get the vive tracker working and they also couldnt get it working, I wonder if the trackers are not sending interaction profile changed events.

    I assume the tracker isnt showing up in the input debugger?
     
  16. pmem

    pmem

    Joined:
    Aug 4, 2019
    Posts:
    5
    I have since improved on the code a bit as it was colliding with XRTracker from OpenVR and to also add characteristics to the devices.
    No useful debugs are being shown.
    Yes, the Tracker is not showing up in the input debugger, and that's the missing piece in my opinion. I guess that only after the tracker is presented to the Input System can it attach to the profile.

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine.Scripting;
    3. using UnityEngine.XR.OpenXR.Input;
    4. using UnityEngine.InputSystem.Layouts;
    5. using UnityEngine.InputSystem.Controls;
    6. using UnityEngine.InputSystem.XR;
    7. using UnityEngine.InputSystem;
    8. using System.Runtime.InteropServices;
    9. using System;
    10.  
    11. #if UNITY_EDITOR
    12. using UnityEditor;
    13. #endif
    14.  
    15. using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
    16.  
    17. namespace UnityEngine.XR.OpenXR.Features.Interactions
    18. {
    19.     /// <summary>
    20.     /// This <see cref="OpenXRInteractionFeature"/> enables the use of HTC Vive Trackers interaction profiles in OpenXR.
    21.     /// </summary>
    22. #if UNITY_EDITOR
    23.     [UnityEditor.XR.OpenXR.Features.OpenXRFeature(
    24.         UiName = "HTC Vive Tracker Profile",
    25.         BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.WSA },
    26.         Company = "MASSIVE",
    27.         Desc = "Allows for mapping input to the HTC Vive Tracker interaction profile.",
    28.         DocumentationLink = Constants.k_DocumentationManualURL,
    29.         OpenxrExtensionStrings = HTCViveTrackerProfile.extensionName,
    30.         Version = "0.0.1",
    31.         Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
    32.         FeatureId = featureId)]
    33. #endif
    34.     public class HTCViveTrackerProfile : OpenXRInteractionFeature
    35.     {
    36.         /// <summary>
    37.         /// The feature id string. This is used to give the feature a well known id for reference.
    38.         /// </summary>
    39.         public const string featureId = "com.massive.openxr.feature.input.htcvivetracker";
    40.  
    41.         /// <summary>
    42.         /// The interaction profile string used to reference the <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#:~:text=in%20this%20case.-,VIVE%20Tracker%20interaction%20profile,-Interaction%20profile%20path">HTC Vive Tracker</a>.
    43.         /// </summary>
    44.         public const string profile = "/interaction_profiles/htc/vive_tracker_htcx";
    45.  
    46.         /// <summary>
    47.         /// The name of the OpenXR extension that supports the Vive Tracker
    48.         /// </summary>
    49.         public const string extensionName = "XR_HTCX_vive_tracker_interaction";
    50.  
    51.         private const string kDeviceLocalizedName = "HTC Vive Tracker OpenXR";
    52.  
    53.         /// <summary>
    54.         /// OpenXR user path definitions for the tracker.
    55.         /// </summary>
    56.         public static class TrackerUserPaths
    57.         {
    58.             /// <summary>
    59.             /// Path for user left foot
    60.             /// </summary>
    61.             public const string leftFoot = "/user/vive_tracker_htcx/role/left_foot";
    62.  
    63.             /// <summary>
    64.             /// Path for user roght foot
    65.             /// </summary>
    66.             public const string rightFoot = "/user/vive_tracker_htcx/role/right_foot";
    67.  
    68.             /// <summary>
    69.             /// Path for user left shoulder
    70.             /// </summary>
    71.             public const string leftShoulder = "/user/vive_tracker_htcx/role/left_shoulder";
    72.  
    73.             /// <summary>
    74.             /// Path for user right shoulder
    75.             /// </summary>
    76.             public const string rightShoulder = "/user/vive_tracker_htcx/role/right_shoulder";
    77.  
    78.             /// <summary>
    79.             /// Path for user left elbow
    80.             /// </summary>
    81.             public const string leftElbow = "/user/vive_tracker_htcx/role/left_elbow";
    82.  
    83.             /// <summary>
    84.             /// Path for user right elbow
    85.             /// </summary>
    86.             public const string rightElbow = "/user/vive_tracker_htcx/role/right_elbow";
    87.  
    88.             /// <summary>
    89.             /// Path for user left knee
    90.             /// </summary>
    91.             public const string leftKnee = "/user/vive_tracker_htcx/role/left_knee";
    92.  
    93.             /// <summary>
    94.             /// Path for user right knee
    95.             /// </summary>
    96.             public const string rightKnee = "/user/vive_tracker_htcx/role/right_knee";
    97.  
    98.             /// <summary>
    99.             /// Path for user waist
    100.             /// </summary>
    101.             public const string waist = "/user/vive_tracker_htcx/role/waist";
    102.  
    103.             /// <summary>
    104.             /// Path for user chest
    105.             /// </summary>
    106.             public const string chest = "/user/vive_tracker_htcx/role/chest";
    107.  
    108.             /// <summary>
    109.             /// Path for user custom camera
    110.             /// </summary>
    111.             public const string camera = "/user/vive_tracker_htcx/role/camera";
    112.  
    113.             /// <summary>
    114.             /// Path for user keyboard
    115.             /// </summary>
    116.             public const string keyboard = "/user/vive_tracker_htcx/role/keyboard";
    117.         }
    118.  
    119.         /// <summary>
    120.         /// OpenXR component path definitions for the tracker.
    121.         /// </summary>
    122.         public static class TrackerComponentPaths
    123.         {
    124.             /// <summary>
    125.             /// Constant for a boolean interaction binding '.../input/system/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    126.             /// </summary>
    127.             public const string system = "/input/system/click";
    128.             /// <summary>
    129.             /// Constant for a boolean interaction binding '.../input/squeeze/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    130.             /// </summary>
    131.             public const string squeeze = "/input/squeeze/click";
    132.             /// <summary>
    133.             /// Constant for a boolean interaction binding '.../input/menu/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    134.             /// </summary>
    135.             public const string menu = "/input/menu/click";
    136.             /// <summary>
    137.             /// Constant for a float interaction binding '.../input/trigger/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    138.             /// </summary>
    139.             public const string trigger = "/input/trigger/value";
    140.             /// <summary>
    141.             /// Constant for a boolean interaction binding '.../input/trigger/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    142.             /// </summary>
    143.             public const string triggerClick = "/input/trigger/click";
    144.             /// <summary>
    145.             /// Constant for a Vector2 interaction binding '.../input/trackpad' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    146.             /// </summary>
    147.             public const string trackpad = "/input/trackpad";
    148.             /// <summary>
    149.             /// Constant for a boolean interaction binding '.../input/trackpad/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    150.             /// </summary>
    151.             public const string trackpadClick = "/input/trackpad/click";
    152.             /// <summary>
    153.             /// Constant for a boolean interaction binding '.../input/trackpad/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    154.             /// </summary>
    155.             public const string trackpadTouch = "/input/trackpad/touch";
    156.             /// <summary>
    157.             /// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    158.             /// </summary>
    159.             public const string grip = "/input/grip/pose";
    160.             /// <summary>
    161.             /// Constant for a haptic interaction binding '.../output/haptic' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    162.             /// </summary>
    163.             public const string haptic = "/output/haptic";
    164.         }
    165.  
    166.         /// <summary>
    167.         /// A base Input System device for XR Trackers, based off the TrackedDevice
    168.         /// </summary>
    169.         [InputControlLayout(isGenericTypeOfDevice = true, displayName = "XR Tracker")]
    170.         public class XRTracker : TrackedDevice
    171.         {
    172.         }
    173.  
    174.         /// <summary>
    175.         /// An Input System device based off the <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#_htc_vive_controller_profile">HTC Vive Tracker</a>.
    176.         /// </summary>
    177.         [Preserve, InputControlLayout(displayName = "HTC Vive Tracker (OpenXR)", commonUsages = new[] { "Left Foot", "Right Foot", "Left Shoulder", "Right Shoulder", "Left Elbow", "Right Elbow", "Left Knee", "Right Knee", "Waist", "Chest", "Camera", "Keyboard" })]
    178.         public class XRViveTracker : XRTracker
    179.         {
    180.             /// <summary>
    181.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the HTC Vive Tracker Profile select OpenXR binding.
    182.             /// </summary>
    183.             [Preserve, InputControl(aliases = new[] { "Secondary", "selectbutton" }, usage = "SystemButton")]
    184.             public ButtonControl select { get; private set; }
    185.  
    186.             /// <summary>
    187.             /// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents information from the <see cref="HTCViveTrackerProfile.squeeze"/> OpenXR binding.
    188.             /// </summary>
    189.             [Preserve, InputControl(aliases = new[] { "GripAxis", "squeeze" }, usage = "Grip")]
    190.             public AxisControl grip { get; private set; }
    191.  
    192.             /// <summary>
    193.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.squeeze"/> OpenXR binding.
    194.             /// </summary>
    195.             [Preserve, InputControl(aliases = new[] { "GripButton", "squeezeClicked" }, usage = "GripButton")]
    196.             public ButtonControl gripPressed { get; private set; }
    197.  
    198.             /// <summary>
    199.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.menu"/> OpenXR binding.
    200.             /// </summary>
    201.             [Preserve, InputControl(aliases = new[] { "Primary", "menubutton" }, usage = "MenuButton")]
    202.             public ButtonControl menu { get; private set; }
    203.  
    204.             /// <summary>
    205.             /// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents information from the <see cref="HTCViveTrackerProfile.trigger"/> OpenXR binding.
    206.             /// </summary>
    207.             [Preserve, InputControl(alias = "triggeraxis", usage = "Trigger")]
    208.             public AxisControl trigger { get; private set; }
    209.  
    210.             /// <summary>
    211.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.triggerClick"/> OpenXR binding.
    212.             /// </summary>
    213.             [Preserve, InputControl(alias = "triggerbutton", usage = "TriggerButton")]
    214.             public ButtonControl triggerPressed { get; private set; }
    215.  
    216.             /// <summary>
    217.             /// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents information from the <see cref="HTCViveTrackerProfile.trackpad"/> OpenXR binding.
    218.             /// </summary>
    219.             [Preserve, InputControl(aliases = new[] { "Primary2DAxis", "touchpadaxes", "touchpad" }, usage = "Primary2DAxis")]
    220.             public Vector2Control trackpad { get; private set; }
    221.  
    222.             /// <summary>
    223.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.trackpadClick"/> OpenXR binding.
    224.             /// </summary>
    225.             [Preserve, InputControl(aliases = new[] { "joystickorpadpressed", "touchpadpressed" }, usage = "Primary2DAxisClick")]
    226.             public ButtonControl trackpadClicked { get; private set; }
    227.  
    228.             /// <summary>
    229.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveTrackerProfile.trackpadTouch"/> OpenXR binding.
    230.             /// </summary>
    231.             [Preserve, InputControl(aliases = new[] { "joystickorpadtouched", "touchpadtouched" }, usage = "Primary2DAxisTouch")]
    232.             public ButtonControl trackpadTouched { get; private set; }
    233.  
    234.             /// <summary>
    235.             /// A <see cref="PoseControl"/> that represents information from the <see cref="HTCViveTrackerProfile.grip"/> OpenXR binding.
    236.             /// </summary>
    237.             [Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
    238.             public PoseControl devicePose { get; private set; }
    239.  
    240.             /// <summary>
    241.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
    242.             /// </summary>
    243.             [Preserve, InputControl(offset = 26)]
    244.             new public ButtonControl isTracked { get; private set; }
    245.  
    246.             /// <summary>
    247.             /// A [IntegerControl](xref:UnityEngine.InputSystem.Controls.IntegerControl) required for back compatibility with the XRSDK layouts. This represents the bit flag set indicating what data is valid. This value is equivalent to mapping devicePose/trackingState.
    248.             /// </summary>
    249.             [Preserve, InputControl(offset = 28)]
    250.             new public IntegerControl trackingState { get; private set; }
    251.  
    252.             /// <summary>
    253.             /// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for back compatibility with the XRSDK layouts. This is the device position. For the Oculus Touch device, this is both the grip and the pointer position. This value is equivalent to mapping devicePose/position.
    254.             /// </summary>
    255.             [Preserve, InputControl(offset = 32, alias = "gripPosition")]
    256.             new public Vector3Control devicePosition { get; private set; }
    257.  
    258.             /// <summary>
    259.             /// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the device orientation. For the Oculus Touch device, this is both the grip and the pointer rotation. This value is equivalent to mapping devicePose/rotation.
    260.             /// </summary>
    261.             [Preserve, InputControl(offset = 44, alias = "gripOrientation")]
    262.             new public QuaternionControl deviceRotation { get; private set; }
    263.  
    264.             /// <summary>
    265.             /// A <see cref="HapticControl"/> that represents the <see cref="HTCViveTrackerProfile.haptic"/> binding.
    266.             /// </summary>
    267.             [Preserve, InputControl(usage = "Haptic")]
    268.             public HapticControl haptic { get; private set; }
    269.  
    270.             /// <inheritdoc cref="OpenXRDevice"/>
    271.             protected override void FinishSetup()
    272.             {
    273.                 base.FinishSetup();
    274.                 select = GetChildControl<ButtonControl>("select");
    275.                 grip = GetChildControl<AxisControl>("grip");
    276.                 gripPressed = GetChildControl<ButtonControl>("gripPressed");
    277.                 menu = GetChildControl<ButtonControl>("menu");
    278.                 trigger = GetChildControl<AxisControl>("trigger");
    279.                 triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
    280.                 trackpad = GetChildControl<Vector2Control>("trackpad");
    281.                 trackpadClicked = GetChildControl<ButtonControl>("trackpadClicked");
    282.                 trackpadTouched = GetChildControl<ButtonControl>("trackpadTouched");
    283.  
    284.                 devicePose = GetChildControl<PoseControl>("devicePose");
    285.                 isTracked = GetChildControl<ButtonControl>("isTracked");
    286.                 trackingState = GetChildControl<IntegerControl>("trackingState");
    287.                 devicePosition = GetChildControl<Vector3Control>("devicePosition");
    288.                 deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
    289.  
    290.                 haptic = GetChildControl<HapticControl>("haptic");
    291.  
    292.                 Debug.Log("Device added");
    293.             }
    294.         }
    295.  
    296.         /// <summary>
    297.         /// Registers the <see cref="ViveTracker"/> layout with the Input System.
    298.         /// </summary>
    299.         protected override void RegisterDeviceLayout()
    300.         {
    301.             InputSystem.InputSystem.RegisterLayout<XRTracker>();
    302.  
    303.             InputSystem.InputSystem.RegisterLayout(typeof(XRViveTracker),
    304.                         matches: new InputDeviceMatcher()
    305.                         .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
    306.                         .WithProduct(kDeviceLocalizedName));
    307.         }
    308.  
    309.         /// <summary>
    310.         /// Removes the <see cref="ViveTracker"/> layout from the Input System.
    311.         /// </summary>
    312.         protected override void UnregisterDeviceLayout()
    313.         {
    314.             InputSystem.InputSystem.RemoveLayout(nameof(XRViveTracker));
    315.             InputSystem.InputSystem.RemoveLayout(nameof(XRTracker));
    316.         }
    317.  
    318.         //
    319.         // Summary:
    320.         //     A set of bit flags describing XR.InputDevice characteristics.
    321.         //"Left Foot", "Right Foot", "Left Shoulder", "Right Shoulder", "Left Elbow", "Right Elbow", "Left Knee", "Right Knee", "Waist", "Chest", "Camera", "Keyboard"
    322.         [Flags]
    323.         public enum InputDeviceTrackerCharacteristics : uint
    324.         {
    325.             TrackerLeftFoot = 0x1000u,
    326.             TrackerRightFoot = 0x2000u,
    327.             TrackerLeftShoulder = 0x4000u,
    328.             TrackerRightShoulder = 0x8000u,
    329.             TrackerLeftElbow = 0x10000u,
    330.             TrackerRightElbow = 0x20000u,
    331.             TrackerLeftKnee = 0x40000u,
    332.             TrackerRightKnee = 0x80000u,
    333.             TrackerWaist = 0x100000u,
    334.             TrackerChest = 0x200000u,
    335.             TrackerCamera = 0x400000u,
    336.             TrackerKeyboard = 0x800000u
    337.         }
    338.  
    339.         /// <inheritdoc/>
    340.         protected override void RegisterActionMapsWithRuntime()
    341.         {
    342.             ActionMapConfig actionMap = new ActionMapConfig()
    343.             {
    344.                 name = "htcvivetracker",
    345.                 localizedName = kDeviceLocalizedName,
    346.                 desiredInteractionProfile = profile,
    347.                 manufacturer = "HTC",
    348.                 serialNumber = "",
    349.                 deviceInfos = new List<DeviceConfig>()
    350.                 {
    351.                     new DeviceConfig()
    352.                     {
    353.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerLeftFoot,
    354.                         userPath = TrackerUserPaths.leftFoot
    355.                     },
    356.                     new DeviceConfig()
    357.                     {
    358.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerRightFoot,
    359.                         userPath = TrackerUserPaths.rightFoot
    360.                     },
    361.                     new DeviceConfig()
    362.                     {
    363.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerLeftShoulder,
    364.                         userPath = TrackerUserPaths.leftShoulder
    365.                     },
    366.                     new DeviceConfig()
    367.                     {
    368.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerRightShoulder,
    369.                         userPath = TrackerUserPaths.rightShoulder
    370.                     },
    371.                     new DeviceConfig()
    372.                     {
    373.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerLeftElbow,
    374.                         userPath = TrackerUserPaths.leftElbow
    375.                     },
    376.                     new DeviceConfig()
    377.                     {
    378.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerRightElbow,
    379.                         userPath = TrackerUserPaths.rightElbow
    380.                     },
    381.                     new DeviceConfig()
    382.                     {
    383.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerLeftKnee,
    384.                         userPath = TrackerUserPaths.leftKnee
    385.                     },
    386.                     new DeviceConfig()
    387.                     {
    388.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerRightKnee,
    389.                         userPath = TrackerUserPaths.rightKnee
    390.                     },
    391.                     new DeviceConfig()
    392.                     {
    393.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerWaist,
    394.                         userPath = TrackerUserPaths.waist
    395.                     },
    396.                     new DeviceConfig()
    397.                     {
    398.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerChest,
    399.                         userPath = TrackerUserPaths.chest
    400.                     },
    401.                     new DeviceConfig()
    402.                     {
    403.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerCamera,
    404.                         userPath = TrackerUserPaths.camera
    405.                     },
    406.                     new DeviceConfig()
    407.                     {
    408.                         characteristics = (InputDeviceCharacteristics.TrackedDevice) | (InputDeviceCharacteristics)InputDeviceTrackerCharacteristics.TrackerKeyboard,
    409.                         userPath = TrackerUserPaths.keyboard
    410.                     }
    411.                 },
    412.                 actions = new List<ActionConfig>()
    413.                 {
    414.                     new ActionConfig()
    415.                     {
    416.                         name = "grip",
    417.                         localizedName = "Grip",
    418.                         type = ActionType.Axis1D,
    419.                         usages = new List<string>()
    420.                         {
    421.                             "Grip"
    422.                         },
    423.                         bindings = new List<ActionBinding>()
    424.                         {
    425.                             new ActionBinding()
    426.                             {
    427.                                 interactionPath = TrackerComponentPaths.grip,
    428.                                 interactionProfileName = profile,
    429.                             }
    430.                         }
    431.                     },
    432.                     new ActionConfig()
    433.                     {
    434.                         name = "gripPressed",
    435.                         localizedName = "Grip Pressed",
    436.                         type = ActionType.Binary,
    437.                         usages = new List<string>()
    438.                         {
    439.                             "GripButton"
    440.                         },
    441.                         bindings = new List<ActionBinding>()
    442.                         {
    443.                             new ActionBinding()
    444.                             {
    445.                                 interactionPath = TrackerComponentPaths.squeeze,
    446.                                 interactionProfileName = profile,
    447.                             }
    448.                         }
    449.                     },
    450.                     new ActionConfig()
    451.                     {
    452.                         name = "menu",
    453.                         localizedName = "Menu",
    454.                         type = ActionType.Binary,
    455.                         usages = new List<string>()
    456.                         {
    457.                             "MenuButton"
    458.                         },
    459.                         bindings = new List<ActionBinding>()
    460.                         {
    461.                             new ActionBinding()
    462.                             {
    463.                                 interactionPath = TrackerComponentPaths.menu,
    464.                                 interactionProfileName = profile,
    465.                             }
    466.                         }
    467.                     },
    468.                     new ActionConfig()
    469.                     {
    470.                         name = "select",
    471.                         localizedName = "Select",
    472.                         type = ActionType.Binary,
    473.                         usages = new List<string>()
    474.                         {
    475.                             "SystemButton"
    476.                         },
    477.                         bindings = new List<ActionBinding>()
    478.                         {
    479.                             new ActionBinding()
    480.                             {
    481.                                 interactionPath = TrackerComponentPaths.system,
    482.                                 interactionProfileName = profile,
    483.                             }
    484.                         }
    485.                     },
    486.                     new ActionConfig()
    487.                     {
    488.                         name = "trigger",
    489.                         localizedName = "Trigger",
    490.                         type = ActionType.Axis1D,
    491.                         usages = new List<string>()
    492.                         {
    493.                             "Trigger"
    494.                         },
    495.                         bindings = new List<ActionBinding>()
    496.                         {
    497.                             new ActionBinding()
    498.                             {
    499.                                 interactionPath = TrackerComponentPaths.trigger,
    500.                                 interactionProfileName = profile,
    501.                             }
    502.                         }
    503.                     },
    504.                     new ActionConfig()
    505.                     {
    506.                         name = "triggerPressed",
    507.                         localizedName = "Trigger Pressed",
    508.                         type = ActionType.Binary,
    509.                         usages = new List<string>()
    510.                         {
    511.                             "TriggerButton"
    512.                         },
    513.                         bindings = new List<ActionBinding>()
    514.                         {
    515.                             new ActionBinding()
    516.                             {
    517.                                 interactionPath = TrackerComponentPaths.triggerClick,
    518.                                 interactionProfileName = profile,
    519.                             }
    520.                         }
    521.                     },
    522.                     new ActionConfig()
    523.                     {
    524.                         name = "trackpad",
    525.                         localizedName = "Trackpad",
    526.                         type = ActionType.Axis2D,
    527.                         usages = new List<string>()
    528.                         {
    529.                             "Primary2DAxis"
    530.                         },
    531.                         bindings = new List<ActionBinding>()
    532.                         {
    533.                             new ActionBinding()
    534.                             {
    535.                                 interactionPath = TrackerComponentPaths.trackpad,
    536.                                 interactionProfileName = profile,
    537.                             }
    538.                         }
    539.                     },
    540.                     new ActionConfig()
    541.                     {
    542.                         name = "trackpadTouched",
    543.                         localizedName = "Trackpad Touched",
    544.                         type = ActionType.Binary,
    545.                         usages = new List<string>()
    546.                         {
    547.                             "Primary2DAxisTouch"
    548.                         },
    549.                         bindings = new List<ActionBinding>()
    550.                         {
    551.                             new ActionBinding()
    552.                             {
    553.                                 interactionPath = TrackerComponentPaths.trackpadTouch,
    554.                                 interactionProfileName = profile,
    555.                             }
    556.                         }
    557.                     },
    558.                     new ActionConfig()
    559.                     {
    560.                         name = "trackpadClicked",
    561.                         localizedName = "Trackpad Clicked",
    562.                         type = ActionType.Binary,
    563.                         usages = new List<string>()
    564.                         {
    565.                             "Primary2DAxisClick"
    566.                         },
    567.                         bindings = new List<ActionBinding>()
    568.                         {
    569.                             new ActionBinding()
    570.                             {
    571.                                 interactionPath = TrackerComponentPaths.trackpadClick,
    572.                                 interactionProfileName = profile,
    573.                             }
    574.                         }
    575.                     },
    576.                     new ActionConfig()
    577.                     {
    578.                         name = "devicePose",
    579.                         localizedName = "Device Pose",
    580.                         type = ActionType.Pose,
    581.                         usages = new List<string>()
    582.                         {
    583.                             "Device"
    584.                         },
    585.                         bindings = new List<ActionBinding>()
    586.                         {
    587.                             new ActionBinding()
    588.                             {
    589.                                 interactionPath = TrackerComponentPaths.grip,
    590.                                 interactionProfileName = profile,
    591.                             }
    592.                         }
    593.                     },
    594.                     // Haptics
    595.                     new ActionConfig()
    596.                     {
    597.                         name = "haptic",
    598.                         localizedName = "Haptic Output",
    599.                         type = ActionType.Vibrate,
    600.                         usages = new List<string>() { "Haptic" },
    601.                         bindings = new List<ActionBinding>()
    602.                         {
    603.                             new ActionBinding()
    604.                             {
    605.                                 interactionPath = TrackerComponentPaths.haptic,
    606.                                 interactionProfileName = profile,
    607.                             }
    608.                         }
    609.                     }
    610.                 }
    611.             };
    612.  
    613.             AddActionMap(actionMap);
    614.         }
    615.  
    616.         protected override bool OnInstanceCreate(ulong xrInstance)
    617.         {
    618.             bool res = base.OnInstanceCreate(xrInstance);
    619.  
    620.             if (OpenXRRuntime.IsExtensionEnabled("XR_HTCX_vive_tracker_interaction"))
    621.             {
    622.                 Debug.Log("HTC Vive Tracker Extension Enabled");
    623.             }
    624.             else
    625.             {
    626.                 Debug.Log("HTC Vive Tracker Extension Not Enabled");
    627.             }
    628.  
    629.             return res;
    630.         }
    631.     }
    632.  
    633.  
    634. }
    635.  
     
  17. the_real_apoxol

    the_real_apoxol

    Unity Technologies

    Joined:
    Dec 18, 2020
    Posts:
    467
    I reached out to Valve to see if they have any insight.

     
    NTLX likes this.
  18. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    Hi there - thanks for the report.

    I'm not too familiar with the hooks available for OpenXR plugins in Unity, I can't see much from the code you have here but they all seem sound.

    Assuming you have properly mapped the physical tracker to a specific role in the SteamVR dashboard, one thing to note about tracker paths is you need to use full paths such as:
    /user/vive_tracker_htcx/role/left_foot/input/grip/pose

    There is an event we emit when trackers are connected, and if you can listen to this event somehow that'll show you when and which trackers are connected, here's a sample from the UE plugin:

    https://github.com/ValveSoftware/op...iveTracker/Private/OpenXRViveTracker.cpp#L151

    To get the poses, either your plugin or the engine needs to create the appropriate spaces for the device and do the appropriate openxr calls. In the UE plugin, we've handled most of the openxr calls for as less reliance on the engine as possible:

    https://github.com/ValveSoftware/op...iveTracker/Private/OpenXRViveTracker.cpp#L319

    https://github.com/ValveSoftware/op...iveTracker/Private/OpenXRViveTracker.cpp#L216

    If the engine can handle custom device spaces and action poses for you and you just provide the paths, that'd be ideal/easier of course if you're not keen on delving too deeply with openxr calls. @the_real_apoxol - is that something that can be accessed easily on the C# end?

    Our goal btw is to have engine plugins available for our and partner extensions available here:
    https://github.com/ValveSoftware/openxr_engine_plugins

    We have a UE plugin ready, and depending on resources (time mostly) looking at having a Unity and Godot one as well there. But certainly happy to take any Pull Requests/Community contributions :)
     
    Last edited: Jan 4, 2022
  19. the_real_apoxol

    the_real_apoxol

    Unity Technologies

    Joined:
    Dec 18, 2020
    Posts:
    467
    Most of this should already be handled by the Unity OpenXR plugin as the data is fed through the InputSystem. Currently it looks like what is stalling is that the `xrGetCurrentInteractionProfile` is failing which prevents the Unity OpenXR code from properly hooking up the device for that user path.

    As for handling the actual activation events that can be done but requires some native code be written to hook the event processing and spy on the event. It should not be necessary to get data flowing on an active device though.
     
  20. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    Thanks @the_real_apoxol! It does look like an issue on our end with xrGetCurrentInteractionProfile when tracker paths are sent. I've got a fix now and just testing. Will post here once we've released in a Beta.

    Since the engine is relying on this to hook up the device, i dont think there's a temporary workaround I can provide but will try to get the fix out asap.
     
  21. thep3000

    thep3000

    Unity Technologies

    Joined:
    Aug 9, 2013
    Posts:
    400
    Valve released fixes to SteamVR Beta channel yesterday which fixes the issues described in this thread.

    I tested @pmem 's script and had some changes to properly register characteristics / usages and fix offsets (attached). With this version of the script you can bind paths like `<XRViveTracker>{Left Foot}/devicePose/position` and `<XRViveTracker>{Left Foot}/devicePose/rotation` in the tracked pose driver and tracking works.

    ezgif-5-9e92515e82.gif

    There's a bit more work to do to make this script fully functioned - like listening for trackers to be connected / disconnected and reflecting that in the input system. We think that will require additional extension points but at least this should get you unblocked.
     

    Attached Files:

  22. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    I have followed up on this issue with a full minimal repro project, I have definitely stumbled on a bug where SteamVR OpenXR + Unity OpenXR plugin just produces a black screen in Unity when using a non SteamVR tracking headset and a SteamVR base-station tracked Vive Tracker in the same setup with SteamVR reporting
    Code (CSharp):
    1. ' CEF Local Resource Load Error: http://localhost:27062/app/image?app_key=system.generated.unity.exe&version=1.21.6 -> 404 (Not Found)'
    This is a blocker for using OpenXR for Vive trackers for my team.
    I have reported this to Unity with Case:
    1399332 and Steam Support with Ticket: HT-KB3B-G3TJ-RNNH

    How to reproduce it:

    Download this repro project:
    https://drive.google.com/file/d/1Qv0bpq4ZdZoCQU5A7edSoBQeCrl3CYe_/view?usp=sharing

    I have tested this with both Vive Cosmos and Oculus Quest 2
    1. Install Unity 2021.2.8f1
    2. Install SteamVR Beta 1.21.6
    3. Set up your Oculus Quest 2 via Oculus Link or Vive Cosmos (without SteamVR tracking faceplate)
    4. Set up at least 1 SteamVR base station and Vive tracker

    Now to set up multiple drivers with SteamVR, this is a supported feature of SteamVR
    Below steps you can follow this video if it helps, it is a popular setup for steamVR games that use Unity like VRChat where people use multiple steamvr supported devices in the same play space as kit is interchangeable


    5. Install OpenVR space calibration - https://github.com/pushrax/OpenVR-SpaceCalibrator/releases
    6. Go to your steam installation e.g. C:\Program Files\Steam\steamapps\common\SteamVR\resources\settings
    7. Open default.vrsettings with notepad or VS Code to edit
    8. Change 'requireHmd' value from true to false
    9. Change activateMultipleDrivers from false to true
    10. Save the file
    11. Open SteamVR with your tracker and headset of choice switched on + the steamVR base station
    12. Goto SteamVR settings - Startup/Shutdown - Choose startup overlay apps - enable Space Calibrator
    13. Goto SteamVR settings - Advanced settings - show
    14. Goto SteamVR settings - set steamvr as Current OpenXR runtime if it isn't already.
    15. Open OpenVR Space Calibrator through the steamVR overlays menu (SteamVR menu - third dot on the bottom right from the right, looks like a compass)
    16. Select reference space - your headset controller you are holding and choose the vive tracker in the target space.
    17. Choose calibration speed - slow and click start calibration to calibrate the play spaces then hold the tracker and controller together while drawing an infinity symbol with your hand in your play space to help calibration.
    18. Verify the tracker and controllers line up in the same play space, if not try calibration again or refer to this clip of the video:


    (We are nearly there!)
    You can watch my repro video of this here

    19. To repro now, turn on SteamVR, turn off the vive tracker and base station, just keep your headset on or ready
    20 Open the project in Unity 2021.2.8f1
    21. Verify in Project settings - XR Plug-In Management that OpenXR is the default target
    22. Verify in Project settings - XR Plug-In Management - OpenXR - Play Mode OpenXR Runtime set to System Default
    23. Also verify in Project settings - XR Plug-In Management - OpenXR that Oculus Touch Controller Profile and HTC Vive Tracker profile is in the list if you are using Oculus, if you are using Cosmos (make sure it is without the steamvr tracking faceplate add-on), you can add the Vive Cosmos controller profile but it will cause an error with SteamVR as SteamVR OpenXR doesn't support the Cosmos controller profile yet somehow so leave that off but make sure HTC Vive Tracker Profile is in the list
    24. Open Scenes - Controller sample, with just your headset on click play and verify the scene opens SteamVR for OpenXR and works fine for at least the headset tracking, Vive Cosmos as mentioned the controllers will not track either way (I will report that as a separate bug).
    25. Now, keep the scene running and switch on the SteamVR base station and Vive Tracker, wait for them to connect. If you open the steamVR overlay you should see the tracker show up while connected.
    26. Now the scene view should go black, open SteamVR - Developer - WebConsole to see logs for this reporting this error
    Code (CSharp):
    1. ' CEF Local Resource Load Error: http://localhost:27062/app/image?app_key=system.generated.unity.exe&version=1.21.6 -> 404 (Not Found)'
    27. If you stop play mode and try again the view will be black and nothing tracks, this will continue until you close SteamVR + Unity and just with only the headset on (no base station or trackers on) and repeat from step 19 of this repro.
    Refer to this repro video to see it at this timestamp exactly as soon as the vive tracker connects it all goes black
     
  23. the_real_apoxol

    the_real_apoxol

    Unity Technologies

    Joined:
    Dec 18, 2020
    Posts:
    467

    Everything looks good with your project from a Unity standpoint as far as I can tell, but I dont have a Vive Tracker to test with here. I would say if changing a setting in the Steam VR settings causes the screen to go black then its very likely a steam VR issue as the OpenXR plugin really isnt doing anything special with the vive tracker, it just looks like any other controller. Have to asked Valve about this issue yet? I will forward this link to valve to see if they have any ideas too.
     
  24. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    It might not even be a Vive tracker, it looks like the addition of two different tracking space devices in SteamVR over OpenXR either breaks something in SteamVR or Unity as Unity is the only place the screen goes black, all overlays work fine like SteamVR dashboard/Oculus/Vive overlay.

    Do you have a Vive wand to test with or similar? I only have a Cosmos/Quest 2 and Vive tracker + base station here currently.

    I have reported these to Unity with Case: 1399332 and Steam Support with Ticket: HT-KB3B-G3TJ-RNNH so I will report back if I have any updates. @thep3000 sorry to tag but if you have a moment would you be able to try out my project too?

    I have posted about this on the Vive forum here also although they aren't much help https://forum.vive.com/topic/12427-...enxr-causes-black-screen-on-cosmos-in-unity/#

    I have also posted on Valve's OpenXR Support forum here:
    https://steamcommunity.com/app/250820/discussions/8/3187988018476738869/
     
    Last edited: Feb 2, 2022
  25. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    I was just trying to get this to work with my ViveTracker on the latest SteamVR beta 1.21.6 but could not get it to work.

    I see all of the HTCViveTrackerOpenXR devices load into the Input Debug panel.
    upload_2022-2-3_23-33-43.png

    But none of them are recording any changes to their position and rotation data. Is there some additional setup I need to do?

    I tried setting my tracker to be the 'Waist' tracker under the SteamVR manage trackers menu, but that did not work.

    Is there something else necessary?
     
    ROBYER1 likes this.
  26. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    Same thing in my repro project in my post above. I think it is related to the black screen issue somehow as my very first attempt at using the script to get the vive tracker position/rotation tracked perfectly then it only worked once or twice very intermittently when I was minimising/reopening windows it randomly tracked position/rotation for a few frames as my tracker moved!

    I really hope both these issues can be investigated together as the black screen bug and the tracker not moving are both blockers for me.
     
  27. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    @the_real_apoxol Did you hear anything from Valve? I have spent the last 2 weeks trying to chase this issue through their Steam Support team who can't forward issues to devs, their SteamVR discussion forums the support team told me to post on are dead, their github repos are also dead and full of unanswered issues too.

    I have discovered this black screen issue happens with other OpenXR using Unity games like Starcaller, if you launch the game with an Oculus Quest 2/Vive Cosmos then turn on a vive tracker after, the game black screen/crashes just like the Unity editor.
     
  28. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    I've gone and ordered a Vive Cosmos Faceplate and controller to see if having an OpenVR headset running at the same time helps but with SteamVR null driver the Vive tracker still doesn't track in Unity like @techmage said.
     
  29. LucaSerafino

    LucaSerafino

    Joined:
    Aug 6, 2021
    Posts:
    3
    Can you please explain how to get information about position and rotation of trackers using that script? I'm using steamvr beta 1.21.8 and openxr last update, i can't see the tracker in input debugger or xr input debugger. I only need the position and rotation of left foot tracker, right foot tracker and chest tracker.
     
    ROBYER1 likes this.
  30. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    Having the same issue here can you try this project too? This is my example test project
    Download this repro project:
    https://drive.google.com/file/d/1Qv0bpq4ZdZoCQU5A7edSoBQeCrl3CYe_/view?usp=sharing

    I'm trying to get this issue escalated
     
    Immersive-Matthew likes this.
  31. LucaSerafino

    LucaSerafino

    Joined:
    Aug 6, 2021
    Posts:
    3
    I realized that i need to add the profile htc vive tracker under openxr settings. Now i can see the trackers but i have a big problem, if i add this profile open xr controller right and left hand are at the same position, i don't know why. @thep3000 did you have same issue?
     
    Last edited: Feb 21, 2022
    JoRouss likes this.
  32. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    Do your tracker position/rotations actually come through though? Mine are always values of 0 despite the tracker being active and the HTC vive tracker profile being active in the openXR Settings too.

    Even just a working reproducible project or package would go a long way to help us figure this out here.

    Can you also confirm this works in the repro project I posted above too?! I am trying to put together a working example of OpenXR + Vive trackers working in Unity.

    upload_2022-2-21_16-52-25.png
     
    Last edited: Feb 21, 2022
    Immersive-Matthew likes this.
  33. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
  34. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    Last edited: Feb 22, 2022
  35. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    I think there are completely TWO different issues here now.

    The OP's original question was around HTC Vive Tracker Support in OpenXR which is post #1 - #21

    Post #22 raises a completely different issue which is the mixing of two tracking systems in SteamVR. We have seen the forums posts and they are not being ignored, there's just a lot going on in the background that we're unable to share any details yet until some areas that are affected are resolved.

    I suggest @ROBYER1 that your issue be raised in a completely separate thread so it doesn't mix in with the original issue here.
     
  36. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    @runeberg-valve Thanks, I will keep discussion to the matter of trackers working here as I have some actual OpenVR tracked headsets arriving through a Vive Cosmos faceplate this week.

    Still having the same issue as @techmage here where the trackers don't provide position/rotation through Unity for some reason. We can see them in the input debugger but any connected trackers don't send any data through.
     
  37. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    Things to double check:
    - HTC Vive Tracker Profile is added to the Interaction Profiles List
    - Trackers are set an appropriate role

    upload_2022-2-23_8-11-19.png
     
  38. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    Yeah if you have the same issues with multidriver=false, then that defintiely is related to here.

    The issue with the "black screen" however, regardless of tracking status you were raising only happens in multidriver=true, which is a completely separate and unrelated issue to this one, and can just add unnecessary confusion for those who have a normal setup of lighthouse only devices.
     
    Last edited: Feb 22, 2022
  39. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    @runeberg-valve Is that using the same repro project I attached above in my other comments?

    I was using multipledrivers =true to allow the NULL driver to be used so I could test without a HMD so that could be it. There are a lot of uses in tools and plugins I am working on that do not actually require a HMD for this reason e.g. motion capture

    I show all of that here in this video on my comment above at 0:37, 1:37 and 1:56 I show

    - The tracker working in the SteamVR view, assigned as Left Foot.
    - HTC Vive tracker profile is set in OpenXR settings in Unity
    - SteamVR is running as OpenXR runtime also

    My only suspicion is that in this test environment I am using the SteamVR NULL driver just so that I can use Vive trackers without a HMD which is causing the issue due to multipledrivers being true not false.

    I can only assume that techmage had a similar setup as me here and you can see when I hit play in the project I get black screens a few times until it works as you mentioned that is an issue.
     
  40. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    I used the sample Controller Project from Unity. Yes I noticed you're using a headless setup from your screenshots and that would be related to the "black screen issue" with a CV based headset + Trackers (e.g. Oculus or Cosmos CV), the cause for that is different from any OpenXR Tracker related issues with normal lighthouse setups.

    Can you try with a lighthouse headset (Vive, Index, etc) and see if you're still getting issues?
     
    Last edited: Feb 22, 2022
  41. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    I have one arriving this week, I will try with the NULL driver though and report back soon when I do though. I'm going to reset my steamVR settings but just get NULL driver working without multipledrivers = true on so it is false to be sure (if that is possible). The biggest use case for my plugins I am making though is to use the vive trackers without a headset still so if there is an issue I found with the NULL driver I am pleased you have seen this!

    Edit: Seems NULL driver is it's own separate driver so I can't test until I have the Vive Cosmos faceplate on friday I guess. I'll report back then but I assume that works. Looking forward to a SteamVR beta fix for the issues identified. If you want to take this conversation offline feel free to DM me. Hope my posts here help others looking into this when migrating from working OpenVR Vive tracker setups to OpenXR.

    Edit 2: Trackers are working for lighthouse only headsets used with SteamVR through OpenXR, I can confirm the trackers work when using Vive Cosmos + External Tracking Faceplate on it.
     
    Last edited: Feb 23, 2022
    JoRouss likes this.
  42. LucaSerafino

    LucaSerafino

    Joined:
    Aug 6, 2021
    Posts:
    3
    Did you find a way to use vive controllers and vive trackers at the same time? I'm using openxr, steamvr 1.21.8 released yesterday, a vive pro with its controllers and three vive trackers. When i add to openxr the profile of vive tracker and also the profile of the vive controllers, xr input debugger show me the trackers correctly but right hand and left hand have always same position and rotation(the ones of the left controller)
     
    syedjawadakhtar, ROBYER1 and JoRouss like this.
  43. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    I can't help with this as I have a Vive Wand on the way but only one Vive Wand so I won't be able to repro this with 1 controller but I will report back if I can change the wand from left to right and check.

    Can you also verify the controllers work fine without the tracker in use? I don't see how they would interfere. Reproduce it by testing with the controllers only then try turning the tracker on does that cause it to mess up?
     
    Last edited: Feb 24, 2022
  44. JoRouss

    JoRouss

    Joined:
    Apr 1, 2014
    Posts:
    53
    I have the same behavior. In a working scene with 2 controllers, using the Index and only the Index profile, both controllers work fine. After adding the Tracker profile, both controllers show in the input window, but they're at the same position.

    I also can't get the trackers to send any data. They show up, they're set up as left foot in SteamVR Beta, but always at position 0.
     
    syedjawadakhtar likes this.
  45. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    If this is using the project I linked above, please disregard it as the player rig in that test scene is an old one and I messed around with things
     
  46. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    This leads me to ask when will this be added or is it something I can add right now? I would like to know if trackers are connected or disconnected.

    Edit: I have just seen that for over 2 years now, OpenXR doesn't support InputDevices.deviceDisconnected events, I went and made a new thread about that issue here. Right now I can't use OpenXR because of this. Another wonderful blocking issue!!!

    Reported at Unity bug (Case 1407649) [InputSystem][OpenXR] - Device disconnected events not firing - InputDevices.deviceDisconnected

    @thep3000 I found the Vive Tracker Disconnected events in the OpenXR runtime here
    https://www.khronos.org/registry/Op...Space));-,Example 2,-This example illustrates


    A vid of the issue in action:
     
    Last edited: Mar 1, 2022
  47. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    Same issue here. Seems there is a whole host of issues with tracker support right now which is still blocking me from using them!
     
    JoRouss likes this.
  48. JoRouss

    JoRouss

    Joined:
    Apr 1, 2014
    Posts:
    53
    No, that was using my own project.
     
  49. gems2020

    gems2020

    Joined:
    Jul 21, 2012
    Posts:
    6


    Same here. Is there no solution yet?
     
  50. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,454
    There is not. Sometimes you need to rattle the chain hard to cause a ruckus. I end up posting the issue everywhere and report a bug to Unity. Valve are slippery to get hold of directly (understandable as they are working hard internally) but their devs do pay attention to here and github issues.