如何只使用加速度计来找到速度?

14

只使用手机(Android)内置的加速计,我该如何找到它的速度?

我一直在进行这个问题的数学实验,但是无论我提出什么函数,都会导致速度呈指数级增长。 我从假设开始工作,即在应用程序启动时,手机处于静止状态。这应该可以确保至少粗略地找到速度。

我有相当扎实的物理和数学背景,因此在这里的任何概念上都不应该遇到任何困难。

我该怎么做?


@Ignacio 什么?恒定加速意味着速度线性增加。 - Imran
你有任何可行的解决方案吗?能否指向或分享代码? - VenomVendor
嗨,你有没有考虑关闭这个问题? - Mr. Developerdude
2
你的手机使用的传感器只有豌豆大小,成本大约2美元,是通过将微小的金属片蚀刻成粗糙弹簧和重物的形状制成的。它足以知道你拿着手机的方向以及是否在晃动。但它永远不会成为一个合格的惯性传感器组件。相信我,误差累积得非常快,这是一个无望解决的问题。(来源:我曾在亚马逊工作时负责嵌入式固件来完成这项任务。) - Edward Falk
2
我刚刚发现了这个精彩的视频,它解释了为什么这很难:https://www.youtube.com/watch?v=C7JQ7Rpwn2k#t=23m20s - Edward Falk
8个回答

9
那将取决于加速度的大小和持续时间。轻微而长时间的加速度是可测量的,但任何突然增加的加速度,随后保持恒定速度,都会使您的测量结果相当困难且容易出错。假设有恒定的加速度,则公式非常简单:a = (V1-V0)/t。因此,如果知道时间和加速度,并假设V0 = 0,则V1 = a*t。在更现实的情况下,您可能没有恒定的加速度,因此应计算每个测量的ΔV,并将所有速度变化相加以获得最终速度。始终考虑到您不会拥有连续的加速度数据,因此这是最可行的方法(即真实数据与积分数学理论相比)。无论如何,在最佳情况下,您最终将得到非常高的误差率,因此我不建议使用这种方法来依赖真实速度的任何应用程序。

5
如果没有人注意到的话,V1 = a*t! - erdomester

8

首先,您需要从加速度计数据中消除重力加速度。然后,只需对加速度进行积分即可得到速度。不要忘记,加速度和速度是向量而不是标量,并且您还需要跟踪手机在空间中的旋转,以正确确定加速度向量相对于计算出的速度向量的方向。


你能从编程角度解释一下吗,或者给我一个链接,让我可以了解更多细节吗? - VenomVendor
5
TYPE_LINEAR_ACCELERATION传感器会提供去掉重力加速度的加速度数据,这很好。TYPE_ROTATION_VECTOR传感器会提供设备方向的四元数,可以轻松转换为3x3旋转矩阵。在每个时间片,使用旋转矩阵将加速度转换为三维空间中的向量。随着时间的推移进行积分以获得加速度(另一个向量),再对其进行积分可得到相对于起始位置的位置信息(假设初始速度为零)。然后去酒吧喝一杯因为便宜的传感器使一切都无望了。 - Edward Falk

5
除了同意上面所有伟大答案中提出的合理论点外,我没有别的办法,但是如果你像我这样务实型的人,我需要想出一种解决方案,以某种方式让它起作用。
我遇到了和你类似的问题,发现网上没有找到任何解决方案后,我决定自己制作一个。我只需要一个简单的“倾斜”输入来控制游戏,因此这个解决方案可能不适用于更复杂的需求,但我决定分享它,以防其他人正在寻找类似的东西。
注意:我在这里贴出了我的全部代码,可以免费用于任何目的。
基本上,在我的代码中,我会查找加速度计传感器。如果未找到,则会禁用倾斜反馈。如果存在加速度计传感器,我会查找磁场传感器,如果存在,则通过组合加速度计和磁场数据推荐的方式获取倾斜角度。
public TiltSensor(Context c) {
    man = (SensorManager) c.getSystemService(Context.SENSOR_SERVICE);
    mag_sensor = man.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    acc_sensor = man.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    has_mag = man.registerListener(this, mag_sensor, delay);
    has_acc = man.registerListener(this, acc_sensor, delay);
    if (has_acc) {
        tiltAvailble = true;
        if (has_mag) {
            Log.d("TiltCalc", "Using accelerometer + compass.");
        }
        else {
            Log.d("TiltCalc", "Using only accelerometer.");
        }
    }
    else {
        tiltAvailble = false;
        Log.d("TiltCalc", "No acceptable hardware found, tilt not available.");
        //No use in having listeners registered
        pause();
    }
}

如果只有加速度计传感器存在,我会退而求其次,累加连续阻尼(乘以0.99)的加速度,以消除任何漂移。对于我的简单倾斜需求来说,这个方法非常有效。
@Override
public void onSensorChanged(SensorEvent e) {
    final float[] vals = e.values;
    final int type = e.sensor.getType();
    switch (type) {
        case (Sensor.TYPE_ACCELEROMETER): {
            needsRecalc = true;
            if (!has_mag) {
                System.arraycopy(accelerometer, 0, old_acc, 0, 3);
            }
            System.arraycopy(vals, 0, accelerometer, 0, 3);
            if (!has_mag) {
                for (int i = 0; i < 3; i++) {
                    //Accumulate changes
                    final float sensitivity = 0.08f;
                    dampened_acc[i] += (accelerometer[i] - old_acc[i]) * sensitivity;
                    //Even out drift over time
                    dampened_acc[i] *= 0.99;
                }
            }
        }
            break;
        case (Sensor.TYPE_MAGNETIC_FIELD): {
            needsRecalc = true;
            System.arraycopy(vals, 0, magnetic_field, 0, 3);
        }
            break;
    }
}

总之,我只想重申这并不是以任何方式“正确”的代码,它只是作为游戏输入的一种简单方法。要使用此代码,我只需执行以下操作(是的,奇怪的常量很糟糕):

Ship ship = mShipLayer.getShip();
mTiltSensor.getTilt(vals);
float deltaY = -vals[1] * 2;//1 is the index of the axis we are after
float offset = ((deltaY - (deltaY / 1.5f)));
if (null != ship) {
    ship.setOffset(offset);
}

享受吧!


2
将加速度积分得到速度是一个不稳定的问题,几秒钟后您的误差会发散。手机加速度计也不是很准确,这并没有帮助,有些加速度计不能轻易区分倾斜和平移,这种情况下您真的会遇到麻烦。

2
手机中的加速度计对于这样的任务几乎没有用处。您需要高精度、漂移非常低的加速度计——这是手机所不具备的。最多只能获得几秒钟的有用结果,或者非常幸运地获得一两分钟的结果,之后结果就变得毫无意义了。
此外,您需要一个三轴陀螺仪,用于在正确方向上积分速度。一些手机有陀螺仪,但它们在漂移和精度方面甚至比加速度计更差。
然而,可能有一个有用的应用程序,即将加速度计与陀螺仪或磁罗盘结合使用,以填补GPS缺失数据。每次GPS提供良好的定位时,都会重置位置、速度和方向的初始条件,并且加速度计将提供数据,直到下一个有效的GPS定位。

假设我想获取倾斜信息以控制游戏。在这种情况下,我可以做出许多假设。例如,我可以假设用户以某种方式握住设备。那么,不可能以某种方式平滑数据,使突然的变化凸显出来,并成为游戏输入的有用信息吗? - Mr. Developerdude

2
重力会破坏你所有的测量结果。手机静止时,会经历高恒定向上(是的,向上)的加速度。加速度计不能区分加速度和重力(从技术上讲,它们是相同的),因此在几秒钟后就会达到极高的速度。 如果您从不稍微倾斜加速度计,那么您可以从z轴(或指向上/下的任何轴)中减去恒定的重力拉力,但这很不可能。 基本上,您必须使用陀螺仪/磁强计和加速度计的复杂系统来计算重力的精确方向,然后减去加速度。

1
传感器融合技术可以为您过滤掉这些杂乱数据。只需使用TYPE_LINEAR_ACCELERATION传感器即可。 - Edward Falk

1

v = 积分(a) ?

一般来说,我认为加速度计的不准确性会使这变得相当困难。


取决于不准确性的类型。你可以进行线性误差校准,不是吗? - William T. Mallard

-2
如果手机静止不动,那么加速度为零,速度也就是0。你可能需要从GPS获取位置数据,并获取相关的时间样本,计算出速度距离与时间的关系。

是的,在应用程序启动时速度为0。我从这个点开始校准它。 - Mark D
“静止不动”实际上应该很容易检测出来。如果加速度计(使用TYPE_LINEAR_ACCELERATION)的输入非常恒定,那么手机可能没有被操作。 - Edward Falk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接