Wednesday, January 25, 2012

Compensating accelerometer data with the gyroscope

In the previous post we have seen, how we can simulate the rotations of the gravity vector (thus measuring the exact tilt) with the help of the gyroscope. During that measurement we moved the device only slowly to validate the claim that the gyroscope is able to track the gravity vector for a certain period of time. We were aware of the fact that measurement errors for this type of measurement will eventually accumulate and therefore we have to pick the correct gravity vector time to time.

In this post we go one step further. We will use the gyro-based simulated gravity vector only if the accelerometer does not provide us with reliable gravity vector measurement (because the device is subject to motion acceleration too). But how to figure out if the gravity measurement of the accelerometer is reliable or not? Let's see the picture below which is shows the absolute value (the length) of the accelerometer's output vector as a function of sample count when the device is subject to a "tennis-like" movement. This means that the device is held in one hand and I simulated as if it was a tennis racquet. The device rotates but is also subject to a significant motion acceleration.

We have problem when the absolute value of the acceleration is significantly larger (or smaller) than 1 g (about 10 m/s^2). This means that when the absolute value of the acceleration vector is close to 1g, we can be quite sure that there is no motion acceleration and we have reliable gravity vector measurement.

This detection method is not foolproof, however. We can construct gravity and motion acceleration vector arrangements so that the length of the resulting vector is 1 g, still it points to completely wrong direction compared to the gravity vector. The keyword is "construction". Even though these arrangements are possible, it is very unlikely that they persist for a long time during motion.

So the gyro compensation algorithm is the following:

  • If the absolute value of the acceleration vector is significantly larger or smaller than 1g, ignore it and use the gyro-simulated gravity vector.
  • If the absolute value of the acceleration vector is close to 1g but differs significantly from the gyro-simulated vector then start counting these cases. If this case happens 5 times consecutively then update the gyro-simulated vector from the acceleration vector and use that.
Otherwise update the gyro-simulated vector from the acceleration vector and use this value to calculate the gravity vector.

Let's see now our racquet swing. The samples were taken with the Android application attached to the previous post, the analysis was done with this Sage script. The Sage script takes the samples from capture.csv file - you can easily change that in line 456. Blue line is the collection of 3D acceleration vectors from the accelerometer, red line is the gyro-compensated gravity vector (taken from the accelerometer if there is no motion, simulated with the help of the gyroscope if motion acceleration is detected).

As you can see, the blue line is everywhere. Actually it goes out of the coordinate system as the Nexus S has its accelerometer limited at 2g - that's why you see the acceleration curve turned into straight lines at the fastest points of the movement. The red line, however, follows the curve of the device's tilt nicely and eventually ends almost where the acceleration's blue line does. Then it gets compensated by the accelerometer's gravity vector measurement - no cumulative errors.

There's more to come, just stay tuned.

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.