如何实施最具成本效益的振动检测器

How to implement the most cost effective shake detector

我有一个应用需要在用户 phone 的屏幕打开时检测可能发生的抖动。我发现了很多关于如何检测抖动的例子。下面的示例是迄今为止最有趣的示例,它使用了 Google 代码并添加了重力组件。我的问题是,这段代码可以改进吗?抖动检测非常可靠,我没有得到任何误报。我最关心的是电池寿命的延长。

private static final int mMinimumForce   = 5;
private static final int mShakeFrequency = 500;
private static final int mMovesRequired  = 4;
private float[] mGravity                 = { 0.0f, 0.0f, 0.0f };
private float[] mAcceleration            = { 0.0f, 0.0f, 0.0f };
private static final int mXAxis          = 0;
private static final int mYAxis          = 1;
private static final int mZAxis          = 2;
private long mCurrentTime                = 0;
private long mLastTime                   = 0;
private int mMoveCount                   = 0;
private final float mAlpha               = 0.8f;

public void onSensorChanged(SensorEvent event)
{
        if(event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
        {
            return;
        }


        // Set linear acceleration
        // Gravity components of x, y, and z acceleration
        mGravity[mXAxis] = mAlpha * mGravity[mXAxis] + (1 - mAlpha) * event.values[mXAxis];
        mGravity[mYAxis] = mAlpha * mGravity[mYAxis] + (1 - mAlpha) * event.values[mYAxis];
        mGravity[mZAxis] = mAlpha * mGravity[mZAxis] + (1 - mAlpha) * event.values[mZAxis];

        // Linear acceleration of x, y, z with gravity effect removed
        mAcceleration[mXAxis] = event.values[mXAxis] - mGravity[mXAxis];
        mAcceleration[mYAxis] = event.values[mYAxis] - mGravity[mYAxis];
        mAcceleration[mZAxis] = event.values[mZAxis] - mGravity[mZAxis];


        // Set maximum linear acceleration amongst x, y, z
        float maxAcceleration = mAcceleration[mXAxis];

        if (mAcceleration[mYAxis] > maxAcceleration)
        {
            maxAcceleration = mAcceleration[mYAxis];
        }

        if (mAcceleration[mZAxis] > maxAcceleration)
        {
            maxAcceleration = mAcceleration[mZAxis];
        }


        // Process shake
        if (maxAcceleration > mMinimumForce)
        {
            Log.d(TAG, "Shake detected");

            mCurrentTime = System.currentTimeMillis();

            if (mLastTime == 0)
            {
                mLastTime = mCurrentTime;
            }

            long elapsedTime = mCurrentTime - mLastTime;

            if (elapsedTime > mShakeFrequency)
            {
                    mLastTime  = 0;
                    mMoveCount = 0;
            }
            else
            {
                mMoveCount++;

                if (mMoveCount > mMovesRequired)
                {
                    Log.d(TAG, "Shake moves detected: " + mMovesRequired);
                    // do some work here

                        mLastTime  = 0;
                        mMoveCount = 0;
                }
            }
        }
}

Google I/O 文档提供了有关您所有问题的重要信息。这是一份这样的文件。 https://dl.google.com/io/2009/pres/W_0300_CodingforLife-BatteryLifeThatIs.pdf

您关于浮点数学的观点是正确的。虽然您的代码在计算方面做的不多,但以高频率不断调用它可能会对 CPU.

造成负担

你关于使用电池的加速度计的观点。虽然每个设备的功耗都不同,并且该设备的使用方式与陀螺仪的使用方式不尽相同,但如果在一整天的活动屏幕使用中不间断使用,将会显示出明显的差异。

我同意按照最高标准和效率进行编码是好的,无论您是否发现电池使用情况有明显差异。这只是一个好公民。如果我的 phone 还能多出 30 分钟,就给我吧!!!

我对您的代码的建议,实际上只是反映了 Google 的建议以及您已经谈到的许多建议。

  • 以尽可能低的轮询率注册您的侦听器。
  • 根据不满足的轮询率,在代码开头用过滤器补充点一,以立即return。 (当前时间 - 上次)> POLL_RATE。这很重要,因为 Android 可能不遵守在侦听器中注册的轮询率。
  • 如果可以的话,喜欢整数数学而不是浮点数。
  • 调查是否可以先使用 AlarmManager and/or 其他更具成本效益的传感器,然后再使用加速度计。我不知道你的情况是否可行,但值得一试。