2016-10-14 2 views
7

Я работаю над приложением, которое собирает данные CoreMotion, и я использую существующее приложение магазина приложений в качестве ссылки, чтобы убедиться, что я правильно собираю данные.Необычные данные Sensorusion CoreMotion

По большей части все эквивалентно, но в некоторых тестах я вижу некоторые странные данные. Проблема обнаруживается в значениях валиков, тангажа и рыскания, однако исходные данные с акселерометра, гироскопа и магнитометра эквивалентны ...

В приведенных ниже графиках представлены данные, собранные с 5 устройств на буровой установке @ 100Hz:

  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: SensorLog Data Во-вторых, данные, собранные из моего приложения: My App Data В-третьих, данные, собранные из моего приложения, но на этот раз @ 10Hz: enter image description here

Наблюдения:

  • Проблема, кажется, ограничена iPhone 5 & 5s Обновление: Проблема была замечена в 6s тоже
  • SensorLog способен записывать значения правильно (хотя я видел один экземпляр этого файла, генерирующий «плохие» данные), которые, казалось бы, устраняют аппаратное ограничение (предыдущие тесты iPhone 4s тоже хорошо)
  • iPhone 6s выполняет отлично во всех тестах Update: Нет больше случае
  • Мое приложение может зависеть от частоты, поскольку результаты показывают, что @ 10Hz, 1 iPhone 5 в порядке, но @ 100Hz ни в
  • Исходные данные эквивалентны для всех устройств, поэтому неясно, почему данные слияния датчиков отключены для некоторых устройств.
  • Использование кватернионов не решает проблему, поскольку они получены из одних и тех же исходных данных появляется
  • «плохой» данные в некоторых случаях должны быть следующие хорошие данные, но амплитуда слишком велика, как показано ниже

Увеличение на участках:

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? Есть ли более эффективный способ сделать это?

Что может быть здесь?

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

} 

ответ

2

Из того, что я вижу, что приложение «Sensor Log» вы упоминается использование еще нескольких фильтров данных для очистки их данных. Потому что их не так, что даже после того, как данные слияния датчиков настолько чисты, как показано в приложении.

В соответствии с вашим наблюдением, что телефон Sensor Fusion выключен. Он не может быть отключен, потому что, если он выключен, вы получите абсолютно необработанные данные, которые не были бы понятны или даже приблизились к тому, что ваш выход.

Из того, что я могу предложить, является поиск фильтров, используемых для очистки данных гироскопа с помощью акселерометра и магнитометра. Возможно, если вас интересует только Roll, Pitch, Yaw. Найдите фильтры, которые используются для балансировки четырехполюсного устройства. Они могут помочь вам.

Жаль, что это не ответ, просто комментарий. Но у меня нет большой репутации, чтобы комментировать. так что вы можете понять.