DeviceOrientationEvent: how to deal with crazy gamma when beta approaches/hits 90deg?
Asked Answered
T

2

8

Anyone with DeviceOrientationEvent experience and a phone/tablet handy?

Running the following code snippets on a gyroscope-having device, I notice gamma (rotating left/right along y-axis) gets large and unpredictable as beta approaches 90deg (device pointing straight up). I assume this is gimbal-lock.

var data, raf, alpha = document.getElementById("alpha"),
  beta = document.getElementById("beta"),
  gamma = document.getElementById("gamma");

window.addEventListener("deviceorientation", processData);
window.addEventListener('click', togglePause);
updateText();

function processData(e) {
  data = e;
}

function updateText() {
  if (data) {
    alpha.textContent = Math.round(data.alpha);
    beta.textContent = Math.round(data.beta);
    gamma.textContent = Math.round(data.gamma);
  }
  raf = requestAnimationFrame(updateText);
}

function togglePause(e) {
  if (raf) {
    cancelAnimationFrame(raf);
    raf = null;
    window.removeEventListener("deviceorientation", processData);
  } else {
    window.addEventListener("deviceorientation", processData);
    raf = requestAnimationFrame(updateText);
  }
}
body {
  font: normal 30px/200% sans-serif;
  margin: 20px;
  cursor: default;
}
span {
  font-size: 50px;
  vertical-align: middle;
}
<body>
  alpha: <span id="alpha">null</span>
  <br>beta: <span id="beta">null</span>
  <br>gamma: <span id="gamma">null</span>
  <br>[tap to pause/resume]
</body>

https://jsfiddle.net/1us8p1ad/show

My question: How can I predictably track left/right device orientation using gamma? Gamma is the only value I care about - no 3d space needed.

I looked into using rotation matrix and quaternion as discussed here, but not getting valid results. In fact, the examples on the author's github page also break when beta hits 90deg! Same with this MDN tutorial - check it on your device: when it's straight up, the ball goes bonkers. How have these aberrations gone unnoticed!

Tingaling answered 5/1, 2017 at 18:15 Comment(2)
Does this CodePen help? It uses Quaternion angles over Euler angles to avoid gimbal lock.Digenesis
@Digenesis thanks for your reply - that codepen however still runs into a lock issue - you'll notice if you hold your device straight up and down, twisting it has no effect. In contrast, if you lay your device flat, twisting it left/right produces the desired result.Tingaling
T
7

It seems gimbal lock is a known real-world obstacle, and many applications avoid it by restricting device motion (not possible in my case).

My solution was to convert the alpha/beta/gamma values into a rotation matrix, and then pull data from one of the matrix values. The code I used was given here from W3C.

Note, I tried using Quaternions but the resulting values were not helpful for motion in just 1 direction.

Tingaling answered 15/1, 2017 at 20:17 Comment(6)
Due you have any code you can share which produces the rotation matrix?Digenesis
@Digenesis of course! I updated my answer to include the source of the code I used. The entire discussion on that page is very relevant to understanding my issue.Tingaling
Thank you, you saved my ass. It is not working perfectly for me, gamma is still little jumpy, but it is acceptable.Plater
Gamma got a little bit better. Before it was almost unusable at that angle, now it's just bearable... Still can't figure out how to fix it completely though.Senator
Okay, so I got this to work, no gimbal lock, but you need to use the W3C code. FULLTILT.js uses this code internally, but realize if you're using THREE.js you'll need to convert from row major to column major matrix format before applying it to your Vector3 or Object3D. For some reason I got still gimbal lock when taking the alpha, gamma, beta myself, and throwing them into a THREE.Matrix3...Senator
I had to switch to {"type": "game"} in FULLTILT.js and now I get the same crazy gamma asymptote behavior :cSenator
F
0

try to google 'gimbal lock' for the reason,

and don't just focus on gamma itself, part of its angle value goes to alpha axis, you need to recalculate taking consider of other 2 dimensions

see similar question: https://mcmap.net/q/507148/-fixing-ios-safari-javascript-39-deviceorientation-39-event-irregularity

Ferrocene answered 10/9, 2018 at 20:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.