gyroscopecore-motionwatchos-5

Cannot get Core Motion Updates using watchOS 5: "[Gyro] Manually set gyro-interrupt-calibration to 800"


I am trying to get Core Motion data from an Apple Watch 3 (WatchOS 5.1) but although the DeviceMotion is available (isDeviceMotionAvailable property is true), the handler is never triggered. I get the following message in the console right after parsing super.willActivate():

[Gyro] Manually set gyro-interrupt-calibration to 800

I am using the following function to get Device Motion updates:

func startQueuedUpdates() {
    if motion.isDeviceMotionAvailable {
        self.motion.deviceMotionUpdateInterval = 1.0 / 100.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 {

                print(String(validData.userAcceleration.x))

            }
        })
    }
}

In the InterfaceController I have declared

let motion = CMMotionManager()
let queue : OperationQueue = OperationQueue.main

Has anyone met this message before and managed to resolve it?

Note: I have checked the isGyroAvailable property and it is false.


Solution

  • The trick here is to match the startDeviceMotionUpdates(using: CMAttitudeReferenceFrame parameter to your device's capabilities. If it has no magnetometer, it cannot relate to magnetic north, and even if it has a magnetometer, it cannot relate to true north unless it knows where you are (i.e. has latitude & longitude). If it hasn't got the capabilities to comply with the parameter you select, the update will be called, but the data will be nil.

    If you start it up with the minimum .xArbitraryZVertical you will get updates from the accelerometer, but you won't get a meaningful heading, just a relative one, through the CMDeviceMotion.attitude property ...

    if motion.isDeviceMotionAvailable {
        print("Motion available")
        print(motion.isGyroAvailable ? "Gyro available" : "Gyro NOT available")
        print(motion.isAccelerometerAvailable ? "Accel available" : "Accel NOT available")
        print(motion.isMagnetometerAvailable ? "Mag available" : "Mag NOT available")
    
        motion.deviceMotionUpdateInterval = 1.0 / 60.0
        motion.showsDeviceMovementDisplay = true
        motion.startDeviceMotionUpdates(using: .xArbitraryZVertical) // *******
    
        // Configure a timer to fetch the motion data.
        self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
            if let data = self.motion.deviceMotion {
                print(data.attitude.yaw)
            }
        }
    }