如何仅使用加速度计找到速度?

Mar*_*k D 10 math android accelerometer

仅使用内置加速度计的手机(Android),如何才能找到它的速度?

我一直在修补这个数学,但无论我想出什么功能都会导致速度呈指数增长.我的假设是,在应用程序启动时,手机处于静止状态.这绝对应该能够找到速度(至少粗略地).

我在物理和数学方面也有不错的背景,所以我对这里的任何概念都不会有任何困难.

我该怎么办?

Ano*_*mie 7

首先,您必须从加速度计数据中移除由于重力引起的加速度.然后,只需要集成加速度来获得速度.不要忘记加速度和速度是正确的矢量,而不是标量,并且您还必须跟踪手机在空间中的旋转,以正确地确定加速度矢量相对于计算的速度矢量的方向.

  • TYPE_LINEAR_ACCELERATION传感器会在重力过滤时为您提供加速度,这样很好.TYPE_ROTATION_VECTOR将为您提供四元数的设备方向,可以轻松转换为3x3旋转矩阵.在每个时间切片,使用旋转矩阵将加速度转换为3空间中的矢量.随着时间的推移对其进行积分以获得加速度(另一个向量)并整合**以获得相对于起始位置的位置.(这一切都假设初始速度为零.)然后去酒吧喝一品脱,因为这对于便宜的传感器来说都是无望的. (4认同)

Ale*_*dam 7

这实际上取决于加速度和持续时间.一个温和的,长的加速度可以测量,但加速度的任何突然增加,然后是恒定的速度,将使您的测量非常困难并且容易出错.

假设恒定加速度,公式非常简单:a =(V1-V0)/ t.因此,知道时间和加速度,并假设V0 = 0,则V1 = a*t

在更现实的世界中,您可能不会有恒定的加速度,因此您应该为每次测量计算Delta V,并添加所有这些速度变化以获得最终速度.始终认为您不会有连续的加速度数据,因此这是最可行的方式(即实际数据与积分数学理论).

无论如何,即使在最佳情况下,您最终也会得到非常高的误差范围,因此我不建议将这种方法用于任何真正依赖于实际速度的应用程序.

  • 如果没有人注意到,V1 = a*t! (5认同)

Len*_*and 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,如果仅存在加速度计传感器,我会回退到累积加速度,该加速度会连续阻尼(乘以 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

总之,我只是重复一遍,这可能在任何方面都不是“正确的”,它只是作为游戏的简单输入。要使用此代码,我只需执行如下操作(是的,魔术常量是不好的 mkay):

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);
}
Run Code Online (Sandbox Code Playgroud)

享受!


And*_*eas 1

v = 积分 (a) ?

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