필터의 이해와 활용

Sinaenjuni·2023년 4월 5일
0

ROS

목록 보기
9/12

필터란?

센서로 측정된 데이터에는 노이즈가 포함되어 있다. 정확한 데이터를 얻기위한 과정으로 다음과 같이 다양한 방법들이 있다.

1. Recursive filter (재귀 필터)

이전 데이터들의 평균을 누적해서 현재 데이터를 추정하는 방법이다. 이전에 계산된 결과를 재귀적으로 사용하기 때문에 현재 데이터만 계산에 사용된다.

xˉk=axˉk1+(1a)xk\bar{x}_k=a\bar{x}_{k-1}+(1-a)x_k

2. Average filter (평균 필터)

평균을 계산할 때 사용되며,

  • 센서의 초기값을 설정
  • 배터리의 전압 추정
  • 등...

에 응용될 수 있다.
하지만 시간에 따라 변하는 물리량에 적합하지 않다는 특징을 가지고 있으며, 시간에 관계없이 모든 데이터가 현재 데이터에 영향을 미친다는 단점이 있다.

평균 (Average)

평균은 전체 데이터의 합을 개수로 나눈 값이다. 데이터의 전체 개수로 나눠야하기 때문에 새로운 데이터가 추가되면 모든 데이터를 다시 계산해야 한다는 단점이 있다.

xˉn=x1+x2+x3+...+xnn\bar{x}_n=\frac{x_1+x_2+x_3+...+x_n}{n}

평균의 재귀식

바로 전의 평균값과 데이터의 개수를 알고 있다면 비교적 쉽고 빠르게 평균을 구할 수 있다. 데이터가 순차적으로 입력되는 경우 효율성이 극대화 되며, 실시간 처리가 가능하다.

xˉn=x1+x2+x3+...+xnnxˉn1=x1+x2+x3+...+xn1n1nxˉn=x1+x2+x3+...+xnnn1xˉn=x1+x2+x3+...+xnn1nn1xˉn=x1+x2+x3+...+xn1n1+xnn1nn1xˉn=xˉn1+xnn1xˉn=n1nxˉn1+1nxnxˉn=(n1)xˉn1+1xnna=n1na=11n1n=1axˉn=axˉn1+(1a)xn\begin{aligned} \bar{x}_n=\frac{x_1+x_2+x_3+...+x_n}{n} && \rightarrow \bar{x}_{n-1}=\frac{x_1+x_2+x_3+...+x_{n-1}}{n-1} \\ n\bar{x}_n=x_1+x_2+x_3+...+x_n \\ \frac{n}{n-1}\bar{x}_n=\frac{x_1+x_2+x_3+...+x_n}{n-1} \\ \frac{n}{n-1}\bar{x}_n=\frac{x_1+x_2+x_3+...+x_{n-1}}{n-1} + \frac{x_{n}}{n-1} \\ \frac{n}{n-1}\bar{x}_n=\bar{x}_{n-1} + \frac{x_{n}}{n-1} \\ \bar{x}_n=\frac{n-1}{n}\bar{x}_{n-1} + \frac{1}{n}x_n \\ \bar{x}_n=\frac{(n-1) * \bar{x}_{n-1} + 1*x_n}{n} \\ a=\frac{n-1}{n} \\ a = 1-\frac{1}{n} \\ \frac{1}{n}=1-a \\ \bar{x}_n=a\bar{x}_{n-1}+(1-a)x_n \end{aligned}

코드

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(0)

def get_volt():
	noise = np.random.normal(0,4)
    # mean, std
    volt_mean = 14.4
    v = volt_mean + noise
    return v
    
def avg_filter(n, x, x_pre):
	alpha = (n-1) / n
    x_mean = alpha * x_pre = (1-alpha) * x
	return x_mean

3. Simple moving average filter (단순 이동 평균 필터)

전체 데이터 중의 일부분만을 이용해서 평균을 계산하는 방법이다. 데이터의 개수가 많으면 잡음 제거에 유리하지만 시간 지연이 발생한다. 반면 데이터의 개수가 적어지면 잡음 제거 성능을 떨어지지만 신호 변화를 잘 따라간다. 특히 평균을 구하기 위한 데이터의 개수를 잘 설정해야 한다.

xˉn=xnk+1+xnk+2+xnk+3+...+xnkxˉn1=xnk+xnk+1+xnk+3+...+xn1kxˉnxˉn1=xkxnkkxnˉ=xˉk1+xkxnkk\begin{aligned} \bar{x}_n=\frac{x_{n-k+1}+x_{n-k+2}+x_{n-k+3}+...+x_n}{k} \\ \bar{x}_{n-1}=\frac{x_{n-k}+x_{n-k+1}+x_{n-k+3}+...+x_{n-1}}{k} \\ \bar{x}_n-\bar{x}_{n-1}=\frac{x_k-x_{n-k}}{k} \\ \bar{x_n}=\bar{x}_{k-1}+\frac{x_k-x_{n-k}}{k} \end{aligned}
def mov_avg_filter(x_pre, x):
	n = len(x_pre)
    for i in range(n-1):
    	x_pre[i] = x_pre[i+1]
	x_pre[n-1] = x
    x_avg = np.mean(x_pre)
    return x_avg, x_pre

4. Low-pass filter (1차 저주파 통과 필터)

평균 필터들은 모든 데이터에 대해서 같은 가중치를 갖는다. 많은 경우에 과거 데이터보다 최근 데이터의 중요도가 높게된다. 특히 변화가 심한 데이터의 경우 잡음을 제거하면서 민감도를 동시에 달성하기 어렵다.
저주파 통과 필터의 경우 최근에 측정된 데이터에 높은 가중치를 주고, 오래된 데이터 일수록 낮은 가중치를 주는 방법으로 기존 평균 필터들의 문제를 개선한다.
alpha의 크기가 크면 측정 데이터의 변화에 민감해지며, 반대로 작다면, 잡음이 줄어들어 데이터의 변화가 줄어든다.

xˉk=axˉk1+(1a)xkxˉk1=axˉk2+(1a)xk1\begin{aligned} \bar{x}_k=a\bar{x}_{k-1}+(1-a)x_k \\ \bar{x}_{k-1}=a\bar{x}_{k-2}+(1-a)x_{k-1} \\ \end{aligned}
xˉk=a{axˉk2+(1a)xk1}+(1a)xk=a2xˉk2+a(1a)xk1+(1a)xk\begin{aligned} \bar{x}_k=a\{a\bar{x}_{k-2}+(1-a)x_{k-1}\}+(1-a)x_k \\ = a^2\bar{x}_{k-2}+a(1-a)x_{k-1}+(1-a)x_k \end{aligned}

code

def low_pass_filter(x_pre, x, alpha):
	x = alpha * x_pre + (1-alpha) * x
    return x

5. 가중 이동 평균 필터 (Weighted moving average filter)

산술 방식으로 옛날 데이터의 가중치가 지나치가 작아지는 문제를 방지한다.

xˉ=x1+2x2+3x3+4x4+5x5+6x61+2+3+4+5+6\bar{x} = \frac{x_1 + 2x_2 + 3x_3 + 4x_4 + 5x_5 + 6x_6}{1+2+3+4+5+6}

0개의 댓글