I'm using compass heading to rotate an MKMapView. The rotation was a bit jerky so I'm trying to filter it like Google Maps on the iphone does (or appears to do some trickery).
I'm trying to filter the reading from the iphone compass using a moving average formula but it fails on the crossover between 359 adn 0 becuase it starts to average backwards from 35x to 0 and causes the map to rotate backwards as it approaches north from the west.
Any ideas what the best way is to filter this data so that it crosses from 359 back to zero and maintain the rolling average.
Code is here:
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
static float xd=0;
static float k = 0.22;
// Moving average formula
xd = k * xd + (1.0 - k) * newHeading.magneticHeading;
NSLog(@"%0.2f : %0.2f", newHeading.magneticHeading, xd);
[map setTransform:CGAffineTransformMakeRotation((-1 * xd * M_PI) /180)];}
Thanks for any help
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)heading
{
int newHeading;
int queuecount;
newHeading = heading.trueHeading;
[queue addObject:[NSNumber numberWithInt:newHeading]];
if([queue count] > 10) [queue removeObjectAtIndex:0];
queuecount = [queue count];
NSEnumerator *e = [queue objectEnumerator];
NSNumber *sum;
int oldd = 0 , newd, average =0;
BOOL firstLoop = YES;
while ((sum = [e nextObject]))
{
newd = [sum intValue];
if(firstLoop) {oldd = newd;firstLoop=NO;}
if((newd +180) < oldd)
{
newd +=360; oldd = newd;
average = average + newd;
continue;
}
if((newd - 180) > oldd)
{
newd -=360;oldd = newd;
average = average + newd;
continue;
}
average = average + newd;
oldd = newd;
}
average = (average / queuecount) % 360;
[map setTransform:CGAffineTransformMakeRotation((-1 * average * M_PI) /180)];
}
If the previous moving average and the new heading are different by more than 180 degrees, add 360 to whichever is smaller. Then mod by 360 when storing the new moving average. So (without precise math):
HDG MA
350 350
355 353
0 356 (because 353 - 0 > 180 so adjusted HDG is 360)
5 359 (likewise)
10 2 (likewise, then 362 is new MA, mod 360 to normalize)
350 356 (because 2 - 350 < -180 so adjusted MA is 362)
My hope is that this works and is more efficient than the trigonometric method described in Averaging angles (credit to Mark Ransom for referring to that).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With