3d加速度计计算方向

我有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; 

正确答案是:

 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的计算也永远不会是等价的。

虽然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度。

我已经尝试了推荐的解决方案(matteo’s),虽然它起初看起来效果很好,但我注意到当音高接近90度时(从大约70度开始但不一定在不同的手机上保持一致),滚动突然激增。 当音高达到90时,应该在0左右的滚动现在超过100且持续增加到180.我试图想办法在数学上防止这种情况,如果我将滚动限制在+ 90 / -90它行为正常,但我没有得到我想要的范围(+ 180 / -180):Math.atan2(y,Math.sqrt((x x)+(z z)))*(180 / Math.PI))

对于roll ,我发现你可以使用arctan(y/sqrt(X*X)+(z*z))这将给出-90/90这是航空标准而不会给出音高问题

我使用以下计算将加速度计读数转换为滚动和俯仰值:

 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);