Motion information for iOS apps is made available through the use of motion events. Part 2 of this tutorial explains how it works.
Part one of this motion events series touched on the history of various motion sensing technologies and uses in current iOS devices. Between the cluster of accelerometers and the gyroscope contained within all fourth-generation iOS devices, no motion goes undetected. It is up to the developer, of course, to determine the frequency and level of information required for use within an iOS app. A basic business app, for example, may only be concerned with the device's orientation, while a gaming app could take full advantage of detecting acceleration across three spatial axes.
Tracking device motionThe Core Motion framework consists of three data objects and several classes for capturing and retrieving low-level motion events. The CMAccelerometerData object captures information from the three accelerometers. The CMGyroData object captures rotation information from the iOS device's gyroscope. The CMDeviceMotion object encapsulates data from the accelerometer and gyroscope. The information is used to populate attitude, gravity, userAcceleration, and rotationRate member properties of the CMDeviceMotion class. For iOS devices with a magnetometer, the magneticField property contains the magnetic field vector. Detailed information of an iOS device's symmetry axes (yaw, pitch, and roll) can be retrieved in real-time by implementing the CMDeviceMotion class (Figure A).
Figure Aattitude property of the CMDeviceMotion class allows access to motion data within each of the symmetry axes. The yaw, pitch, and roll properties are returned as Euler angles (Listing 1).
[CMMotionManagerObject startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^ (CMDeviceMotion *devMotion, NSError *error)
CMAttitude *currentAttitude = devMotion.attitude;
verticalAxis = currentAttitude.roll*180/M_PI;
lateralAxis = currentAttitude.pitch*180/M_PI;
longitudinalAxis = currentAttitude.yaw*180/M_PI;
}];The values of the CMAttitude roll, pitch, and yaw properties are returned in radians. While mathematicians prefer radians, many developers prefer working with degrees. The math constant M_PI can be used in a formula to convert radians to degrees and vice-versa. As shown in Listing 1, the properties are multiplied by the quotient of 180 divided by M_PI. You could write stand-alone methods to handle the conversion of degrees and radians (Listing 2). Remember to include the header file math.h in your project.
CGFloat DegreesToRadians(CGFloat degrees)
CGFloat RadiansToDegrees(CGFloat radians)
};With real-time access to motion tracking data, you can call methods to do everything from moving objects on the screen to displaying navigation information in a heads-up-display (HUD). The Core Motion framework is easy to implement and very powerful. As with all of Apple's iOS frameworks, you begin by adding the framework references to your project (Figure B). Be sure to add #import <CoreMotion/CoreMotion.h> to the appropriate files.
Using Core Motion to trigger movement of an object
The basics of using Core Motion to control direction and movement of an object on the screen - such as a character within a game - consists of the following steps:
- Add Core Motion to the project.
- Include references to the Core Motion header file(s).
- Add an instance of the CMMotionManager class.
- Create methods for using Core Motion data to move objects.
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (readonly) CMMotionManager *motionManager;
-(CMMotionManager *) motionManager
if(!motionManager) motionManager = [[CMMotionManager alloc] init];
}You can now reference the CMMotionManager object in the AppDelegate implementation from within the ViewController.m file. From this point, your app is ready to start collecting motion data. There are two approaches for retrieving motion data - push and pull. The pull approach requires less code and processor overhead. The concept is that you would query (or pull) the information whenever you need it. Pulling motion data begins with a request from the iOS app to start an instance of the manager class and request information at certain times. The developer is responsible for starting and stopping the updates (Listing 5).
// Start capturing motion data
// Stop capturing motion data
[motionManager stopDeviceMotionUpdates];The push approach calls a custom handler, or block object, generating a steady stream of continuous data. The code within the block is called each time a motion event happens. This is achieved by using the NSOperationsQueue (Listing 6). The developer can set the update interval to any value between 10 and 100 times per second.
// Set the update frequency
motionManager.deviceMotionUpdateInterval = 1.0/60.0;
// Setup the update queue
[motionManager startDeviceMotionUpdatesToQueue : queue withHandler: handler];