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