提问人:Cheloute 提问时间:7/26/2023 最后编辑:Cheloute 更新时间:7/27/2023 访问量:93
如何从加速度估计角度和从三维角度估计加速度?
How to estimate angles from acceleration and acceleration from angles in 3 dimensions?
问:
我在很多论坛上看到了几个关于这个问题的问题,但没有一个能让我足够清晰或精确地满足我的需求。或者我只是不理解他们,这是另一种可能性。
好吧,考虑一下设备(不是 android 设备,这里不需要实时处理)采取的几个加速度计测量(3 维)(m/s^2)。我正在从文本文件中读取这些值,需要将它们转换为度数。
我尝试的第一个代码是:
private static final double G = 9.81;
private static final double RAD_TO_DEG = 180.0 / Math.PI;
private double[] calculateAngles(double acX, double acY, double acZ) {
double accelX = acX * G;
double accelY = acY * G;
double accelZ = acZ * G;
double angleX = Math.atan2(accelX, Math.sqrt(accelY * accelY + accelZ * accelZ)) * RAD_TO_DEG;
double angleY = Math.atan2(accelY, Math.sqrt(accelX * accelX + accelZ * accelZ)) * RAD_TO_DEG;
double angleZ = Math.atan2(Math.sqrt(accelX * accelX + accelY * accelY), accelZ) * RAD_TO_DEG;
return new double[] { angleX, angleY, angleZ };
}
这段代码“似乎”给了我一个很好的结果。至少,可信的。我将加速度计放在固定位置,注意到随机测量给出的 3 个角度(更新:我说的是偏航、俯仰和滚动),将加速度计旋转 90º(大约),其中一个角度将这个或多或少的 90º 添加到其值中。
尽管如此,我尝试的逆运算根本不起作用:
private static final double RAD_TO_DEG = 180.0 / Math.PI;
private static double[] calculateAccelerations(double angleX, double angleY, double angleZ) {
// Convertir les angles en radians
double radianAngleX = angleX * DEG_TO_RAD;
double radianAngleY = angleY * DEG_TO_RAD;
double radianAngleZ = angleZ * DEG_TO_RAD;
double accelX = Math.tan(radianAngleX) / Math.sqrt(1.0 + Math.tan(radianAngleX) * Math.tan(radianAngleX) + Math.tan(radianAngleY) * Math.tan(radianAngleY));
double accelY = Math.tan(radianAngleY) / Math.sqrt(1.0 + Math.tan(radianAngleX) * Math.tan(radianAngleX) + Math.tan(radianAngleY) * Math.tan(radianAngleY));
double accelZ = Math.tan(radianAngleZ) * Math.sqrt(1.0 + Math.tan(radianAngleX) * Math.tan(radianAngleX) + Math.tan(radianAngleY) * Math.tan(radianAngleY));
return new double[]{accelX/G, accelY/G, accelZ/G};
}
如果我采用我的初始加速度计值,估计偏航、俯仰和滚动,将它们转换为加速度......怎么说...发明这些值会更准确。第一个问题是......为什么?我在这里看不出我的错误。
在谷歌上搜索替代方案,卡尔曼滤波器是我能找到的最相关的结果。我在 common-math3 (Apache) 中找到了一个实现,但我不明白它是如何工作的,也不明白它是否真的适用于这里。
我需要的是读取这些加速度计值,并在加速度计以不同方式定位的情况下估计这些值。为此,我需要能够“估计”加速度计的位置,添加我需要添加的角度以虚拟更改其方向,然后返回加速度计值。
理想情况下是 Java 建议,但欢迎任何帮助,包括不可知论的解释!
答:
首先,你希望你的角度测量什么?从您在 中的计算来看,您似乎在计算:calculateAngles
- 角度X
- “X”加速度计测量值与地板之间的角度。(也就是说,当“x”测量值笔直向上时,你得到 90°,当“x”测量值指向地平线时,你得到 0°,当“x”测量值指向地板时,你得到 -90°)
- 角度Y
- “Y”加速度计测量值与地板之间的角度。(也就是说,当“y”测量值笔直向上时,你会得到 90°,以此类推,与“x”相同)
- 角度Z
- “Z”加速度计测量与直线向上之间的角度。(也就是说,当“z”测量值笔直向上时,你得到 0°,当“Z”测量值指向地平线时,你得到 90°,当“z”测量值指向地板时,你得到 180°)
鉴于您的后续评论,我将假设这些实际上是您希望测量的角度,并从那里继续。
现在,由于您在该方法中使用的函数 (),将所有三个加速度度量乘以相同的常数不起作用;因此,可以在 中省略该步骤。atan2
* G;
calculateAngles
因此,首先,我将该函数更改为:
private double[] calculateAngles(double acX, double acY, double acZ) {
double angleX = Math.atan2(acX, Math.sqrt(acY * acY + acZ * acZ)) * RAD_TO_DEG;
double angleY = Math.atan2(acY, Math.sqrt(acX * acX + acZ * acZ)) * RAD_TO_DEG;
double angleZ = Math.atan2(Math.sqrt(acX * acX + acY * acY), acZ) * RAD_TO_DEG;
return new double[] { angleX, angleY, angleZ };
}
现在,为了反转计算,我们需要使用这样一个事实,即当我们完成时,我们应该有三个加速度的平方之和应该等于平方。此外,我们想利用这一事实来反转G
angle = Math.atan2(y, x);
通常不应使用该函数,而应改为使用:tan
x = Math.cos(angle);
y = Math.sin(angle);
// then multiple x and y by some scaling factor
所以:
private static double[] calculateAccelerations(double angleX, double angleY, double angleZ) {
// Convertir les angles en radians
double radianAngleX = angleX * DEG_TO_RAD;
double radianAngleY = angleY * DEG_TO_RAD;
double radianAngleZ = angleZ * DEG_TO_RAD;
double acX = Math.sin(radianAngleX);
double acY = Math.sin(radianAngleY);
double acZ = Math.cos(radianAngleZ);
// use this if you need the sum of the acceleration squared to be G squared
//double scaling = G / Math.sqrt(acX*acX + acY*acY + acZ*acZ);
// EDIT Cheloute: with scaling = 1, that works perfectly for my use case
double scaling = 1;
return new double[]{acX*scaling, acY*scaling, acZ*scaling};
}
请注意,尽管该函数会吐出任意三个输入角度的值,但这并不意味着任何三个角度组合实际上都是有效的;例如,您设置测量的方式仅限于介于 和 之间,我很确定可以确定或至少将其缩小到只有两种可能性。calculateAccelerations
angleY
-abs(abs(angleX)-90)
abs(abs(angleX)-90)
angleX
angleY
angleZ
但是,如果您进给的角度,您应该恢复原始加速度,或者足够接近。calculateAccelerations
calculateAngles
评论
下一个:如何在网格网格上应用积分函数
评论