我有3轴的加速度计值(通常只有重力包含介于-1.0和1.0之间的数据):
float Rx;
float Ry;
float Rz;
Run Code Online (Sandbox Code Playgroud)
我做了躯体计算,然后我得到每个轴的角度.
float R = sqrt(pow(Rx,2)+pow(Ry,2)+pow(Rz,2));
float Arx = acos(Rx/R)*180/M_PI;
float Ary = acos(Ry/R)*180/M_PI;
float Arz = acos(Rz/R)*180/M_PI;
Run Code Online (Sandbox Code Playgroud)
然后我在opengl中设置框角度的值
rquad = Arx;
yquad = Ary;
Run Code Online (Sandbox Code Playgroud)
哪个旋转我的盒子:
glRotatef(yquad,1.0f,0.0f,0.0f);
glRotatef(rquad,0.0f,1.0f,0.0f);
Run Code Online (Sandbox Code Playgroud)
它适用于半球.我想使用完整的球体,我知道我必须使用Arz值使其工作,但我不知道如何使用它进行此旋转.你可以帮帮我吗?
更新:最终答案在我的情况下:
rquad = -atan2(Rx/R, Rz/R)*180/M_PI;
yquad = -atan2(Ry/R, Rz/R)*180/M_PI;
Run Code Online (Sandbox Code Playgroud)
mat*_*teo 42
正确答案是:
Roll = atan2(Y, Z) * 180/M_PI;
Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI;
Run Code Online (Sandbox Code Playgroud)
资料来源:http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf(第10页,方程25和26)
uesp的回答是错误的.它看起来像一个可接受的近似值,直到俯仰和滚动都超过45度.
我可能假设一个不同的方向约定,但即使你以任何一致的方式交换轴和反转值,uesp的计算也永远不会是等价的.
Pan*_*rei 19
虽然matteo的答案是正确的,但它没有提供完整,完整的解决方案:公式是正确的:
Roll = atan2(Y, Z) * 180/M_PI;
Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI;
Run Code Online (Sandbox Code Playgroud)
但是,当音高为+ 90/-90度且X轴垂直向上/向下时,理想的加速度计标准化输出应为:
accX = -1 / accX = 1
accY = 0
accZ = 0
Run Code Online (Sandbox Code Playgroud)
这意味着一个roll angle of 0 degrees; 正确.但在实践中,加速度计输出是嘈杂的,你会得到更接近的东西:
accX = -1 / accX = 1
accY = 0.003
accZ = 0.004
Run Code Online (Sandbox Code Playgroud)
这可能看起来很小但是会导致滚动角度为~30 dregrees,这是不正确的.
显而易见的本能是过滤掉最后的数字,但这会影响精度,这并不总是可以接受的.
在参考应用笔记中非常好地解释了折衷方案,即在滚动公式中包含一小部分加速度计X轴读数:
Roll = atan2( Y, sign* sqrt(Z*Z+ miu*X*X));
sign = 1 if accZ>0, -1 otherwise
miu = 0.001
Run Code Online (Sandbox Code Playgroud)
这种方式引入的误差比前一种情况要小得多:在上述相同条件下测量滚动时的误差为2-3度.
我已经尝试了推荐的解决方案(matteo 的),虽然起初看起来效果很好,但我注意到当俯仰接近 90 度时(从大约 70 度开始,但在不同的手机上不一定一致),滚动突然激增。当俯仰角为 90 时,应该在 0 左右的滚转现在超过 100 并不断增加到 180。我试图想出一种方法来从数学上防止这种情况,如果我将滚转限制为 +90/-90 它行为正常,但我没有得到我想要的范围 (+180/-180): Math.atan2(y, Math.sqrt((x x) + (z z))) * (180/Math.PI))