不寻常的 CoreMotion Sensorfusion 数据

Posted

技术标签:

【中文标题】不寻常的 CoreMotion Sensorfusion 数据【英文标题】:Unusual CoreMotion Sensorfusion Data 【发布时间】:2016-10-14 00:05:57 【问题描述】:

我正在开发一个收集 CoreMotion 数据的应用程序,并且我使用现有的应用程序商店应用程序作为参考,以确保我正确收集数据。

在大多数情况下,一切都是等效的,但我在某些测试中看到了一些奇怪的数据。问题出现在横滚、俯仰和偏航值中,但是来自加速度计、陀螺仪和磁力计的原始数据是等效的...

下图绘制了从 100Hz 钻机上的 5 个设备收集的数据:

    iPhone 5 (ios 10.0.2) iPhone 5 (iOS 10.0.2) iPhone 5 (iOS 10.0.2) iPhone 5s (iOS 10.0.2) iPhone 6s (iOS 10.0.2)

首先,从SensorLog收集的数据: 其次,从我的应用程序收集的数据: 第三,从我的应用程序收集的数据,但这次是@10Hz:

观察:

问题似乎仅限于 iPhone 5 和 5s 更新:在 6s 中也观察到问题 SensorLog 能够正确记录值(尽管我见过它的一个实例生成“坏?”数据),这似乎消除了硬件限制(以前的 iPhone 4s 测试也可以) iPhone 6s 在所有测试中表现良好更新:不再是这种情况 我的应用可能会受到频率的影响,因为结果显示@10Hz, 1 iPhone 5 可以,但@100Hz 都没有 原始数据在所有设备中都是等效的,因此尚不清楚为什么某些设备会关闭传感器融合数据 使用四元数并不能解决问题,因为它们源自相同的原始数据 在某些情况下,“坏”数据似乎跟随好数据,但幅度太大,如下所示

放大图:

并在上图中覆盖手动拉伸的滚动数据:

代码:

func start(_ interval: TimeInterval = 0.1) 
    self.interval = interval

    logTimer = Timer.new(every: interval, 
        self.motionData.currentRecord = self.motionDataRecord
        self.motionData.createCoreDataRecord()
        NotificationCenter.default.post(name: .motionHelperDidUpdateData, object: nil)
    )
    logTimer.start()

    startCoreLocation()
    startAccelerometer()
    startDeviceMotion()
    startGyroscope()
    startMagnetometer()


func startCoreLocation() 
    switch CLLocationManager.authorizationStatus() 
    case .authorizedAlways:
        locationManager.startUpdatingLocation()
        locationManager.startUpdatingHeading()
    case .notDetermined:
        locationManager.requestAlwaysAuthorization()
    case .authorizedWhenInUse, .restricted, .denied:
        delegate?.reRequestAlwaysAuthorization()
    


func startAccelerometer() 
    if motionManager.isAccelerometerAvailable 
        motionManager.accelerometerUpdateInterval = interval
        motionManager.startAccelerometerUpdates(to: queue) 
            [weak self] (data, error) in

            guard let weakSelf = self else  return 

            if error != nil 
                print("Accelerometer Error: %@", error)
            
            guard let data = data else  return 

            weakSelf.motionDataRecord.accelerometer = data
        
     else 
        print("The accelerometer is not available")
    



func startGyroscope() 
    if motionManager.isGyroAvailable 
        motionManager.gyroUpdateInterval = interval
        motionManager.startGyroUpdates(to: queue) 
            [weak self] (data, error) in

            guard let weakSelf = self else  return 

            if error != nil 
                print("Gyroscope Error: %@", error)
            
            guard let data = data else  return 

            weakSelf.motionDataRecord.gyro = data
        
     else 
        print("The gyroscope is not available")
    


func startMagnetometer() 
    if motionManager.isMagnetometerAvailable 
        motionManager.magnetometerUpdateInterval = interval
        motionManager.startMagnetometerUpdates(to: queue) 
            [weak self] (data, error) in

            guard let weakSelf = self else  return 

            if error != nil 
                print("Magnetometer Error: %@", error)
            
            guard let data = data else  return 

            weakSelf.motionDataRecord.magnetometer = data
        
     else 
        print("The magnetometer is not available")
    


func startDeviceMotion() 
    if motionManager.isDeviceMotionAvailable 
        motionManager.deviceMotionUpdateInterval = interval
        motionManager.startDeviceMotionUpdates(using: attitudeReferenceFrame, to: queue) 
            [weak self] (data, error) in

            guard let weakSelf = self else  return 

            if error != nil 
                print("Device Motion Error: %@", error)
            
            guard let data = data else  return 

            weakSelf.motionDataRecord.deviceMotion = data
        
     else 
        print("Device motion is not available")
    

我从 CoreMotion 收集数据的方式有问题吗?有没有更有效的方法?

这里会发生什么?

更新:

我已经编写了一个简单的应用程序,如下所示,我得到了类似的结果:

class ViewController: UIViewController 

    @IBOutlet weak var startStop: UIButton!

    var isRunning = false

    let manager: CMMotionManager = 
        let manager = CMMotionManager()
        manager.deviceMotionUpdateInterval = 1/100
        return manager
    ()

    @IBAction func handleStartStop(_ sender: AnyObject) 
        if isRunning 
            stopMotionUpdates()
            startStop.setTitle("Start", for: .normal)
         else 
            startMotionUpdates()
            startStop.setTitle("Stop", for: .normal)
        
        isRunning = !isRunning
    

    func startMotionUpdates() 
        manager.startDeviceMotionUpdates(using: .xTrueNorthZVertical, to: .main)  (data, error) in
            print("Roll: \(data!.attitude.roll), Pitch: \(data!.attitude.pitch), Yaw: \(data!.attitude.yaw)")
        
    

    func stopMotionUpdates() 
        manager.stopDeviceMotionUpdates()
    


【问题讨论】:

【参考方案1】:

据我所知,您提到的“传感器日志”应用程序正在使用更多数据过滤器来清理其数据。因为即使在 Sensor fusion 之后,他们的数据也不可能像 app 显示的那样干净。

根据您的观察,手机 Sensor Fusion 已关闭。它不能关闭,因为如果它关闭,您将获得完全无法理解的原始数据,甚至接近您的输出。

我可以建议您在加速度计和磁力计的帮助下搜索用于清理陀螺仪数据的过滤器。可能如果您只对 Roll、Pitch、Yaw 感兴趣。搜索用于平衡四轴飞行器的过滤器。他们可能会帮助你。

对不起,这不是一个答案,只是一个评论。但我没有太多评论的声誉。所以,你可以理解。

【讨论】:

以上是关于不寻常的 CoreMotion Sensorfusion 数据的主要内容,如果未能解决你的问题,请参考以下文章

UIMotionEffect 和 CoreMotion 有何不同?

使用 CoreMotion 移动 SKSpriteNode

如何使用 CoreMotion 框架确定设备位置?

CoreMotion框架--加速计和陀螺仪

CoreMotion 授权问题

CoreMotion 授权问题