如何根据手机加速度计算距离
Posted
技术标签:
【中文标题】如何根据手机加速度计算距离【英文标题】:How to calculate distance based on phone acceleration 【发布时间】:2010-12-01 21:08:32 【问题描述】:我想构建类似的东西,但使用的是安卓手机:http://www.youtube.com/watch?v=WOt9mb5QqRs
我已经构建了一个通过套接字发送传感器信息的应用程序(仍在为 android 寻找一个好的 websocket 实现)。我打算使用该信息与网络应用程序进行交互,例如,我将能够根据手机移动移动图像。 问题是我试图根据加速度计数据计算距离,但结果非常糟糕。我想知道是否有人可以帮助我计算正确的方程式,但首先,是否有可能做到这一点?
到目前为止,我使用的是以下等式:
velocity = acceleration * time;
distance = velocity * time + (acceleration * time^2) / 2;
然后我根据显示器屏幕分辨率将距离从每秒米转换为像素。
每次我收到传感器数据时,都会在浏览器中使用 javascript 计算,大约每 80 毫秒。
【问题讨论】:
【参考方案1】:基础很简单。在模拟世界中,您使用连续数学:
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 同步以纠正这种漂移。
其次,加速度计测量的是力,而不是运动。任何一种力都可以测量。我提到了重力,但它也测量与桌子摩擦引起的颠簸,你的脉搏,你的心跳和呼吸导致你的手轻微颤抖,任何东西。好消息是,从长远来看,所有这些力量都会平均化,公式仍然是正确的。但从短期来看,这意味着你的阅读会很吵。人们想出了很多技巧来使用诸如 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)/t
和 a = (v2-v1)/t
)获取导出的距离并进行反向计算,您应该会返回加速度读数。
【讨论】:
好的,现在我可以评论了,这没有任何意义,速度(最初为 0)如何等于加速度?时间呢?加速 9m/s² 表示手机将在一秒钟内达到该速度,但我每 ~ 80 毫秒测量一次速度 物理学就是这样运作的。也许你忘记了速度只是加速度的积分。当时间变得离散时,积分就变成了总和。 对时间和值离散的值求和与积分不同。您必须考虑加速度值之间的时间/间隔。 @Ashwin:我强烈建议尝试我的方法作为测试,看看计算是否最终与实际长度一致。然后将其与您的代码进行比较。也就是说,把你的代码中的0.5去掉再试试。 @Amir 这个公式确实是简单而幼稚的工作。它基本上有太多的假设,使其不切实际。【参考方案2】:最大速度 = 时间 * 加速度。 平均速度 = 最大速度 / 2。 行驶距离 = 平均速度 * 时间。
行驶距离 = 时间 * 时间 * 加速度 / 2。
【讨论】:
这是正确答案。上面的答案是错误的。他说你在 0-80 毫秒内从 0 加速到 9m/s2。但要计算他的距离。 v=9*0.80,d=v*0.80。 v 是第 80 毫秒的最终速度。他通过将最终速度乘以 80 毫秒来计算距离。 @Ashwin 我知道这真的很老了,但他实际上是对的!查找黎曼和。上面的答案是错误的,因为它处理的是连续加速的情况,而不是像电话那样离散测量的间隔。干杯。以上是关于如何根据手机加速度计算距离的主要内容,如果未能解决你的问题,请参考以下文章