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:
- 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)
pierwsze, dane zebrane od SensorLog: drugie, dane zebrane z mojego app: trzecie, dane zebrane z mojej aplikacji, ale tym razem @ 10Hz:
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:
i nałożenie ręcznie wyciągnięte danych pochyleniu działki powyżej:
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()
}
}