Article

Getting Processed Device-Motion Data

Retrieve data that has already been processed to remove environmental bias, such as the effects of gravity.

Overview

The device-motion service offers a simple way for you to get motion-related data for your app. Raw accelerometer and gyroscope data must be processed to remove bias from other factors, such as gravity. The device-motion service does this processing for you, giving you refined data that you can use right away. For example, this service provides separate values for user-initiated accelerations and for accelerations caused by gravity.

The device-motion service uses all relevant hardware to generate a CMDeviceMotion object, which contains the following information:

  • The device's orientation (or attitude) in three-dimensional space relative to a reference frame

  • The unbiased rotation rate

  • The current gravity vector

  • The user-generated acceleration vector (without gravity)

  • The current magnetic field vector

You access the device-motion service using the CMMotionManager class of the Core Motion framework. Before enabling the service, always check the value of the deviceMotionAvailable property to verify that the service is available for you to use. You have several options for receiving data from the device-motion service. You can get the motion data only when you need it, or you can ask the framework to push updates to your app at regular intervals. Each technique involves different configuration steps and has a different use case.

Getting Device Motion Data Only When You Need It

For apps that process device-motion data on their own schedule, such as games, use the startDeviceMotionUpdates or startDeviceMotionUpdatesUsingReferenceFrame: method of CMMotionManager to start the delivery of motion data. When you call this method, the system enables the needed hardware and begins updating the deviceMotion property of your CMMotionManager object. However, the system does not notify you when it updates that property. You must explicitly check the value of the property when you need the data.

Before you start the delivery of motion updates, specify an update frequency by assigning a value to the deviceMotionUpdateInterval property. The maximum frequency at which you can request updates is hardware-dependent but is usually at least 100 Hz. If you request a frequency that is greater than what the hardware supports, Core Motion uses the supported maximum instead.

Listing 1 shows a method that configures the device-motion service to deliver new motion data 60 times per second. The method then configures a timer to fetch those updates at the same frequency and do something with the data. You could configure the timer to fire at a lower frequency, but doing so would waste power by causing the hardware to generate more updates than were actually used. Setting the showsDeviceMovementDisplay property to YES lets the system display the standard calibration interface to ensure an accurate starting point for motion tracking.

Listing 1

Fetching device-motion data on demand

func startDeviceMotion() {
    if motion.isDeviceMotionAvailable {
        self.motion.deviceMotionUpdateInterval = 1.0 / 60.0
        self.motion.showsDeviceMovementDisplay = true
        self.motion.startDeviceMotionUpdates(using: .xMagneticNorthZVertical)
        
        // Configure a timer to fetch the motion data.
        self.timer = Timer(fire: Date(), interval: (1.0 / 60.0), repeats: true,
                           block: { (timer) in
                            if let data = self.motion.deviceMotion {
                                // Get the attitude relative to the magnetic north reference frame.
                                let x = data.attitude.pitch
                                let y = data.attitude.roll
                                let z = data.attitude.yaw
                                
                                // Use the motion data in your app.
                            }
        })
        
        // Add the timer to the current run loop.
        RunLoop.current.add(self.timer!, forMode: RunLoop.Mode.default)
    }
}

Processing a Steady Stream of Motion Updates

When you want to capture all of the device-motion data being generated, perhaps so you can analyze it for movement patterns, use the startDeviceMotionUpdatesUsingReferenceFrame:toQueue:withHandler: or startDeviceMotionUpdatesToQueue:withHandler: method of CMMotionManager. These methods push each new data set to your app by executing your handler block on the specified queue. The queueing of these blocks ensures that your app receives all of the motion data, even if your app becomes busy and is unable to process updates for a brief period of time. Before you start the delivery of motion updates, specify an update frequency by assigning a value to the deviceMotionUpdateInterval property. The maximum frequency at which you can request updates is hardware-dependent but is usually at least 100 Hz. If you request a frequency that is greater than what the hardware supports, Core Motion uses the supported maximum instead.

Listing 2 shows a method that receives incoming motion data at a rate of 60 times per second. Because the incoming data is delivered using an operation queue, the app is guaranteed to receive all of the data generated by Core Motion. Setting the showsDeviceMovementDisplay property to YES lets the system display the standard calibration interface to ensure an accurate starting point for motion tracking.

Listing 2

Accessing queued motion data

func startQueuedUpdates() {
   if motion.isDeviceMotionAvailable {       self.motion.deviceMotionUpdateInterval = 1.0 / 60.0
      self.motion.showsDeviceMovementDisplay = true
      self.motion.startDeviceMotionUpdates(using: .xMagneticNorthZVertical, 
               to: self.queue, withHandler: { (data, error) in
         // Make sure the data is valid before accessing it.
         if let validData = data {
            // Get the attitude relative to the magnetic north reference frame. 
            let roll = validData.attitude.roll
            let pitch = validData.attitude.pitch
            let yaw = validData.attitude.yaw

            // Use the motion data in your app.
         }
      })
   }
}

Topics

Related Topics

Understanding Reference Frames and Device Attitude

Learn about the initial frame of reference used to report rotation and attitude values.

See Also

Device Motion

CMDeviceMotion

Encapsulated measurements of the attitude, rotation rate, and acceleration of a device.

CMAttitude

The device’s orientation relative to a known frame of reference at a point in time.