设备方向事件:当beta接近/达到90度时如何处理疯狂的伽马值?

8

有DeviceOrientationEvent经验并且有手机/平板电脑的人吗?

在装备陀螺仪的设备上运行以下代码片段,我注意到当beta接近90度(设备正指向上方)时,gamma(沿y轴左右旋转)变得很大且不可预测。 我认为这是万向节锁定

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

我的问题是:如何可预测地使用gamma跟踪设备的左右方向?我只关心Gamma值-不需要3D空间。

我研究了使用旋转矩阵和四元数的方法,如此处所述,但没有得到有效的结果。事实上,作者在github页面上的示例在beta达到90度时也会出现错误!这个MDN教程也一样-在您的设备上检查它:当它竖直时,球会发疯。这些异常怎么会被忽视了呢!


这个 CodePen 有帮助吗?它使用四元数角度而不是欧拉角度来避免万向锁问题。 - u01jmg3
@u01jmg3 感谢您的回复 - 但是那个 codepen 仍然遇到了锁定问题 - 如果您将设备直立,扭曲它没有任何效果。相比之下,如果您将设备放平,左/右扭曲会产生所需的结果。 - calipoop
2个回答

7
似乎万向节锁是一个已知的现实障碍,许多应用通过限制设备运动来避免它(在我的情况下不可能)。我的解决方案是将alpha/beta/gamma值转换为旋转矩阵,然后从其中一个矩阵值中提取数据。我使用的代码可以在W3C 这里 找到。注意,我尝试使用四元数,但结果对于单向运动并不有用。

你有任何可以分享的产生旋转矩阵的代码吗? - u01jmg3
1
@u01jmg3 当然可以!我更新了我的答案,包括我所使用的代码源。在该页面上的整个讨论非常相关,可以帮助理解我的问题。 - calipoop
谢谢你,你救了我一命。对我来说它还不完美,伽玛仍然有点抖动,但是可以接受。 - Tomasz Nowak
Gamma有所改善。之前在那个角度几乎无法使用,现在只是能够勉强使用...但仍然无法完全解决问题。 - Cobertos
1
好的,所以我让它工作了,没有万向节锁定,但你 需要 使用 W3C 代码。FULLTILT.js 在内部使用此代码,但请注意,如果您正在使用 THREE.js,则需要在将其应用于您的 Vector3Object3D 之前将其从行主要矩阵格式转换为列主要矩阵格式。由于某种原因,当我自己获取 alpha、gamma、beta 并将它们放入 THREE.Matrix3 中时,仍然出现万向节锁定问题... - Cobertos
我不得不在FULLTILT.js中切换到{"type": "game"},现在我得到了相同的疯狂伽马渐近行为:c - Cobertos

0

尝试谷歌搜索“万向节锁定”以了解原因,

不要只关注伽马本身,其角度值的一部分进入阿尔法轴,您需要重新计算并考虑其他两个维度

参见类似问题: https://dev59.com/2X3aa4cB1Zd3GeqPj_Lj#52264991


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接