Noise and filtering · University · about 30 min
Every filter delays. Measuring the delay, and what it does to a loop closed around it.
[1 mark]An exponential filter with alpha = 0.2 runs in a 0.1 s loop. About how many seconds does it delay the signal?
[1 mark]What does this print?
DT = 0.1
for a in (0.5, 0.25, 0.1):
steps = (1 - a) / a
print(a, round(steps, 2), round(steps * DT, 2))0.5 1.0 0.1 0.25 3.0 0.3 0.1 9.0 0.9
(1 - alpha) / alpha gives 1, 3 and 9 steps, so 0.1 s, 0.3 s and 0.9 s at a 0.1 s loop. Halving alpha more than doubles the delay.
[1 mark]A controller holds a gap to the wall. Why should the filter go on the measurement rather than on the error?
[1 mark]In a PID controller, which term usually needs the filter?
[1 mark]The plant has a time constant of 0.25 s and the loop runs at 0.1 s. By the lesson's rule of thumb, which filter is acceptable in the loop?
[1 mark]A controller was twitchy, so its sensor filter was made heavier twice. It now oscillates slowly. What is the right fix?
Drive steadily at the wall, filter the distance, plot raw and filtered, and print lag:, the seconds by which the filtered signal trails the raw one.
from bugbot import * connect() ALPHA = 0.2 DT = 0.1 filtered = distance()
The hint students can ask for: Drive steadily at the wall so the distance falls in a straight line, then compare the two signals: the filtered one reaches any given value later. The theory says the delay is about (1 - alpha) over alpha, times the loop period. Check it against what you measure.
from bugbot import *
connect()
ALPHA = 0.2
DT = 0.1
filtered = distance()
raws, filts = [], []
forward(50)
for i in range(60):
raw = distance()
filtered = ALPHA * raw + (1 - ALPHA) * filtered
raws.append(raw)
filts.append(filtered)
plot("raw", raw)
plot("filtered", filtered)
if raw < 30:
break
wait(DT)
stop()
# how much later does the filtered signal reach the value the raw one reached?
target = raws[len(raws) // 2]
def first_below(series):
for i, v in enumerate(series):
if v <= target:
return i
return len(series)
lag = (first_below(filts) - first_below(raws)) * DT
print("theory:", round((1 - ALPHA) / ALPHA * DT, 2))
print("lag:", round(max(lag, 0.0), 2))
Any program that meets the task's checks is marked correct in the simulator; this is one way, not the only way.