I am a very new iOS and Android developer, and I need to develop an augmented reality application (location-based) and have problems getting good compass results.
I already made an android application, and the solution just played with the Roll and Yaw data from the accelerometers and magnetic fields, as shown in the following diagram:
And reassign them as described in the Android documentation. (Also thanks to Hoan Nguyen, who helped me fix my code on android (for interested people: How to get the phone header for augmented reality? :))
The problem is this: I cannot prevent trueHeading, which affects roll
, NSObject ( , , , , , !: $)
Compass.h
#include <CoreMotion/CoreMotion.h>
#import <CoreFoundation/CoreFoundation.h>
#import <GLKit/GLKit.h>
#import "constants.h"
@interface Compass : NSObject
+ (id) getSingleton:(UIView*)view;
- (double) getHeading;
@end
Compass.m
#import "Compass.h"
@implementation Compass
CMAttitude *attitude;
CMQuaternion quaternion;
CMRotationMatrix rotationMatrix;
double yaw;
double pitch;
double roll;
double gyro_x;
double gyro_y;
double gyro_z;
double acc_x;
double acc_y;
double acc_z;
float updateSpeed;
UIView *userview;
CADisplayLink *motionDisplayLink;
CMMotionManager *motionManager;
+ (id) getSingleton:(UIView *)view
{
userview = view;
static Compass *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
-(id) init
{
if((self=[super init])) {
updateSpeed = 1.0/60.0;
motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = updateSpeed;
motionDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(motionRefresh:)];
[motionDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
if ([motionManager isGyroAvailable]) {
[motionManager startGyroUpdates];
[motionManager startDeviceMotionUpdates];
[motionManager startMagnetometerUpdates];
}
}
return self;
}
-(void)motionRefresh:(id)sender
{
attitude = motionManager.deviceMotion.attitude;
rotationMatrix = motionManager.deviceMotion.attitude.rotationMatrix;
quaternion = motionManager.deviceMotion.attitude.quaternion;
yaw = IN_DEGREES(motionManager.deviceMotion.attitude.yaw);
roll = IN_DEGREES(motionManager.deviceMotion.attitude.roll);
pitch = IN_DEGREES(motionManager.deviceMotion.attitude.pitch);
gyro_x = IN_DEGREES(motionManager.gyroData.rotationRate.x);
gyro_y = IN_DEGREES(motionManager.gyroData.rotationRate.y);
gyro_z = IN_DEGREES(motionManager.gyroData.rotationRate.z);
acc_x = IN_DEGREES(motionManager.accelerometerData.acceleration.x);
acc_y = IN_DEGREES(motionManager.accelerometerData.acceleration.y);
acc_z = IN_DEGREES(motionManager.accelerometerData.acceleration.z);
}
#pragma mark -
#pragma Getters Sensors Values
- (double) getHeading
{
double heading = 0.0;
return heading;
}
@end
, , ( )
...
, , , , , - ( iOS6)...
, , , , - , .
, , 6.0+ - iPhone.
( 3% App Store : developer.apple.com/support/appstore/)
- : ( Android)

1
www.metaio.com/sdk, , , ; !
2
, , . , , , , , !;)
, :
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
globalHeading = newHeading;
}
- (void) updateCompassValues
{
double tiltCompensation = IN_DEGREES(asin(2*(quaternion.x*quaternion.z - quaternion.w*quaternion.y)));
currentHeading = globalHeading.magneticHeading + tiltCompensation;
}
- , 10 °, , !