Shake detection on HTC HD2

In the previous post I mentioned that the acceleration vector or the force vector can be used to detect gestures like shake. Here is a crude implementation of shake detection,

private const double SHAKE_THRESHOLD = 5.0f;

private bool IsShakeDetected(HTCSensorData sensorData)
{
    bool isShake = false;

    double x = (double)sensorData.tiltX / 1000;
    double y = (double)sensorData.tiltY / 1000;
    double z = (double)sensorData.tiltZ / 1000;

    double forceSqrd = x * x + y * y + z * z;

    System.Console.WriteLine("Force:{0}", forceSqrd);

    if (forceSqrd >= SHAKE_THRESHOLD)
    {
        isShake = true;
    }

    return isShake;
}

This function calculates the square of the magnitude of the force vector and if the value exceeds a certain threshold, shake is detected. After experimenting with a few threshold values, 5.0f seemed to work ok. The problem with this implementation is that it makes an assumption that if the force acting on the device is more than 5.0f, it must be experiencing shake. This, of course, can be false. If you hold and swing the device in one fast sweep, shake will be detected. Technically, that’s not a shake if you ask me. The algorithm can be improved by checking the force against the threshold continuously, say 4-5 times, will work on that when I have time. Here’s a video showing shake detection,

Mark Arteaga wrote a post on shake detection sometime back. The algorithm he used compares (x, y), (x, z) and (y, z) values against a threshold. A shake is registered when the threshold is reached or exceeded 5 times. I replaced my function with his implementation and it works nicely.

private void FuncWhereYouWantToDetectShake()
{
    if (!shaking && CheckForShake(prevSensorData, sensorData, SHAKE_THRESHOLD_LEVEL) &&
        shakeCount >= 5)
    {
        shaking = true;
        shakeCount = 0;
        //SHAKE DETECTED!
    }
    else if (CheckForShake(prevSensorData, sensorData, SHAKE_THRESHOLD_LEVEL))
    {
        shakeCount++;
    }
    else if (!CheckForShake(prevSensorData, sensorData, 200))
    {
        shakeCount = 0;
        shaking = false;
    }
    prevSensorData = sensorData;           

}

private bool CheckForShake(HTCSensorData prevData, HTCSensorData currentData, double threshold)
{
    double deltaX = Math.Abs(prevSensorData.tiltX – sensorData.tiltX);
    double deltaY = Math.Abs(prevSensorData.tiltY – sensorData.tiltY);
    double deltaZ = Math.Abs(prevSensorData.tiltZ – sensorData.tiltZ);

    return (deltaX > threshold && deltaY > threshold) ||
        (deltaX > threshold && deltaZ > threshold) ||
        (deltaY > threshold && deltaZ > threshold);
}

Update:
Source Code: AccelerometerDemo-Shake.zip

Leave a Reply

Your email address will not be published. Required fields are marked *