Search Unity

Sporadic controller tracking issues with Immersive mixed reality headset by Acer

Discussion in 'AR/VR (XR) Discussion' started by jjennings1990, Sep 20, 2017.

  1. jjennings1990

    jjennings1990

    Joined:
    Oct 25, 2012
    Posts:
    132
    Hey everybody I've recently begun working with the Immersive Mixed reality headset developed by Acer , Our machines have had a challenging time with the headsets unfortunately so It's hard for me to tell what is an error on my side in terms of implementation and what is the product of our hardware and the headsets themselves not getting along .


    To the issue at hand I've been working on a small demo Utilizing both the Motion controllers and the Xbox One controller for input , I followed this guide on the Mixed Reality developer portal which has been very straight forward and have managed to get basic user inputs working . Unfortunately I'm having a problem where the inputs are working and a Tracking loss message comes up and I have to restart the editor , sometimes re-initialize the mixed reality portal, or just disconnect the headset entirely and reconnect to get the headset to possibly respond to Xbox one controller or Motion controller inputs.


    A few times the rest of the controller was unresponsive but I would press the windows button on the motion controller which would somehow send me to the home environment and upon re-entering unity through the projected window in the environment the Inputs would work again . Other times the Inputs initialize correctly and after a few button presses a hard crash happens to the editor as whole . A few times the inputs worked perfectly fine only to stop working when I'd run the editor again just a minute later. This Is becoming quite frustrating to work around and I'd like to know if perhaps there is something I'm doing wrong that may be contributing to the Tracking / input loss?


    I'm including my basic Input button class code just in case I am overlooking something in my implementation . any help or advice is appreciated, thank you. I'm using Events for the Motion controller inputs and the Input manager of unity for the Xbox One controller inputs



    Code (CSharp):
    1. using System.Collections;
    2.  
    3. using System.Collections.Generic;
    4.  
    5. using UnityEngine;
    6.  
    7. using UnityEngine.UI;
    8.  
    9. using UnityEngine.XR.WSA.Input;
    10.  
    11.  
    12. public class OVRImmersiveButton :OVR3DButton  {
    13.  
    14.  
    15.     // Use this for initialization
    16.  
    17.     void Start () {
    18.  
    19.         base.Start ();
    20.  
    21.         //Debug.Log("Source detected , Initializing Immersive button!!!!!");
    22.  
    23.         InteractionManager.InteractionSourcePressed += InteractionManager_SourcePressed;
    24.  
    25.         InteractionManager.InteractionSourceDetected += InteractionManager_SourceDetected;
    26.  
    27.     }
    28.  
    29.  
    30.     void Update(){
    31.  
    32.  
    33.         base.Update ();
    34.  
    35.  
    36.         if (base.crosshair.TargettedObject == this.gameObject) {
    37.  
    38.             //Debug.Log ("Looking at:" + this.gameObject.name);
    39.  
    40.             bool xbox_a = Input.GetButtonDown ("Button A");
    41.  
    42.             if (xbox_a) {
    43.  
    44.                 Debug.Log ("Input button Recieved!");
    45.  
    46.                 base.Click ();
    47.  
    48.             }
    49.         }
    50.     }
    51.  
    52.  
    53.  
    54.     void InteractionManager_SourceDetected(InteractionSourceDetectedEventArgs state)
    55.     {
    56.  
    57.         Debug.Log("Source detected , Initializing Immersive button!!!!!");
    58.  
    59.         // Source was detected
    60.  
    61.         // state has the current state of the source including id, position, kind, etc.
    62.     }
    63.  
    64.  
    65.  
    66.  
    67.     void InteractionManager_SourcePressed(InteractionSourcePressedEventArgs state)
    68.     {
    69.         // state has information about:
    70.  
    71.         // targeting head ray at the time when the event was triggered
    72.  
    73.         // whether the source is pressed or not
    74.  
    75.         // properties like position, velocity, source loss risk
    76.  
    77.         // source id (which hand id for example) and source kind like hand, voice, controller or other
    78.  
    79.         Debug.Log("Touch Pad Pressed!!!!! " + " targetted object == " +base.crosshair.TargettedObject.name  + " this.gameObject == " +this.gameObject.name );
    80.  
    81.         if ((state.pressType == InteractionSourcePressType.Touchpad) && (base.crosshair.TargettedObject == this.gameObject)) {
    82.  
    83.             Debug.Log("This button Pressed!!!!!");
    84.  
    85.             base.Click ();
    86.         }
    87.     }
    88. }
     
  2. jjennings1990

    jjennings1990

    Joined:
    Oct 25, 2012
    Posts:
    132
    So I found a " hack " on the mixed reality forums that if you hold the unity editor play button and lower the headset over your eyes ( which then auto launches the app as it switches from desktop mode to Mixed reality mode) the headset tracks the controllers at a much more consistent rate. It's worked well for me for the last hour .

    Secondly I think the Event implementation was too much for my machine . I have about 30 buttons checking against a pressed event every time the user presses the touchpad button . It was just way easier and I think far less processor intensive to check the State of the buttons , see if the current button is active and then check within the update loop for the current device input state .

    Here is how It looks in my code which is in my update loop:

    Code (CSharp):
    1.  
    2. var interactionSourceState = InteractionManager.GetCurrentReading ();
    3.  
    4.  
    5.             if (interactionSourceState [0].touchpadPressed) {
    6.                 Debug.Log("Touch Pad Pressed!!!!! " + " targetted object == " +base.crosshair.TargettedObject.name  + " this.gameObject == " +this.gameObject.name );
    7.                 base.Click ();
    8.             }
    Implementing it this way over Events hasn't seen any crashes thankfully.
     
  3. craveiro

    craveiro

    Joined:
    Dec 10, 2014
    Posts:
    4
    It's very unstable for me using Rewired and the same approach as yours (get state with current reading and then check pressed states). Feels like if I mash the buttons it sometimes crashes not only the app but also freezes Unity (without any error messages) like you are saying. I'm using 5.6 MRTP, are you on that or 2017.x?

    Have you tried building and testing in Visual Studio (master)? Is it any more stable?

    BTW, how are you converting axis values from double to float? I'm using
    Convert.ToSingle(state.controllerProperties.thumbstickY) and am wondering whether it's possible hitting Infinity on conversion is causing the crash. Though it's probably very unlikely.
     
    Last edited: Sep 21, 2017
    jjennings1990 likes this.
  4. craveiro

    craveiro

    Joined:
    Dec 10, 2014
    Posts:
    4
    Not sure how it is performing for you but things improved for me doing the two following things:

    1. Bailing out if there are no states:
    Code (CSharp):
    1.  
    2. private void OnInputUpdate() {
    3.         InteractionSourceState[] interactionSourceStates = InteractionManager.GetCurrentReading();
    4.         if (interactionSourceStates.Length == 0) {
    5.             return;
    6.         }
    7. [...]
    8.  
    2. And there are usually two states, so loop over them:
    Code (CSharp):
    1.  
    2. [...]
    3.         // There should be two states
    4.         for (int i=0; i < interactionSourceStates.Length; i++) {
    5.             InteractionSourceState state = interactionSourceStates[i];
    6.             //Left
    7.             if (state.source.handedness == InteractionSourceHandedness.Left) {[...]}
    8.             //Right
    9.             if (state.source.handedness == InteractionSourceHandedness.Right) {[...]}
    10.        }
    11. [...]
    12.  
     
  5. jjennings1990

    jjennings1990

    Joined:
    Oct 25, 2012
    Posts:
    132
    I'm working on 2017.x at the moment and This implementation has been much more stable for me . As for how we convert our inputs I am not at the moment and haven't experienced any crashes, our inputs are very simple as well though this is an example of how I'm implementing it at the moment :

    Code (CSharp):
    1. var interactionSourceState = InteractionManager.GetCurrentReading ();
    2.  
    3.             if (interactionSourceState.Length > 0) {
    4.            
    5.                 if (interactionSourceState [0].thumbstickPosition.x >= 0.1f) {
    6.                     Debug.Log (" Left Stick moved Left");

    With a similar statement being written for a Right stick press.

    I did encounter an issue where by doing the check in the update loop , you have the potential for overlapping inputs , where you press one button , it closes and then a button below it may get pressed as well , I ended up creating an input manager that essentially locks input ( for button presses only) to ensure only one object can be interacted with per frame .

    I didn't realize the state source had enums for the different hand types though thanks for that info !