不寻常的CoreMotion Sensorfusion数据

时间:2016-10-14 00:05:58

标签: ios swift core-motion

我正在处理收集CoreMotion数据的应用,并且我使用现有的应用商店应用作为参考,以确保我正确收集数据。

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

下面的图表绘制了从100Hz上的5台设备收集的数据:

  1. iPhone 5(iOS 10.0.2)
  2. iPhone 5(iOS 10.0.2)
  3. iPhone 5(iOS 10.0.2)
  4. iPhone 5s(iOS 10.0.2)
  5. iPhone 6s(iOS 10.0.2)
  6. 首先,从SensorLog收集的数据: SensorLog Data 其次,从我的应用收集的数据: My App Data 第三,从我的应用程序收集的数据,但这次@ 10Hz: enter image description here

    观察:

    • 问题似乎仅限于iPhone 5& 5s 更新:在6s中也出现了问题
    • SensorLog能够正确记录值(虽然我已经看到它的一个实例产生了糟糕的数据)这似乎消除了硬件限制(以前的iPhone 4s测试也可以)
    • iPhone 6s在所有测试中表现良好更新:不再是
    • 我的应用可能会受到频率的影响,因为结果显示@ 10Hz,1 iPhone 5还可以,但@ 100Hz没有
    • 原始数据在所有设备中都是等效的,因此不清楚为什么某些设备的传感器融合数据已关闭
    • 使用Quaternions不能解决问题,因为它们来自相同的原始数据
    • “坏”'在某些情况下,数据似乎遵循了良好的数据,但振幅太大,如下所示

    放大情节:

    Zoomed Chart

    在上图中叠加手动拉伸的滚动数据:

    Overlay roll

    代码:

    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 个答案:

答案 0 :(得分:2)

从我看到的应用程序'传感器日志'你提到过使用更多的数据过滤器来清理他们的数据。因为即使在传感器融合数据如此干净之后,他们也无法做到这一点。

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

根据我的建议,您可以在Accelerometer和Magnetometer的帮助下搜索用于清洁陀螺仪数据的滤波器。如果你只对Roll,Pitch,Yaw感兴趣的话可能。搜索用于平衡四轮直升机的过滤器。他们可能会帮助你。

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