cancel
Showing results for 
Search instead for 
Did you mean: 

Touch Controllers Gimbal Lock issues

Beloudest
Explorer
Hi I'm using Unity and I am struggling to use the transform.localRotation values returned from the Touch Controller tracking. Essentially depending on the initial transform rotation of the controllers when they are spawned will affect the polarity/signs of the values in a chaotic nature. 

e.g. localRotation.y will sometimes equal -0.1 and other times 0.1 even when pointing in the same direction. 

It's rather confusing...

This seems like a gimbal lock issue, has anyone ever experienced this problem. I can't rely on the localRotation to use for tilt control mechanics in my game as my vehicle turning will be randomly inverted 50% of the time.

Anyone wise to it. Thanks?  
5 REPLIES 5

Beloudest
Explorer


Transform.localRotation
is a quaternion. Please use euler Angles to convert it to the XYZ rotation you are expecting for this activity.


Hi firstly thanks for replying. It's been driving me nuts this problem, great to have support. 😉
 
I have tried this today but the transform.rotation.localEuler values also suffer from gimbal lock jumps in values making them unusable, Quaternions are the solution to gimbal lock yet the touch controllers act sporadically on spawn.

I use the Vive too and this is never a problem somehow. The controllers will always give a reliable value no matter the spawn orientation.    

The issue is defiantly related to the spawn position of my controllers. Hold them in one orientation on spawn the values are as expected, hold them 45 degrees in another direction on spawn the values are now inverted thus inverting the game controls.  To me it's as though the orientation goes past different gimbal lock positions which can invert future values during gameplay. 

The only solution I can think of now is to detect the various permutations of start orientation and somehow invert the values I'm using if required. I will revisit eulers as you say but they are just as confusing and random for tilt-based controls. I also recall Unity saying eulers are unreliable due to gimbal lock jumps hence why Quaternions were invented. 

Is it possible the Steam VR  Unity SDK does something with Matrix conversions to keep Quaternion values useful? It's beyond me but there are interesting functions in the Utilities I lack understanding of. 

I'll keep studying, looks like I need to learn hardcore algebra again. Thanks. 

Beloudest
Explorer
Ok, you can ignore my long message above. I read your answer once more and grasped what you meant.

This is the most unobvious solution but it actually worked. I can make sense of why now, the new Quaternion has a centred Vector3 to act as the vector to rotate around. The controller spawning position is variable and thus changes the point at which the rotations are based from, something like that anyway. It works and it's taken 2 days to solve so once again thanks.

Hope this code can help others and the above is good for SEO. 😉

Quaternion quatStable = Quaternion.Euler( transform.localRotation.eulerAngles);
Debug.Log ("this is unreliable " + transform.localRotation + " that is reliable " + quatStable );
helicopter.VRInputYaw (quatStable.y * yawTwistAmount);



Beloudest
Explorer


I did some quick followup research and found this unity thread here:

http://answers.unity3d.com/questions/573035/avoiding-gimbal-lock.html

A developer there stated this about a similar issue: 

Transform.RotateAround, you don't even need to bother going into Quaternions, though you can also do it with Quaternion.AngleAxis on each axis and multiplying them together (quaternion multiplication applies each rotation in turn).


Thanks but that's for rotating a gameObject itself. All I wanted is a reading of the localRotation of the controllers to be reliable, a value of Y inverting from -1 to 1 on spawn randomly is impossible to code with. My method above in the end suffered very bad gimbal lock issues. Unity does something strange internally. Basically using eulerAngles will always present gimbal lock values that jump. When I used the eulerAngles from localRotation to create a new Quaternion it suffered from very bad jumps from the locking as it was based from eulerAngles XYZ.

There was one positive thing about my method above is the new Quaternion would always give a solid Y value that never inverts randomly due to spawn orientation even if the localRotation used to create it does invert.

So essentially I can now detect when I should manually invert my values passed to the vehicle controls. This code will sum it up:

(note transform.localRotation does not suffer gimbal lock jumping, quatStable will. I've not put the below through enough tests to be 100% this is a final solution...)


Quaternion quatStable = Quaternion.Euler( transform.localRotation.eulerAngles);
if (quatStable.y != transform.localRotation.y) { // sometimes polar opposite
helicopter.VRInputYaw (transform.localRotation.y * yawTwistAmount * -1);
} else {
helicopter.VRInputYaw (transform.localRotation.y * yawTwistAmount);
}



I've got to be honest, the Oculus Touch controllers are jumping around like crazy too.

It's almost unusable for tilt-based controls anyway as the tracking is very unstable. My GUI indicators show this really well by just leaving the controllers in a static position. The sliders jump around like a FFT meter. I was hoping to align the controls with the Vives behaviour to create a great multiplayer eco system. I might have to just use the joysticks. Shame really but it's all about exploration. 

vrdaveb
Oculus Staff
> The controller spawning position is variable and thus changes the point at which the rotations are based

Are you using OVRCameraRig.leftHandAnchor.localRotation or UnityEngine.VR.InputTracking.GetLocalRotation(UnityEngine.VR.VRNode.LeftHand)? Note that in both cases, the rotation is relative to OVRCameraRig.trackingSpace, which is in turn dependent on your tracking origin - OVRManager.instance.trackingOriginType. If it's eye-level, then the base position and rotation corresponds to your initial head pose when the app starts. If it's floor-level, then it corresponds to the "default pose" you set during Rift setup - the part where you stand in the middle of your tracking area and pull the Touch controller's trigger.

Quaternion.Euler( transform.localRotation.eulerAngles)

I wouldn't expect this to help. One of the nice things about quaternions is that you can smoothly interpolate between them. The sign shouldn't flip randomly - it's probably an issue with your frame of reference.

the tracking is very unstable

This shouldn't happen when Touch is set up properly. How many sensors are you using? Are they plugged into USB 2 or USB 3 ports? Do all of the sensors report that they're healthy in the Oculus desktop app?

Beloudest
Explorer

vrdaveb said:

This shouldn't happen when Touch is set up properly. How many sensors are you using? Are they plugged into USB 2 or USB 3 ports? Do all of the sensors report that they're healthy in the Oculus desktop app?

Hey thanks for all the info. I shall check out the configuration of my setup. I got a little busy recently so I've not had a chance to get into the Touch setup. That information you provided is really helpful and I think I follow your suggestions. I must admit Quaternions were not my strong point but I have done my studies recently and think I will be able to crack it now. I'll ping back if I have troubles, hopefully not 🙂 thank you.