Я работаю над приложением, которое собирает данные CoreMotion, и я использую существующее приложение магазина приложений в качестве ссылки, чтобы убедиться, что я правильно собираю данные.Необычные данные Sensorusion CoreMotion
По большей части все эквивалентно, но в некоторых тестах я вижу некоторые странные данные. Проблема обнаруживается в значениях валиков, тангажа и рыскания, однако исходные данные с акселерометра, гироскопа и магнитометра эквивалентны ...
В приведенных ниже графиках представлены данные, собранные с 5 устройств на буровой установке @ 100Hz:
- 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 выполняет отлично во всех тестах Update: Нет больше случае
- Мое приложение может зависеть от частоты, поскольку результаты показывают, что @ 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? Есть ли более эффективный способ сделать это?
Что может быть здесь?
UPDATE:
Я написал приложение голые кости следующим образом, и я получаю аналогичные результаты:
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()
}
}