nivrutti
nivrutti

Reputation: 297

iPhone accelerometer movement is not working smoothly

I have to implement an iPhone accelerometer app in which I have to move an image based on accelerometer coordinates. My app works well but sometime my ImageView moves to top (view y) and then disappears.

I have used following code,

UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self; 
accel.updateInterval = 1.0f/30.f;

#define kFilteringFactor 0.1

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
    static UIAccelerationValue rollingX = 0.0;
    static UIAccelerationValue rollingY = 0.0;

    // Subtract the low-pass value from the current value to get a simplified high-pass filter
    rollingX = (acceleration.x * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor));
    rollingY = (acceleration.y * kFilteringFactor) + (rollingY * (1.0 - kFilteringFactor));

    double accelX = acceleration.x - rollingX;
    double accelY = acceleration.y -  rollingY;

    // Use the acceleration data.
    float newX = containerView.center.x + ((float)accelX * 30.0f);
    float newY = containerView.center.y + ((float)accelY * 30.0f);
    containerView.center = CGPointMake(newX, newY);

}

Upvotes: 1

Views: 408

Answers (1)

Amit Hagin
Amit Hagin

Reputation: 3226

I found it a bit frustrating as well, because this filter you are using (which is pretty common) doesn't seem to do the work as good as you expect. In the end I decided to calculate the weighted average of the last 8 samples of the accelerometer and use it as the final value.

the problem is: the more I weight the old samples - the final movement will be smoother, but a delay will be felt clearer. On the other hand- the more I weight the new samples - the final movements will be more dirty, but more exact (the delay will be felt less and less).

My solution was to weight the middle samples much more than the new or the old, and create a pyramid of weights. I found out (don't know why, can someone explain?) that the Newton's binomial weight is the best.

in simple words, at any point, I add a duplication factor to each of the last 8 samples according to this array: 1; 7; 21; 35; 35; 21; 7 ;1 (the values are easy to find using Pascal triangle: http://www.mathsisfun.com/pascals-triangle.html).

the code looks like this:

  if ([d count]<8) {
    [d addObject:[NSNumber numberWithFloat:acceleration.x]];
}
else{
    [d removeObjectAtIndex:0];
    [d addObject:[NSNumber numberWithFloat:acceleration.x]];
}

NSMutableArray*binom=[[NSMutableArray alloc] init];
[binom addObject:[NSNumber numberWithInt:1]];
[binom addObject:[NSNumber numberWithInt:7]];
[binom addObject:[NSNumber numberWithInt:21]];
[binom addObject:[NSNumber numberWithInt:35]];
[binom addObject:[NSNumber numberWithInt:35]];
[binom addObject:[NSNumber numberWithInt:21]];
[binom addObject:[NSNumber numberWithInt:7]];
[binom addObject:[NSNumber numberWithInt:1]];

float s=0;
int j=0;
for (NSNumber* n in d){
    s+=[n floatValue]*[[binom objectAtIndex:j] intValue];
    j++;
}
s=s/128;

s will give you the value you should set in newX.

do the same for y and z, to get the full movement value.

Hope it help

Upvotes: 1

Related Questions