Skip to content

Commit fea9e35

Browse files
committed
Replace Chebyshev with IIR
1 parent 9d98174 commit fea9e35

2 files changed

Lines changed: 16 additions & 16 deletions

File tree

pedometer/chapter.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ For each component, we can pass total acceleration through a low-pass filter, an
105105

106106
![](chapter-figures/low-pass-filter-a.png)\
107107

108-
There are numerous varieties of filters. The one we'll use is called a Chebyshev filter. We've chosen a Chebyshev filter because it has a steep cutoff, which means that it very quickly attenuates frequencies beyond our chosen threshold.
108+
There are numerous varieties of filters. The one we'll use is called an infinite impulse response (IIR) filter. We've chosen an IIR filter because of its low overhead and ease of implementation.
109109

110-
The Chebyshev filter we've chosen is implemented using the formula $output_{i} = \alpha_{0} * (input_{i} * \beta_{0} + input_{i-1} * \beta_{1} + input_{i-2} * \beta_{2} - output_{i-1} * \alpha_{1} - output_{i-2} * \alpha_{2})$.
110+
The IIR filter we've chosen is implemented using the formula $output_{i} = \alpha_{0} * (input_{i} * \beta_{0} + input_{i-1} * \beta_{1} + input_{i-2} * \beta_{2} - output_{i-1} * \alpha_{1} - output_{i-2} * \alpha_{2})$.
111111

112112
The design of digital filters is outside of the scope of this chapter, but a very short teaser discussion is warranted. It's a well-studied, fascinating topic, with numerous practical applications. A digital filter can be designed to cancel any frequency or range of frequencies desired. The $\alpha$ and $\beta$ values in the formula are coefficients, set based on the cutoff frequency, and the range of frequencies we want to preserve.
113113

@@ -185,11 +185,11 @@ We saw how quickly our seemingly simple problem turned more complex when we thre
185185

186186
### 1. Jumpy Peaks
187187

188-
$a(t)$ is very "jumpy", because a phone can jiggle with each step, adding a high-frequency component to our time series. By studying numerous data sets, we've determined that a step acceleration is at maximum 5 Hz. We can again use a low-pass Chebyshev filter, picking $\alpha$ and $\beta$ to attenuate all signals above 5 Hz, to remove the "jumpiness".
188+
$a(t)$ is very "jumpy", because a phone can jiggle with each step, adding a high-frequency component to our time series. By studying numerous data sets, we've determined that a step acceleration is at maximum 5 Hz. We can again use a low-pass IIR filter, picking $\alpha$ and $\beta$ to attenuate all signals above 5 Hz, to remove the "jumpiness".
189189

190190
### 2. Slow Peaks
191191

192-
With a sampling rate of 100, the slow peak displayed in $a(t)$ spans 1.5 seconds, which is too slow to be a step. In studying enough samples of data, we've determined that the slowest step we can take is at a 1 Hz frequency. Slower accelerations are due to a low-frequency component, that we can again remove using a high-pass Chebyshev filter, setting $\alpha$ and $\beta$ to cancel all signals below 1 Hz.
192+
With a sampling rate of 100, the slow peak displayed in $a(t)$ spans 1.5 seconds, which is too slow to be a step. In studying enough samples of data, we've determined that the slowest step we can take is at a 1 Hz frequency. Slower accelerations are due to a low-frequency component, that we can again remove using a high-pass IIR filter, setting $\alpha$ and $\beta$ to cancel all signals below 1 Hz.
193193

194194
### 3. Short Peaks
195195

@@ -238,30 +238,30 @@ class Filter
238238
alpha: [1, -1.979133761292768, 0.979521463540373],
239239
beta: [0.000086384997973502, 0.000172769995947004, 0.000086384997973502]
240240
}
241-
COEFFICIENTS_LOW_5_HZ = {
241+
COEFFICIENTS_LOW_5_HZ = { # Direct form I, Chebyshev II, type = low-pass, Astop = 2, Fstop = 5, Fs = 100, Direct Form I
242242
alpha: [1, -1.80898117793047, 0.827224480562408],
243243
beta: [0.095465967120306, -0.172688631608676, 0.095465967120306]
244244
}
245-
COEFFICIENTS_HIGH_1_HZ = {
245+
COEFFICIENTS_HIGH_1_HZ = { # Direct form I, Chebyshev II, type = high-pass, Fs = 100, Fstop = 0.5, Astop = 20, order = 2,
246246
alpha: [1, -1.905384612118461, 0.910092542787947],
247247
beta: [0.953986986993339, -1.907503180919730, 0.953986986993339]
248248
}
249249
250250
def self.low_0_hz(data)
251-
chebyshev_filter(data, COEFFICIENTS_LOW_0_HZ)
251+
filter(data, COEFFICIENTS_LOW_0_HZ)
252252
end
253253
254254
def self.low_5_hz(data)
255-
chebyshev_filter(data, COEFFICIENTS_LOW_5_HZ)
255+
filter(data, COEFFICIENTS_LOW_5_HZ)
256256
end
257257
258258
def self.high_1_hz(data)
259-
chebyshev_filter(data, COEFFICIENTS_HIGH_1_HZ)
259+
filter(data, COEFFICIENTS_HIGH_1_HZ)
260260
end
261261
262262
private
263263
264-
def self.chebyshev_filter(data, coefficients)
264+
def self.filter(data, coefficients)
265265
filtered_data = [0,0]
266266
(2..data.length-1).each do |i|
267267
filtered_data << coefficients[:alpha][0] *
@@ -283,9 +283,9 @@ Anytime our program needs to filter a time series, we can call one of the class
283283
* `low_5_hz` is used to low-pass filter signals at or below 5 Hz
284284
* `high_1_hz` is used to high-pass filter signals above 1 Hz
285285

286-
Each class method calls `chebyshev_filter`, which implements the Chebyshev filter and returns the result. If we wish to add more filters in the future, we only need to change this one class.
286+
Each class method calls `filter`, which implements the IIR filter and returns the result. If we wish to add more filters in the future, we only need to change this one class.
287287

288-
One important thing to note is that all magic numbers are defined at the top. This makes our class easier to read and understand. The formula in `chebyshev_filter` is much more obvious using the `coefficients` parameter than it would have been with numerical values directly inserted.
288+
One important thing to note is that all magic numbers are defined at the top. This makes our class easier to read and understand. The formula in `filter` is much more obvious using the `coefficients` parameter than it would have been with numerical values directly inserted.
289289

290290
# Input Formats
291291

pedometer/models/filter.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,20 @@ class Filter
1414
}
1515

1616
def self.low_0_hz(data)
17-
chebyshev_filter(data, COEFFICIENTS_LOW_0_HZ)
17+
filter(data, COEFFICIENTS_LOW_0_HZ)
1818
end
1919

2020
def self.low_5_hz(data)
21-
chebyshev_filter(data, COEFFICIENTS_LOW_5_HZ)
21+
filter(data, COEFFICIENTS_LOW_5_HZ)
2222
end
2323

2424
def self.high_1_hz(data)
25-
chebyshev_filter(data, COEFFICIENTS_HIGH_1_HZ)
25+
filter(data, COEFFICIENTS_HIGH_1_HZ)
2626
end
2727

2828
private
2929

30-
def self.chebyshev_filter(data, coefficients)
30+
def self.filter(data, coefficients)
3131
filtered_data = [0,0]
3232
(2..data.length-1).each do |i|
3333
filtered_data << coefficients[:alpha][0] *

0 commit comments

Comments
 (0)