2016-10-14 9 views
7

Pracuję nad aplikacją, która zbiera dane CoreMotion i używam istniejącej aplikacji sklepu z aplikacjami jako punktu odniesienia, aby zapewnić prawidłowe zbieranie danych.Niezwykłe dane CoreMotion Sensorfusion

W większości przypadków wszystko jest równoważne, ale w niektórych testach widzę dziwne dane. Problem pojawia się w wartościach przechyłu, nachylenia i odchylenia, jednak surowe dane z przyspieszeniomierza, żyroskopu i magnetometru są równoważne ...

Poniższe wykresy przedstawiają dane zebrane z 5 urządzeń na platformie @ 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)

pierwsze, dane zebrane od SensorLog: SensorLog Data drugie, dane zebrane z mojego app: My App Data trzecie, dane zebrane z mojej aplikacji, ale tym razem @ 10Hz: enter image description here

obserwacje:

  • Problem wydaje się być ograniczony do iPhone'a 5 & 5s Aktualizacja: Problem został zaobserwowany również w 6s
  • SensorLog jest w stanie prawidłowo zapisywać wartości (chociaż widziałem, że jedna z nich generuje "złe?" Danych), które zdają się eliminować ograniczenia sprzętowe (poprzednie testy iPhone'a 4s też)
  • iPhone 6s wykonuje dobrze we wszystkich testach Aktualizacja: już przypadku
  • Moja aplikacja może mieć wpływ na częstotliwość jak wyniki pokazują, że @ 10Hz, 1 iPhone 5 jest ok, ale @ 100Hz żadna są
  • Nieprzetworzone dane są równoważne we wszystkich urządzeniach, więc nie jest jasne, dlaczego dane fuzji czujnika są wyłączone w przypadku niektórych urządzeń
  • Korzystanie kwaterniony nie rozwiąże problemu, ponieważ pochodzą od tych samych danych pierwotnych pojawia
  • „złych” danych w niektórych przypadkach należy po dobrych danych, ale amplituda jest zbyt duży, jak wykazano poniżej

Powiększanie poletek:

Zoomed Chart

i nałożenie ręcznie wyciągnięte danych pochyleniu działki powyżej:

Overlay roll

Kod:

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

Czy jest jakiś problem z okazji jestem zbierającej dane z CoreMotion? Czy istnieje skuteczniejszy sposób na zrobienie tego?

Co się tutaj dzieje?

UPDATE:

Napisałem aplikację szkielety następująco a ja dostaję podobne wyniki:

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

} 

Odpowiedz

2

Z tego, co widzę, jest to, że aplikacja „Czujnik Log” ty wspomniano, że do czyszczenia danych używa się więcej filtrów danych. Ponieważ ich nie ma, nawet po tym, jak dane z czujnika Fusion są tak czyste, jak pokazano w aplikacji.

Zgodnie z twoją uwagą, że telefon Sensor Fusion jest wyłączony. Nie można go wyłączyć, ponieważ jeśli jest wyłączony, otrzymasz całkowicie nieprzetworzone dane, które nie będą zrozumiałe, a nawet bliskie twojemu wynikowi.

Z tego co mogę zasugerować, to że szukasz filtrów używanych do czyszczenia danych żyroskopowych za pomocą akcelerometru i magnetometru. Prawdopodobnie, jeśli interesuje Cię tylko Roll, Pitch, Yaw. Szukaj filtrów, które równoważą quad-copter. Mogą ci pomóc.

Niestety nie jest to odpowiedź, tylko komentarz. Ale nie mam wiele opinii do komentowania. więc możesz zrozumieć.

Powiązane problemy