3d加速度计计算方向

时间:2010-09-20 20:05:09

标签: c math opengl

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

5 个答案:

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