Determine the Device Orientation and its resulting Angle on one Dimension?

confile picture confile · Jul 27, 2015 · Viewed 9.8k times · Source

I have the following setup:

enter image description here

An iPhone lies with the display to the ceiling on a table (alpha = 0 degrees). When the iPhone is moved upwards like shown in the image above the alpha angle increases.

How do I compute the value of the alpha angle without taking care of any other axes which could change. I am only interested in this one axis.

How do I get the correct alpha angle the iPhone has when lifting up from the table? How do I get notified when the value of alpha changes?

Answer

Steve Wilford picture Steve Wilford · Jul 31, 2015

You can use the CMMotionManager class to monitor device motion changes.

Objective C

// Ensure to keep a strong reference to the motion manager otherwise you won't get updates
self.motionManager = [[CMMotionManager alloc] init];
if (self.motionManager.deviceMotionAvailable) {

    self.motionManager.deviceMotionUpdateInterval = 0.1;

    // For use in the montionManager's handler to prevent strong reference cycle
    __weak typeof(self) weakSelf = self;

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [self.motionManager startDeviceMotionUpdatesToQueue:queue
                                            withHandler:^(CMDeviceMotion *motion, NSError *error) {

                                                // Get the attitude of the device
                                                CMAttitude *attitude = motion.attitude;

                                                // Get the pitch (in radians) and convert to degrees.                                          
                                                NSLog(@"%f", attitude.pitch * 180.0/M_PI);

                                                dispatch_async(dispatch_get_main_queue(), ^{
                                                    // Update some UI
                                                });

                                            }];

    NSLog(@"Device motion started");
}
else {
    NSLog(@"Device motion unavailable");
}

Swift

// Ensure to keep a strong reference to the motion manager otherwise you won't get updates
motionManager = CMMotionManager()
if motionManager?.deviceMotionAvailable == true {

    motionManager?.deviceMotionUpdateInterval = 0.1;

    let queue = NSOperationQueue()
    motionManager?.startDeviceMotionUpdatesToQueue(queue, withHandler: { [weak self] (motion, error) -> Void in

        // Get the attitude of the device
        if let attitude = motion?.attitude {
            // Get the pitch (in radians) and convert to degrees.
            // Import Darwin to get M_PI in Swift
            print(attitude.pitch * 180.0/M_PI)

            dispatch_async(dispatch_get_main_queue()) {
                // Update some UI
            }
        }

    })

    print("Device motion started")
}
else {
    print("Device motion unavailable");
}

NSHipster is (as always) a great source of information, and the article on CMDeviceMotion is no exception.