admin管理员组

文章数量:1406926

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>

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/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!

Share Improve this question edited Jan 5, 2017 at 18:53 calipoop asked Jan 5, 2017 at 18:15 calipoopcalipoop 85211 silver badges33 bronze badges 2
  • Does this CodePen help? It uses Quaternion angles over Euler angles to avoid gimbal lock. – u01jmg3 Commented Jan 15, 2017 at 11:00
  • @u01jmg3 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. – calipoop Commented Jan 15, 2017 at 20:14
Add a ment  | 

2 Answers 2

Reset to default 8

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.

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://stackoverflow./a/52264991/5853749

本文标签: javascriptDeviceOrientationEvent how to deal with crazy gamma when beta approacheshits 90degStack Overflow