I'm using CoreMotion to get the ccompass heading and i noticed some problems with the compass heading.
At first my initialization of CoreMotion. I got a CMMotionManager object, locationManager, which is an instance of the CMMotionManager.
// initialize CoreMotion
motionManager = [CMMotionManager new];
[motionManager setDeviceMotionUpdateInterval:1.0/30.0];
[motionManager setShowsDeviceMovementDisplay:YES];
[self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical];
The position data is updated every 1/30.0 seconds.
For debug purposes i have a UILabel which shows me the current compass heading updated on every update interval. While the application is starting i always have to do the magical 8 for calibrating the compass.
After calibrating the compass, the heading for north and south is correct for almost 2-5 seconds.
Right after a couple of seconds the compass goes wild and the angles are jumping around. Mostly its floating around 10-20 degrees from the starting position in both directions. Enought to have a wierd result. After 30-60 seconds every now and again the south and north are interchanged or showing to east and west.
At the WWDC 2011, a session has been talked about how they calculate each sensor with another to compensate this problems. Is there anything i missed at the configuration of CoreMotion that i have this massive problems of accurate heading results?
I tested the compass now with 3 devices (2 iPhone 4s and iPhone 4) in and outside buildings. I was at fields, small citys and big citys. It happens all the time. The sample compass app from Apple is almost accurate with 90% accuracy in my tests. Unfortunately its not open sourced by Apple.
Thank you for reading.
Using CoreMotion through CoreLocation will get you what you are looking for.
By default the handset will do the calibration figure 8, to disable this, override locationManagerShouldDisplayHeadingCalibration:
as follows:
- (BOOL)locationManagerShouldDisplayHeadingCalibration: (CLLocationManager *)manager {
return NO;
}
It's not clear from the code in your question if you're calling startUpdateHeading
. If not, do so:
if( [CLLocationManager locationServicesEnabled] && [CLLocationManager headingAvailable]) {
[myLocationManager startUpdatingLocation];
[myLocationManager startUpdatingHeading];
}
You can get crazy results if you don't turn on the heading filter, I'd recommend that you do so. After that, you just get the heading changes in your location manager delegate when didUpdateHeading
is called.
Also note that if the handset is in landscape mode, you'll need to adjust the heading by the appropriate number of degrees(+/- 90), since the heading is always in the Portrait frame of reference.
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