Уравнение фильтра высоких частот от акселерометра iOS не дает хороших результатов

Я пытаюсь реализовать фильтр верхних частот для акселерометра iOS на основе графика акселерометра. проект. Код написан на Swift, вот полный класс:

import Foundation
import CoreMotion
import SpriteKit

class Accelerometer {

     let motionManager: CMMotionManager

     var x: Double
     var y: Double
     var z: Double
     var lastX: Double
     var lastY: Double
     var lastZ: Double
     let kUpdateFrequency: Double
     let cutOffFrequency: Double
     let dt: Double
     let RC: Double
     let alpha: Double
     let kFilteringFactor = 0.6


init(manager: CMMotionManager){

    motionManager = manager
    motionManager.accelerometerUpdateInterval = 1.0 / 60
    motionManager.startDeviceMotionUpdates()

    x = 0.0
    y = 0.0
    z = 0.0
    lastX = 0.0
    lastY = 0.0
    lastZ = 0.00
    kUpdateFrequency = 60.0
    cutOffFrequency = 5.0
    dt = 1.0 / kUpdateFrequency
    RC = 1.0 / cutOffFrequency
    alpha = RC / (dt+RC)
    getAccelerometerUpdates()

}

func getAccelerometerUpdates() {

    motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { (data, error) -> Void in

        // Filter the raw measurments with high pass filter
        self.highPassFilter(data!)
    })

}


// High pass filter function for accelerometer measurments
func highPassFilter(data: CMAccelerometerData){

    self.x = self.alpha * (self.x + data.acceleration.x - self.lastX)
    self.y = self.alpha * (self.y + data.acceleration.y - self.lastY)
    self.z = self.alpha * (self.z + data.acceleration.z - self.lastZ)

    self.lastX = data.acceleration.x
    self.lastY = data.acceleration.y
    self.lastZ = data.acceleration.z

}

}

Этот класс является частью проекта, включающего SpriteKit и CoreLocation, поэтому я удалил некоторые части из класса, поскольку они не имеют значения. Проблема с этим кодом в том, что он не работает как пример, данный Apple. На графике акселерометра все значения равны 0, когда телефон неподвижен и очень чувствителен к движению, чего и следовало ожидать от фильтра верхних частот, однако в моем случае значения не всегда равны 0, когда телефон не движется, для их изменения требуется время (даже при очень интенсивном встряхивании), и, наконец, обычно требуется несколько секунд, прежде чем они стабилизируются. Короче говоря, он больше похож на фильтр нижних частот или фильтр Калмана, чем на фильтр высоких частот. Поскольку это проект SpriteKit, я также пытался вызывать обновления акселерометра из файла GameScene.swift, однако результаты те же. Я также экспериментировал с гравитацией, пробуя обе функции startDeviceMotionUpdatesToQueue и startDeviceMotionUpdatesToQueue, но безуспешно.


person Nermin Sehic    schedule 12.08.2015    source источник
comment
Я считаю, что проблема в том, что вы ставите обновления в основную очередь, которая не может обрабатывать их все в режиме реального времени. что произойдет, если вы создадите еще одну очередь для обновлений вашего акселерометра?   -  person Palle    schedule 13.08.2015
comment
let queue = NSOperationQueue() Я заменил mainQueue на это, и теперь это работает, хотя мое приложение разбилось без сообщения об ошибке, но это может быть что-то еще. Почему очередь была проблемой? Я бы потратил еще месяц, пытаясь отладить это.   -  person Nermin Sehic    schedule 13.08.2015
comment
объяснил все это в ответе ниже.   -  person Palle    schedule 13.08.2015
comment
Привет, Нермин, я хочу преобразовать весь этот проект (график акселерометра) в Swift. Не могли бы вы поделиться со мной, если вы уже сделали это?   -  person user1953977    schedule 09.06.2016
comment
Я преобразовал почти все в Swift, но он не отделен от остального кода. Я мог бы создать репозиторий git с материалом, который я переписал, и, возможно, вы можете клонировать его, добавив больше, если вам интересно.   -  person Nermin Sehic    schedule 09.06.2016
comment
Привет, Нермин. Пожалуйста, поделитесь ссылкой на git.   -  person user1953977    schedule 10.06.2016


Ответы (1)


Проблема в том, что вы используете основную очередь приложения для обновлений вашего акселерометра. Основная очередь используется для внесения изменений в ваш пользовательский интерфейс. Использование вашей основной очереди для обновлений акселерометра перегружает вашу основную очередь, поэтому не каждая операция выполняется сразу после отправки в NSOperationQueue. Решение состоит в том, чтобы создать новый NSOperationQueue

let queue = NSOperationQueue()

и передайте его в motionManager.startAccelerometerUpdatesToQueue вместо NSOperationQueue.mainQueue().

Если вы хотите внести изменения в свой пользовательский интерфейс внутри motionHandler, вы должны использовать gcd

dispatch_async(dispatch_get_main_queue() {
    //perform UI changes here
}
person Palle    schedule 12.08.2015
comment
Привет, Нермин, я хочу преобразовать весь этот проект (график акселерометра) в Swift. Не могли бы вы поделиться со мной, если вы уже сделали это? - person user1953977; 09.06.2016
comment
@ user1953977 Я полагаю, вы намеревались прокомментировать вопрос, но прокомментировали ответ. - person Palle; 09.06.2016
comment
о да, извините, я тоже добавил - person user1953977; 10.06.2016