【问题标题】:Android: Accelerometer false detectionAndroid:加速度计误检
【发布时间】:2009-10-27 13:31:19
【问题描述】:

我有一个代码 sn-p 来检测加速度计的运动。它有时会通过正确检测轻微运动来工作,但有时它也会在我让设备闲置时检测到运动。 Android 上的内置加速度计检测是否存在任何问题?

我使用 HTC G-1 设备。我的代码 sn-p 如下。如何解决这个问题,以便在设备空闲时检测到设备的小动作但检测不到任何东西?

private static final int SHAKE_THRESHOLD = 50;

public void onSensorChanged(int sensor, float[] values) {

    if (sensor == SensorManager.SENSOR_ACCELEROMETER) {
        long curTime = System.currentTimeMillis();
        // only allow one update every 100ms.
        if ((curTime - lastUpdate) > 100) {
            long diffTime = (curTime - lastUpdate);
            lastUpdate = curTime;

            x = values[SensorManager.DATA_X];
            y = values[SensorManager.DATA_Y];
            z = values[SensorManager.DATA_Z];

            float speed = Math.abs(x+y+z - last_x - last_y - last_z) / diffTime * 10000;

            if (speed > SHAKE_THRESHOLD) { 
                long curTime = System.currentTimeMillis();
                long diff = (curTime - shakeTime);              
                shakeTime = curTime;

                if (myFlagIgnoreShakeDetection==true)  //Caused unneccessary accelerometer   
                                                       //notification looping when device is idle
                   return;

                // Doing something...
            }
         last_x = x;
         last_y = y;
         last_z = z;
        }

    }

}

【问题讨论】:

  • 您可能想要对加速度进行适当的矢量加法:jerk = Math.sqrt(Math.pow(x-last_x, 2) + Math.pow(y-last_y, 2) + Math.pow(y-last_y, 2) pow(z-last_z, 2)) / diffTime * 10000;否则,0.29 m/s^2 的加速度变化将触发您的阈值。
  • 我更改了代码 sn-p 上的缩进,以更好地说明左大括号和右大括号的位置。
  • 另一个问题...lastUpdateshakeTimelast_xlast_ylast_z 在某处初始化?它们有哪些初始值?
  • 私有浮点 x, y, z;私人浮动last_x,last_y,last_z;长摇时间=-1;私有的 long lastUpdate = -1;
  • 最后我能够理解是什么导致了问题,但在 HTC 设备上进行测试时发现它,而不是通过代码。当我使用该设备一段时间然后将其闲置时,它在场景中按预期工作(没有错误事件)。场景是,我需要让设备稍微移动(在我的桌子上稍微用力)以保持空闲状态,然后它会停止通知错误事件。否则,如果我将设备闲置而不在桌子上移动(非常缓慢),那么加速度计也会继续通知我的应用程序,这会导致错误事件。现在对我的代码有什么建议吗?

标签: android accelerometer


【解决方案1】:

这里有一些代码差异...

  • last_xlast_ylast_z 的更新可能存在问题。我相信它们应该包含在if ((curTime - lastUpdate) > 100) { 声明中。换句话说,它们是在每次调用onSensorChanged 时更新的,而不是每 100 毫秒更新一次。您可能应该将这三个变量的更新移动到它们上方的大括号中。

  • 在计算speed 的那一行,公式以... / diffTime * 10000; 结尾您是想将diffTime 乘以10000,还是整个结果?由于/* 在我所知道的大多数语言(例如Java)中通常具有相同的operator precedence,因此您的等式将从左到右计算,首先除以diffTime 然后 将结果乘以 10000。

    我猜你的意思是将 diffTime 乘以 10000,因此 将最终结果除以该数量。这是除以 10000 或乘以 10000 之间的差异,这意味着您可能得到的 speed 的值比您应该得到的值大 10^8,因此即使在设备空闲时也会触发您的阈值。您需要在乘法周围加上括号,例如 ... / (diffTime * 10000);,以确保它在除法发生之前执行

    此外,如果您打算将 diffTime 从毫秒缩放到秒,您的比例因子应该是 1000。

【讨论】:

  • 抱歉给您带来了困惑。它仅在“if ((curTime - lastUpdate) > 100) {”内。实际上,我在代码的最后一行错过了“}”(右大括号)。我尝试使用 Mr.peejaybee 的建议,但仍然无法按预期工作。有时,如果它在设备空闲时检测加速度计,这会导致错误通知,我无法按预期执行我的代码。
  • @unknown:如果您错过了代码 end 处的 },那么这三行 不在 if 语句中检查时间。请注意,第二个 if 语句后面有两个左大括号(每个 if 语句一个)和两个右大括号,因此最后更新的三行 在第一个 if 语句之外。跨度>
  • @gnovice,是的,OP肯定需要更新last_x等,在update if test里面。
  • 我一直这样(请按照您的建议查看我的代码更新)仍然无法正常工作。即使设备处于空闲状态,我也会连续获得加速度计。
  • 为什么即使在设备空闲时也会调用 if (sensor == SensorManager.SENSOR_ACCELEROMETER) 和 if (speed > SHAKE_THRESHOLD)?
【解决方案2】:

我个人在我的增强现实库中使用滚动平均值进行更新:

float kFilteringFactor = (float)0.05;    
rollingZ = (float) ((rawZValue * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor)));

这往往会很好地平滑数据,您可以调整过滤因子以获得所需的响应能力。

rawZValue 是来自加速度计的原始值。

【讨论】:

  • rollingZ 是做什么的?可以多提供一点吗?
  • Haseman,您将如何根据您的建议修改代码?这对我很容易理解很有帮助。
  • 我通过删除代码中的“return”语句来修复它。请参考我上面的代码,它在加速度计代码中显示“返回”[ if (myFlagIgnoreShakeDetection==true)],这会导致设备空闲时不必要地循环错误的加速度计通知。请谨慎,加速度计检测代码中不应有任何“return”语句。
  • 就我个人而言,我将 rollingZ 变量作为实际值带入我的 AR 套件。 rawZValue 在您的代码中将是 values[SensorManager.DATA_Z];我在这里写了一篇关于它的文章:devx.com/wireless/Article/43005/0/page/2
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
相关资源
最近更新 更多