如何实施最具成本效益的振动检测器
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 其他更具成本效益的传感器,然后再使用加速度计。我不知道你的情况是否可行,但值得一试。
我有一个应用需要在用户 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 其他更具成本效益的传感器,然后再使用加速度计。我不知道你的情况是否可行,但值得一试。