HTC HD2, Accelerometer and Windows Phone 7

I had an idea and after 5 hours of work I have a demo to show you guys. Check out this video below. It shows how the accelerometer data is read from an HTC HD2 and being used on the Windows Phone 7 emulator! I just finished this up today and will be posting details and the source code soon. Apologize for the bad quality of the video, I really need to get a better cam. But hey, I had to talk, record and demo all at the same time!

 

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

HTC HD2 and the Accelerometer

htc-hd2 A couple of weeks ago I went out and bought myself a HTC HD2. Yes, the 4.3inch monster running windows mobile, probably the best windows mobile device ever; this one running Windows Mobile 6.5. Did you just wince in pain on hearing windows mobile? Well, if it makes you feel any better let me assure you that I’ll buy a Windows Phone 7 device as soon as one is available in market. Ok?

I haven’t tweaked around with it too much yet but this week I had some time to look into the accelerometer.

The Accelerometer
The accelerometer sensor measures the gravitational force acting on it. When the phone is at rest the force acting on it is equal to 1g, move the phone around and the force changes (and that is how you detect shake and other gestures). The accelerometer reports the force as vectors along 3-axes, (x, y, z); the magnitude of the force can be calculated using the formula sqrt(x*x + y*y + z*z). If you hold the phone up facing you, the x axis is the horizontal, y axis is the vertical and z axis is along the direction from the phone pointing towards you. This co-ordinate system moves along with the phone. Now the direction along which the values of x, y and z increase and the origin of this co-ordinate system might depend on the implementation on that particular device, so here we will see how it’s implemented on HD2. With respect to HD2 the top-left corner of the phone can be considered as the origin of the co-ordinate system (see image below). Again, with the phone facing you, x axis is horizontal with values increasing towards the right; y axis is the vertical with values increasing as you go from top to bottom; z axis pointing towards you with values increasing as you move from the origin towards you.

HTC HD2 Accel Axes

Lets do a little exercise. When the phone is lying flat, face-up on a table, what is the acceleration vector? It is (0, 0, –1). These are of course ideal values, in practice there will be slight variations because of inaccuracies in the sensor. Why is the vector (0, 0, –1)? Because when the phone is lying flat, the x and y axes are along the horizontal and there is no gravitational force acting along those axes. The z axis which is pointing upwards now, experiences a gravitational pull of 1g in the opposite direction, that explains the negative sign. Now if you pick the phone up and it is facing you the acceleration vector is (0, 1, 0). When the phone is facing you, the x and the z axes form a horizontal plane and therefore the forces are zero. y axis is pointing downwards, in the same direction as the gravitational force and so the value becomes +1. Now if you turn the phone 90 degrees in counter-clockwise direction the force vector becomes (-1, 0, 0), you should be able to figure this one out. HD2 reports the vector values after scaling them by a factor of 1000. So instead of reporting 0.984, it reports 984. Here are the values that my HD2 reports:

lying flat on a table: (X:-67, Y:84, Z:-973)
facing me: (X:74, Y:974, Z:26)

Accelerometer on HD2
From João Paulo Figueira’s post on the HTC G Sensor I came to know that someone called Scott Seligman reverse engineered the G Sensor driver and figured out how to use it. It also led to a project on Codeplex called “Windows Mobile Unified Sensor API” which provided you with a managed wrapper around various sensors in several devices. I wonder how much effort it takes to reverse engineer  and figure out how to use an exported function from a dll, but I am sure it involves biting through a lot of assembly code. Anyways, the accelerometer driver in HD2 is implemented in a dll called HTCSensorSDK.dll.

If you run the dumpbin tool on this dll,
c:\iamdir> dumpbin.exe /EXPORTS HTCSensorSDK.dll

CmdPromptScrShot

you can see that it implements a few other sensors as well, like the compass and the light sensor (or proximity sensor). The functions of interest to us are HTCSensorOpen(), HTCSensorGetDataOutput() and HTCSensorClose(), which control the accelerometer and are pretty self-explanatory. Open() initializes the accelerometer sensor, GetDataOutput() returns the current (x, y, z) acceleration vector and Close() de-initializes the sensor. These functions are accessed using a combination of LoadLibrary() and GetProcAddress() apis if you want to access it through native code, or you could use the interop services and p/invokes to access it from managed code.

I modified an existing native application to access the accelerometer and there is a lot of unnecessary code in it, if you want the native app leave a comment on this post, I’ll clean it up and post it here. Meanwhile I will be posting the managed application source code here. I have tested it on HD2 and I am guessing it should work well on devices like Touch Pro 2, HTC Diamond as well.

Source Code: AccelerometerDemo-HD2.zip

Here’s a brief video of the sample managed application which uses the data returned by the accelerometer to move a marble on the screen. I shot two videos, one using my pathetic camera (VGA resolution) and the other using a desktop screen capture tool which records at 15fps, so you’ll have to live with these until I buy a better camera.

and,

Windows Phone 7 Developer Tools Beta now available

WP7 Microsoft released yesterday the beta version of the Windows Phone 7 development tools, which was up until now in CTP. You can download it from here. It installs Visual Studio 2010 Express, Silverlight and XNA 4.0 for Windows Phone 7, Windows Phone 7 emulator and Expression Blend 4 beta. Yep, Expression Blend now installs with the beta version and you don’t have to install it separately which is nice. The beta version breaks some of the namespaces and classes from the previous April refresh CTP release. The details about the changes can be found in the release notes here. And finally here is a post explaining how to migrate your app from the CTP to the beta release. You’ll also find two new developer tools with the new installation, Windows Phone Developer Registration and XAP deployment tool. If you’re lucky enough to get your hands on a WP7 developer device you can use this tool to unlock the device for side loading and testing your apps. XAP deployment tool allows you to directly deploy a .xap file to the emulator or a real device. You can find these tools in Start -> Programs -> Windows Phone Developer Tools

Update
Just a slight annoyance while installing the beta release. I uninstalled the CTP and then tried to install the beta and it threw an error saying ".NET Framework 4.0 multi-targeting pack is installed, uninstall it to continue", so I uninstalled it and ran the setup again,  guess what it installed first, yep, .NET Framework 4.0 multi-targeting pack.