【发布时间】: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()
}
}
【问题讨论】:
标签: ios swift core-motion