-
-
Save kristopherjohnson/0b0442c9b261f44cf19a to your computer and use it in GitHub Desktop.
| struct LowPassFilterSignal { | |
| /// Current signal value | |
| var value: Double | |
| /// A scaling factor in the range 0.0..<1.0 that determines | |
| /// how resistant the value is to change | |
| let filterFactor: Double | |
| /// Update the value, using filterFactor to attenuate changes | |
| mutating func update(newValue: Double) { | |
| value = filterFactor * value + (1.0 - filterFactor) * newValue | |
| } | |
| } |
Good stuff. Do you have value and newValue reversed?
Other examples I've been reading (AccelerometerGraph, CMMotionManager and Low-pass Filter, and Stack Overflow) all have the values reversed.
mutating func update(newValue: Double) {
value = filterFactor * newValue + (1.0 - filterFactor) * value
}It's probably the naming that has made you confused. The previous computed value plays the significant role in creation of a new one, hence should be multiplied by higher factor (in our case, where α is picked as a very small number closer to 0, that factor is (1-α)).
Thats the whole point of this filter, to not let new value significantly peak over the current one.
So next to (1-α), where α should number between 0 and 1 but closer to 0, you should have previously computed value.
(1-α) * smoothedValueFromPreviousStep + α * newRawValue
If you look at the equation bellow, you might get better understand where s the motivation coming from.
value * (1-α) + value * α = (1 - α + α) * value = 1 * value = value
Finally, if you take an opposite approach in defining α, where it still resides in [0,1] but closer to 1, then you can revert the naming.
Example: