Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get device plane relative to ground plane using accelerometer

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

like image 696
Eric D'Souza Avatar asked Oct 23 '22 01:10

Eric D'Souza


1 Answers

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

like image 136
zolio Avatar answered Oct 31 '22 13:10

zolio