Saturday, January 21, 2012

Measuring movement with accelerometer and gyroscope

Santa Claus brought me a present and that sadly means retiring of my trusty Nexus One. Not that the phone has any problem - it still functions perfectly. As Google does not update the Nexus One anymore with new software release, I had to change. And the winner is - well, not the Galaxy Nexus, that's too expensive. I chose a Nexus S because of its attractive price, its update path toward Android 4.x (it is actually the cheapest option today of an Android 4 phone) and its built-in gyroscope.

I wanted to put my hand on a gyroscope-equipped phone for a long time. I discussed in length the problems of using only the accelerometer when identifying movements in my Droidcon 2011 presentation and I hinted that additional sensors could be used to compensate for the motion acceleration that is added to the gravity acceleration and is impossible to separate in the general case. That's what I am aiming to do with the gyroscope in this series of posts.

First let's see the problem. As you can see in slides 23 and 24 of the Droidcon 2011 presentation, there is a problem if the accelerometer is subject to gravity and motion accelerations at the same time. These are impossible to separate in the general case which corrupts both use cases. If the accelerometer is used to measure gravity (e.g. to figure out the device tilt), any motion acceleration distorts the measured tilt. If the accelerometer is used to measure motion acceleration and the exact direction of the gravity acceleration is not known, it is impossible to subtract it and the components of the motion acceleration is impossible to calculate. We need another sensor to acquire additional information to separate the gravity and motion components.

Gyroscope sensor is somewhat rare in today's Android phones. Nexus S was the first to have gyro sensor and since then some high-end phones like Galaxy S II got the sensor. If you want to play with gyro, check, whether your phone has the sensor.

The gyroscope measures angular speed along the 3 axes. As the SensorManager in Android delivers the sensor samples along with timestamps measured in nanoseconds, it is possible to calculate the rotation angle in radian by multiplying the angular speed with the time difference between the current and the previous sample. This means that we know the rotation angles along the 3 axes from the previous to the current gyroscope sample.

Thus the gyroscope can be used to replace the accelerometer when the accelerometer data is distorted by motion acceleration. If we have a reliable gravity vector measurement, we can use the rotation angles measured by the gyroscope to rotate this vector to its new position. As the gyroscope is not subject to motion acceleration, the gravity vector updated by the gyroscope rotation angles will not be affected by the motion acceleration.

The example program is available here.

How exact could this tracking be? I have made a simple sensor sampling application that samples the accelerometer and the gyroscope paralelly. If you try it out, please check that both the accelerometer and the gyroscope sensors' name is displayed - this means that they are available. Move the device only slowly - we don't want motion acceleration in this measurement. The sample file is saved in the file capture.csv on the SD card - typically /sdcard/capture.csv. Fetch this file and you can analyse it with this Sage script called This script expects the measurement data file in the current directory with the name of agx.csv - you can easily change it in line 244.

As the figure below demonstrates, the real gravity vector (blue line) is pretty close to the gravity vector simulated with the gyroscope (red line). Eventually the cumulative errors will make the simulated vector diverge from the real gravity vector - more about later.

No comments: