2016-10-14 4 views
7

Je travaille sur une application qui collecte des données CoreMotion et j'utilise une application de magasin d'applications existante comme référence pour m'assurer de collecter correctement les données. Pour la plupart, tout est équivalent, mais je vois des données étranges dans certains tests. Le problème apparaît dans les valeurs de roulis, de tangage et de lacet, cependant, les données brutes de l'accéléromètre, du gyroscope et du magnétomètre sont équivalentes ...Insolite CoreMotion Sensorfusion Data

Les graphiques ci-dessous représentent les données collectées à partir de 5 appareils sur un rig @ 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)

En premier lieu, les données recueillies auprès SensorLog: SensorLog Data En second lieu, les données recueillies à partir de mon application: My App Data Troisièmement, les données recueillies à partir de mon application, mais cette fois-ci @ 10Hz: enter image description here

Observations:

  • Le problème semble se limiter à l'iPhone 5 & 5s Mise à jour: Un problème a été observé dans 6s aussi
  • SensorLog est capable d'enregistrer des valeurs correctement (bien que j'en ai vu une instance générant des données 'mauvaises') ce qui semblerait éliminer une limitation matérielle (les précédents tests de l'iPhone 4s aussi)
  • iPhone 6s effectue bien dans tous les tests Mise à jour: plus le cas
  • Mon application peut être affectée par la fréquence que les résultats montrent que @ 10 Hz, 1 iPhone 5 est ok, mais @ 100Hz ne sont
  • Les données brutes sont équivalentes dans tous les appareils, il n'est donc pas clair pourquoi les données de fusion des capteurs sont désactivées pour certains appareils
  • L'utilisation Quaternions ne résout pas le problème car ils sont dérivés des mêmes données brutes
  • Les données « mauvais » dans certains cas, semble suivre les bonnes données, mais l'amplitude est trop grand comme l'a démontré ci-dessous

zoomant sur les parcelles:

Zoomed Chart

Et superposant les étirées manuellement les données de rouleau sur la parcelle ci-dessus:

Overlay roll

code:

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

est-il un problème avec la façon dont je recueille les données de CoreMotion? Y a-t-il un moyen plus efficace de le faire?

Que pourrait-il se passer ici?

MISE À JOUR:

J'ai écrit une application bare os comme suit et j'obtenir des résultats similaires:

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

} 

Répondre

2

D'après ce que je vois est que l'application « Sensor Log » vous mentionné utilise plus de filtres de données pour nettoyer leurs données. Parce que leur est impossible que même après que les données de fusion de capteur est si propre, comme indiqué par l'application.

Selon votre observation que le téléphone Sensor Fusion est éteint. Il ne peut pas être désactivé car s'il est désactivé, vous obtiendrez des données totalement brutes qui ne seraient pas compréhensibles ou même proches de ce que votre sortie est. De ce que je peux vous suggérer est que vous recherchez des filtres utilisés pour le nettoyage des données gyroscopiques à l'aide de l'accéléromètre et du magnétomètre. Probablement si vous êtes seulement intéressé par Roll, Pitch, Yaw. Rechercher des filtres qui sont utilisés pour équilibrer quad-copter. Ils pourraient vous aider.

Désolé, ce n'est pas une réponse, juste un commentaire.Mais je n'ai pas beaucoup de réputation à commenter. Donc, vous pouvez comprendre.