android - 如何根据手机加速度计算距离

标签 android distance formula acceleration

我想构建这样的东西,但使用安卓手机:http://www.youtube.com/watch?v=WOt9mb5QqRs

我已经构建了一个通过套接字发送传感器信息的应用程序(仍在寻找适用于 android 的良好 websocket 实现)。我打算使用该信息与网络应用程序进行交互,例如,我将能够根据手机移动来移动图像。
问题是我试图根据加速度计数据计算距离,但结果非常糟糕。我想知道是否有人可以帮助我计算出正确的方程式,但首先,是否可以这样做?

到现在为止,我正在使用以下等式:
velocity = acceleration * time;distance = velocity * time + (acceleration * time^2) / 2;
然后我根据显示器屏幕分辨率将距离从米每秒转换为像素。

每次我收到传感器数据时,这是在浏览器中用 javascript 计算的,大约是 80 毫秒。

最佳答案

基础很简单。在模拟世界中,您使用连续数学,即:

velocity = integrate(acceleration)
distance = integrate(velocity)

在数字世界中更容易,您可以使用离散数学,其中积分变为求和:
velocity = sum(acceleration)
distance = sum(velocity)

只需不断地将您读取的所有加速度值相加,最终就会得到距离。

最大的问题是在地球上,由于重力,地球上有一个恒定的向下加速度,大约为 10m/s/s。弄清楚矢量的哪一部分是重力是困难的部分。

顺便说一句,重力是加速度计检测倾斜的方式。因此,无论您怎么做,除非您可以独立于加速度计计算倾斜度(例如在陀螺仪的帮助下),否则您的代码将主要测量倾斜度而不是距离。

哈!我刚刚从上次声明中意识到很多 iPhone 应用程序无法在太空中运行 :-P

补充回答:

根据 OP 发布的“评论”(作为此答案下方或上方的答案),看来我需要提供进一步的解释。实现真的非常简单,不熟悉数学的人会认为它一定比这更复杂。伪代码如下:
// Set distance to zero at start-up:
var distance_X = 0
var velocity_X = 0

function update_acceleration_X (acceleration_X) {
    velocity_X = velocity_X + acceleration_X
    distance_X = distance_X + velocity_X
}

// To use the distance value just read the distance_X variable:
function get_distance_X_and_reset () {
    x = distance_X
    distance_X = 0
    return x
}

除非您将距离变量重置为零,否则始终从软件首次启动的位置开始测量距离。必须不断读取加速度计(最好以加速度计本身测量力的速率)并相应地更新速度和距离的值。当您想知道与起点的距离时,只需读取距离变量即可。

几件事:任何程度的倾斜,无论多么轻微,都会增加漂移。这意味着除非不断跟踪倾斜角度本身,否则在一个方向或另一个方向上总会有少量的恒定加速度。即使是配备高精度加速度计和陀螺仪的核潜艇,因为 GPS 无法在水下工作,也需要定期浮出水面并与 GPS 同步以纠正这种漂移。

其次,加速度计测量的是力,而不是运动。测量任何类型的力。我提到了重力,但它也测量由与 table 摩擦引起的颠簸,你的脉搏,你的心跳和呼吸导致你的手轻微颤抖,任何东西。好消息是,从长远来看,所有这些力量都会趋于平均,公式仍然是正确的。但从短期来看,这意味着你的阅读会很吵。人们已经想出了很多技巧,可以使用 Weiner 和 Kalman 滤波器之类的东西来最小化这种噪音。

第三,您可能已经注意到,加速度计读数不是恒定的。我不是简单的意思是每次阅读它们时的值都不同,这是显而易见的,但它也会改变读数之间的值。我们错过的每个值都会影响我们的准确性,因此尽可能多地读取这些值很重要。现在,好消息是,从长远来看,所有这些由缺失值引起的错误应该平均化,因为它们主要是由急动或振动引起的,我们的公式仍然是正确的。但这再次意味着,在短期内,这会给我们的系统增加噪音。如果您使用像卡尔曼滤波器这样的良好预测滤波器,那么它应该能够解决这一问题,但较弱的滤波器可能需要一些帮助。这样做的一种方法是将每个加速度读数与前一个读数平均。请注意,它必须是之前的“真实”读数,而不是之前的平均读数。

比这更高的精度进入惯性测量单元 (IMU) 和惯性制导以及许多相当繁琐的矢量和矩阵数学领域。不过,有一些开源项目正在这样做(不到 10 年前,这些东西是严格的军事用途,因为潜艇和巡航导弹都在使用它们)。

这些 Sparkfun 文章在底部有一些不错的链接和一些引用代码:

http://www.sparkfun.com/products/9268

http://www.sparkfun.com/products/8454

希望这一切都有帮助。如果其他人有任何可能有帮助的文章的链接,请发表评论。

例子

当然,如果您想要实际单位,则需要缩放采样率。例如,以 9m/s/s 的速度加速 80ms 意味着您的速度是 (9m/s/s * 0.08s) = 0.72m/s .假设您不关心单位,则简化了上述伪代码。最终值仍然将距离表示为一个数字,只是该数字与任何现实世界的测量单位几乎没有关系。您可以简单地在校准到像素值的末尾应用缩放函数。无论如何,这里有一个真实世界单位的例子来阐明正在发生的事情:
given the following acceleration readings:
9m/s/s
3m/s/s
0m/s/s
0m/s/s
0m/s/s
-5m/s/s
-7m/s/s

assuming an 80ms sample rate
we can derive the following velocities:
0.72m/s (what you get from accelerating 9m/s for 80ms)
0.96m/s
0.96m/s
0.96m/s
0.96m/s
0.56m/s
0m/s

from that we can derive the following distances:
57.6mm (what you get from moving at 0.72m/s for 80ms)
134.4mm
211.2mm
288mm
364.8mm
409.6mm

现在,如果您采用导出的距离并照常进行反向计算( v = (s2-s1)/ta = (v2-v1)/t ),您应该会得到加速度读数。

关于android - 如何根据手机加速度计算距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4329164/

相关文章:

algorithm - 确定 map 中的比例因子

math - 找出两个圆之间的距离

python - 如何迭代坐标列表并计算它们之间的距离?

extjs - 绑定(bind)商店更改公式

java - android 获取 android 库上下文与应用程序上下文

google-maps - 用于地理编码(街道位置!)和下一次距离计算的包

math - 计算坡度 - 仅用角度

android - 操作栏下拉打开和关闭项目样式

android - RecyclerView 2 Columns with CardView

java - 关于eclipse中src文件夹的问题