5

Let's say the iPhone is placed on a flat table. I'd like to determine the angle of the tabletop plane, where an angle of 0 would mean the table is exactly perpendicular to the gravity vector. I'm using the following formula:

    radians = atanf (z / sqrt (x^2 + y^2)

in the .h

double      accelerationXAverage;
double      accelerationYAverage;
double      accelerationZAverage;

double      accelerationXSum;
double      accelerationYSum;
double      accelerationZSum;
int         readingsCount;

in the .m

#define kThresholdMovementHigh 0.05

- (void)accelerometer:(UIAccelerometer *)accelerometer
        didAccelerate:(UIAcceleration *)acceleration 
{
    // did device move a lot? if so, reset sums
    if (fabsf(acceleration.x - accelerationXAverage) > kThresholdMovementHigh ||
        fabsf(acceleration.y - accelerationYAverage) > kThresholdMovementHigh ||
        fabsf(acceleration.z - accelerationZAverage) > kThresholdMovementHigh   )
    {
        NSLog(@"deviceDidMove a lot");
        accelerationXSum = acceleration.x;
        accelerationYSum = acceleration.y;
        accelerationZSum = acceleration.z;
        readingsCount = 1;
    }

    else 
    {
        // because the device is at rest, we can take an average of readings
        accelerationXSum += acceleration.x;
        accelerationYSum += acceleration.y;
        accelerationZSum += acceleration.z;
        readingsCount ++;        
    }

    accelerationXAverage = accelerationXSum / readingsCount;
    accelerationYAverage = accelerationYSum / readingsCount;
    accelerationZAverage = accelerationZSum / readingsCount;

    float angle = RadiansToDegrees(atanf(accelerationZAverage/sqrtf(pow(accelerationXAverage, 2) + pow(accelerationYAverage, 2)))) + 90;

    labelAngle.text = [NSString stringWithFormat:@"%.2f°", angle];
}

I'm filtering out noise by averaging the accelerometer readings. The accelerometer update interval is 1/60, and for now while experimenting, I've let the device sit for 10 seconds (so it's an average of 600 readings).

This formula appears to work, it gives me angles about what I'd expect. However, I'm also expecting that if I try this with the device rotated to a different static position while still flat on the tabletop, that I should get the same answer (cause relative to the gravity vector, the angle hasn't changed). However, that's not what I get when I try it out. The angles vary by a couple of degrees.

I am using the right formula? Why would the angle differ for different placements on the same tabletop? Is it just the margin of error?

I've added an image (from http://gotoandplay.freeblog.hu/) to make sure I'm talking about the same x- y- and z- axis.enter image description here

Eric D'Souza
  • 680
  • 5
  • 21
  • im getting error on kThresholdMovementHigh.What is this – srinadh Mar 26 '13 at 14:20
  • kThresholdMovementHigh is just a constant. Below the threshold is "noise" -- ie, movement that you want to ignore. Above the threshold is movement you want to process as deliberate movement by the user. I've updated my question to include my #define. You'll need to determine what is optimal for your app. – Eric D'Souza Mar 28 '13 at 23:34

1 Answers1

3

Your approach and formula are correct.

The x, y and z are relative to the device. Theoretically the angle should be the same irrespective of the angular position of the device on the table top. However there are several factors contributing to the accuracy here including the arctan computation at such a small angle. I would suggest you to try it out with the table inclination (not horizontal to the ground). Say keep your table at angle of 30 degrees from the ground and try out. I assume your x,y,z all are in double

zolio
  • 2,439
  • 4
  • 22
  • 34
  • Thanks for the suggestion. I tried it at a larger inclination. The absolute difference is about the same (~1 degree) although, as a percentage error, it's less significant with the larger inclination. I had x,y,z as floats; I've changed to double. – Eric D'Souza Apr 22 '12 at 14:58
  • After some more experimenting, I think it just is margin of error. I did multiple tests with the iPhone in the same position, and the angle varied 0.5 degrees. (I should have checked the precision in the first place!). You are right, the lack of precision is much more noticeable with the math at small angles. – Eric D'Souza Apr 22 '12 at 15:31