C语言 3d 加速度计计算方向

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3755059/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:28:27  来源:igfitidea点击:

3d Accelerometer calculate the orientation

cmathopengl

提问by Roland Soós

I have accelerometer values for the 3 axes (usually when there is only gravity contains data between -1.0 and 1.0 ):

我有 3 个轴的加速度计值(通常当只有重力包含 -1.0 和 1.0 之间的数据时):

  float Rx;
  float Ry;
  float Rz;

I make some calculations, then I get the angles for each axis.

我做了一些计算,然后得到每个轴的角度。

  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;

Then I set the values for the box angles in opengl

然后我在 opengl 中设置盒子角度的值

rquad = Arx;
yquad = Ary;

Which rotates my box:

哪个旋转我的盒子:

glRotatef(yquad,1.0f,0.0f,0.0f);
glRotatef(rquad,0.0f,1.0f,0.0f);

It works on a hemisphere. I would like to use the full sphere and I know that I have to use the Arz value to make it work, but I don't know how can I use that for this rotation. Could you help me?

它适用于半球。我想使用完整的球体,我知道我必须使用 Arz 值才能使其工作,但我不知道如何将其用于此旋转。你可以帮帮我吗?

Update: The final answer is in my case:

更新:最终答案是在我的情况下:

  rquad = -atan2(Rx/R, Rz/R)*180/M_PI;
  yquad = -atan2(Ry/R, Rz/R)*180/M_PI;

回答by matteo

The correct answer is:

正确答案是:

Roll = atan2(Y, Z) * 180/M_PI;
Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI;

Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf(page 10, Eqn. 25 & 26)

来源:http: //www.freescale.com/files/sensors/doc/app_note/AN3461.pdf(第 10 页,方程 25 和 26)

uesp's answer is wrong. It looks like an acceptable approximation until pitch and roll both go above 45 degrees.

uesp 的回答是错误的。在俯仰和滚转都超过 45 度之前,它看起来是一个可接受的近似值。

I may be assuming a different orientation convention, but even if you swap axes and invert values in any consistent way, uesp's computations will never be equivalent.

我可能假设了不同的方向约定,但即使您以任何一致的方式交换轴和反转值,uesp 的计算也永远不会等效。

回答by Pandrei

While matteo's answer is correct, it does not provide the full, complete solution: The formulas are correct:

虽然 matteo 的答案是正确的,但它没有提供完整、完整的解决方案:公式是正确的:

Roll = atan2(Y, Z) * 180/M_PI;
Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI;

However, when pitch is +90/-90 degrees and the X axis is vertical pointing up/down, the ideal accelerometer normalized output should be:

但是,当俯仰为 +90/-90 度且 X 轴垂直向上/向下时,理想的加速度计归一化输出应为:

accX = -1  / accX = 1 
accY = 0
accZ = 0

Which means a roll angle of 0 degrees; correct. But in practice, the accelerometer output is noisy and you would get something closer to:

这意味着一个roll angle of 0 degrees; 正确的。但在实践中,加速度计的输出是嘈杂的,你会得到更接近的东西:

accX = -1  / accX = 1 
accY = 0.003
accZ = 0.004

This might seem small but it will cause the roll angle to be ~30 dregrees which is not correct.

这可能看起来很小,但它会导致滚动角为 ~30 dregrees,这是不正确的。

The obvious instinct would be to filter out the last digits, but this would affect precision, which is not always acceptable.

显而易见的直觉是过滤掉最后一位数字,但这会影响精度,这并不总是可以接受的。

The compromise, which is very well explained in the reference app note, is to include a very small percentage of the accelerometer X axis reading in the formula for roll:

参考应用说明中很好地解释了折衷方案,即在滚动公式中包含非常小的加速度计 X 轴读数百分比:

Roll  = atan2( Y,   sign* sqrt(Z*Z+ miu*X*X));
sign  = 1 if accZ>0, -1 otherwise 
miu = 0.001

The error introduced this way is dramatically smaller than the previous case: 2-3 degrees when measuring roll under the same conditions explained above.

以这种方式引入的误差比前一种情况小得多:在上述相同条件下测量滚动时,误差为 2-3 度。

回答by FaithNoMan

I've tried the recommended solution (matteo's), and while it seemed to work great at first, I noticed that when the pitch approaches 90 degrees (starting at around 70 degrees but not necessarily consistent across different phones), the roll suddenly surges. When the pitch is at 90 the roll that should be around 0 is now at over 100 and keeps increasing to 180. I'm trying to think of a way to mathematically prevent this, if I restrict the roll to +90/-90 it behaves normally but I don't get the range I want (+180/-180): Math.atan2(y, Math.sqrt((xx) + (zz))) * (180/Math.PI))

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

回答by Ian Bloomfield

For roll, I have found you can use arctan(y/sqrt(X*X)+(z*z))this will give roll -90/90which is aviation standard without giving the pitch issue

因为roll,我发现你可以使用arctan(y/sqrt(X*X)+(z*z))它来提供-90/90航空标准的滚转而不会产生俯仰问题

回答by uesp

I use the following calculations to convert our accelerometer readings into roll and pitch values:

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

Roll = atan2( sqrt(Y*Y + X*X), Z) * 180/M_PI;
Pitch = atan2( sqrt(X*X + Z*Z), Y) * 180/M_PI;

You may need to swap the X/Y/Z values or translate the Roll/Pitch depending on how your accelerometers are defined. To use them in the display them it is a simple matter of:

您可能需要根据加速度计的定义方式交换 X/Y/Z 值或平移滚动/俯仰。要在显示中使用它们,很简单:

glRotatef (Pitch, 0.0f, 0.0f, 1.0f);
glRotatef (Roll,  1.0f, 0.0f, 0.0f);