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:
- 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)
En premier lieu, les données recueillies auprès SensorLog: En second lieu, les données recueillies à partir de mon application: Troisièmement, les données recueillies à partir de mon application, mais cette fois-ci @ 10Hz:
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:
Et superposant les étirées manuellement les données de rouleau sur la parcelle ci-dessus:
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()
}
}