简体   繁体   English

iOS加速度计的高通滤波器方程式未返回良好结果

[英]High Pass Filter Equation from iOS accelerometer not returning good results

I am trying to implement High Pass Filter for iOS accelerometer based on Accelerometer Graph project . 我正在尝试基于Accelerometer Graph项目为iOS加速度计实现高通滤波器。 The code is written in Swift here is the complete class: 代码是用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

}

}

The class is a part of a project involving SpriteKit and CoreLocation so I removed some parts from the class since they are not relevant. 该类是包含SpriteKit和CoreLocation的项目的一部分,因此我从该类中删除了某些部分,因为它们并不相关。 The problem with this code is that it doesn't work as the example given by Apple. 此代码的问题在于它不能像Apple给出的示例那样工作。 In the Accelerometer Graph all the values are equal to 0 when the phone is stationary and very sensitive to movement which is something what is expected from a high pass filter, however in my case the values are not always 0 when the phone is not moving, it takes time for them to change (even with a very intensive shake), and finally it usually takes few seconds before they stabilize. 在加速度计图表中,当手机静止且对移动非常敏感时,所有值都等于0,这是高通滤波器所期望的,但是在我的情况下,当手机不移动时,值并不总是为0,他们需要一段时间才能改变(即使剧烈晃动),最后通常需要几秒钟的时间才能稳定下来。 In short it behaves more like a low pass or Kalman Filter rather than the High pass Filter. 简而言之,它的行为更像是低通或卡尔曼滤波器,而不是高通滤波器。 Since it's a SpriteKit project I've tried calling the accelerometer updates from GameScene.swift file as well however the results are the same. 由于这是一个SpriteKit项目,因此我尝试从GameScene.swift文件调用加速计更新,但是结果是相同的。 I also experimented with gravity trying both startDeviceMotionUpdatesToQueue and startDeviceMotionUpdatesToQueue functions but with no luck. 我还尝试使用startDeviceMotionUpdatesToQueue和startDeviceMotionUpdatesToQueue函数进行引力试验,但是没有运气。

The problem is that you use the Application's main queue for your accelerometer updates. 问题是您将应用程序的主队列用于加速度计更新。 The main queue is used to perform changes to your UI. 主队列用于对UI进行更改。 Using your main queue for accelerometer updates overloads your main queue so not every operation is executed immediately after being submitted to the NSOperationQueue. 将主队列用于加速度计更新会使主队列超载,因此并不是每个操作在提交给NSOperationQueue后都会立即执行。 The solution is to create a new NSOperationQueue 解决方案是创建一个新的NSOperationQueue

let queue = NSOperationQueue()

and pass it to motionManager.startAccelerometerUpdatesToQueue instead of NSOperationQueue.mainQueue() . 并将其传递给motionManager.startAccelerometerUpdatesToQueue而不是NSOperationQueue.mainQueue()

If you want to perform changes to your UI inside the motionHandler, you have to use gcd's 如果要在motionHandler中对UI进行更改,则必须使用gcd

dispatch_async(dispatch_get_main_queue() {
    //perform UI changes here
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM