The worksheetDownload the PDF
Answers

U4.3 The low pass filter

Noise and filtering · University · about 30 min

BugBotLab

What this lesson is about

A moving average, then the exponential filter that does the same job in one line and no memory.

Questions 7 marks in all

  1. [1 mark]An exponential filter starts at 50 and sees three readings of 60. What does it print?

    ALPHA = 0.2
    filtered = 50.0
    for raw in (60, 60, 60):
        filtered = ALPHA * raw + (1 - ALPHA) * filtered
        print(round(filtered, 2))
    Answer:
    52.0
    53.6
    54.88

    Each step closes a fifth of the remaining gap: 50 + 0.2 x 10 = 52, then 52 + 0.2 x 8 = 53.6, then 53.6 + 0.2 x 6.4 = 54.88.

  2. [1 mark]Using the lesson's rule of thumb, an exponential filter with alpha = 0.1 behaves roughly like a moving average of how many readings?

    Answer: 19. The equivalent window is (2 - alpha) / alpha = 1.9 / 0.1 = 19 readings.
  3. [1 mark]Why should an exponential filter be started at the first reading rather than at 0?

    1. AStarting at 0 makes the output climb from zero for the first second, which looks like a real signal
    2. BStarting at 0 makes alpha wrong for the whole run
    3. CStarting at 0 makes the filter unstable
    4. DThe filter needs a nonzero value to avoid dividing by zero
    Answer: A. From 0 the filter spends its first steps converging on reality. That startup transient is easily blamed on the hardware; starting at the first reading removes it.
  4. [1 mark]Compared with a moving average giving similar smoothing, what is the main practical advantage of the exponential filter?

    1. AIt stores only its previous output, instead of the last n readings
    2. BIt has no delay
    3. CIt rejects outliers
    4. DIts output reaches a step's new value in exactly one step
    Answer: A. The moving average costs n stored numbers and n additions per tick. The exponential filter does the same job in one line with one stored value. Both still delay.
  5. [1 mark]Rearranged, the filter is filtered = filtered + alpha * (raw - filtered). In the Kalman filter of U6.3 the update has the same shape. What is different there?

    1. AThe weighting is computed each tick from how uncertain the belief is compared with the measurement
    2. BThe weighting is always 0.5
    3. CThe measurement is filtered twice
    4. DThe difference raw - filtered is squared
    Answer: A. The Kalman gain plays the role of alpha, but it is recalculated every tick from the variances instead of being a constant you chose.
  6. [1 mark]In signal processing terms, the exponential filter is a first order what kind of filter?

    Answer: low pass. It passes slow changes and attenuates fast ones, so it is a first order low pass filter, also called an exponentially weighted moving average.
  7. [1 mark]Put these lines in order to run an exponential filter while driving.

    Number the lines 1 to 5 to put them in the right order.

    1. filtered = ALPHA * raw + (1 - ALPHA) * filtered
    2. for i in range(60):
    3. raw = distance()
    4. plot("filtered", filtered)
    5. filtered = distance()
    Answer:
    filtered = distance()
    for i in range(60):
        raw = distance()
        filtered = ALPHA * raw + (1 - ALPHA) * filtered
        plot("filtered", filtered)

    Start the filter at a real reading, then each tick read, update, and plot the filtered value.

The task: a low pass filter

Drive towards the wall with an exponential filter running, plotting raw and filtered as you go, and print the alpha: you chose.

from bugbot import *
connect()

ALPHA = 0.25
filtered = distance()

The hint students can ask for: filtered = alpha * new + (1 - alpha) * filtered, once per tick. Plot both lines while the robot drives towards the wall, and watch the filtered line follow the raw one at a distance.

A solution

from bugbot import *
connect()

ALPHA = 0.25
filtered = distance()
forward(45)
for i in range(70):
    raw = distance()
    filtered = ALPHA * raw + (1 - ALPHA) * filtered
    plot("raw", raw)
    plot("filtered", filtered)
    if filtered < 30:
        stop()
    wait(0.1)
stop()
print("alpha:", ALPHA)

Any program that meets the task's checks is marked correct in the simulator; this is one way, not the only way.