Saturday, September 21, 2013

Retrieve pitch and roll from the accelerometer data [Update]

UPDATE:
You will find an updated version of this post HERE

    So what happens if you designed your application to drive a bluetooth device using the Motion class (because the output is less noisy) and then you realize that on the Lumia 520 and Lumia 625 the Motion class is not supported and you have to use the accelerometer. In my case, as i only use pitch and roll,  the solution was pretty simple as it is actually possible to calculate the pitch and roll values directly from the accelerometer data. This way I can still use the Motion class and when not available fallback on the data extracted from the accelerometer. To better understand the algorithm behind this transformation have a look at this LINK.
     Before applying the transformation I also apply a low-pass filter to remove short-term fluctuations. The difference between the Arduino sample is that the pitch and roll are inverted and also the pitch was 180 degrees off so I remapped the values (when holding in postion 0 it was telling 180 degrees). I also transformed from radians to degrees for easier visualization (the multiplication with 180/Math.Pi)

     const double alpha = 0.5;  
     double fXg = 0;  
     double fYg = 0;  
     double fZg = 0;  
     void acc_ReadingChanged(Windows.Devices.Sensors.Accelerometer sender, AccelerometerReadingChangedEventArgs args)  
     {  
       //Low Pass Filter  
       fXg = args.Reading.AccelerationX * alpha + (fXg * (1.0 - alpha));  
       fYg = args.Reading.AccelerationY * alpha + (fYg * (1.0 - alpha));  
       fZg = args.Reading.AccelerationZ * alpha + (fZg * (1.0 - alpha));  
       //Roll & Pitch Equations  
       double pitch = (Math.Atan2(-fYg, fZg) * 180.0) / Math.PI;  
       double roll = (Math.Atan2(fXg, Math.Sqrt(fYg * fYg + fZg * fZg)) * 180.0) / Math.PI;  
       //rotate 180 degrees  
       pitch=(pitch>=0)?(180-pitch):(-pitch-180);  
     }  

     I have also built a small sample that does comparative plots of the two values using the motion class and the transformation from accelerometer data. Initially I have added also the Microsoft.Devices.Sensors.Accelerometer but the data is almost the same with Windows.Devices.Sensors.Accelerometer with small delays between updates.
  


 
    Here is the  SOURCE CODE of the sample.