不寻常的CoreMotion Sensorfusion数据

doo*_*ers 7 ios core-motion swift

我正在开发一个收集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)

首先,从SensorLog收集的数据: 传感器日志数据 其次,从我的应用收集的数据: 我的应用数据 第三,从我的应用程序收集的数据,但这次@ 10Hz: 在此输入图像描述

观察:

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

放大图块:

放大图表

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

叠加滚动

码:

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

我从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()
    }

}
Run Code Online (Sandbox Code Playgroud)

saa*_*nad 2

据我所知,您提到的应用程序“传感器日志”正在使用更多数据过滤器来清理其数据。因为即使在传感器融合数据如应用程序所示如此干净之后,他们也不可能做到这一点。

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

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

抱歉,这不是一个答案,只是一条评论。但我没有太多的声誉来发表评论。所以,你可以理解。