본문 바로가기

Study_Engineering

About Avg, MovAvg, LPF

728x90

 

  • Filter : 어떤 신호에서 원하지 않는 신호를 차단하거나, 원하는 신호만을 통과시키는 기능을 하는 회로 등의 장치나 과정
  • 신호 처리의 일부로, 특정 Frequency를 차단 혹은 통과시킨다
  • 원하지 않는 신호인 Noise를 제거하기 위해 사용
  • 모든 Filter들은 이전의 값이 현재 값에 영향을 주는 Recursive(재귀)적인 구조를 갖는다

 

 

1) Average Filter

  • N개의 Sample을 모두 더하고 N으로 나눠 평균을 구하는 단순한 방식의 Filter
    • 평균 계산에 직전 평균값과 데이터 갯수, 새로 추가된 데이터 만을 필요로 함
    • 간단하지만 Noise 제거에 효과적
  • (1 - N) x 이전까지의 평균 + N x 현재값 = Average Filter
  • (수식 찍어서 사진 추가)

 

  • 이전의 값 (x_k-1) 이 현재값(x_k)에 영향을 주는 Recursive(재귀) 적인 구조
    • 데이터가 순차적으로 입력되는 경우 데이터를 저장할 필요가 없고 계산 효율이 높아 실시간 처리에 유리
    • 평균을 취함으로써 Noise 제거 가능

 

- Average Filter 식 유도 과정

  • (아래 과정 수식으로 정리)

 

  • Avg Filter는 Sensor 초기화에도 유용하게 쓰일 수 있다
    • 어떤 이유로 Sensor의 영점이 틀어질 경우 (Ex) 체중계) 처음 일정시간 동안의 Sensor값의 평균을 초기값으로 잡아 영점을 잡을 수 있음

 

- Average Filter C 코드

int k;                              // Number of sample
double x_prev;                      // Previous Average

double AvgFilter(double x){

    double average, alpha;

    k += 1;                         // Add 1 to the number of sample

    alpha = (k - 1) / (k + 0.0);    // Alpha value of the Average Filter 

    average = alpha * x_prev + (1 - alpha) * x; // Recursive expression of average filter

    x_prev = average;               // Update the previous state value of average filter

    return average;
}

 

 

 - Matlab 코드

clear all

dt = 1;                         % Set time interval to 1second
t = 0:dt:100;                   % Make 100 Time samples (0~100)

Nsamples = length(t);           % Fix the number of samples to 100

avgsaved = zeros(Nsamples, 1);  % Make an array which has zero only
xmsaved = zeros(Nsamples, 1);

for k=1:Nsamples
    xm = getvolt();             % Get the value which Noise is added to 14V value
    avg = avgfilter(xm);        % Put the filtered values

    avgsaved(k) = avg;          % Save the measurements and estimated values to array
    xmsaved(k) = xm;
end

figure
plot(t, xmsaved, 'r:*')
hold on
plot(t, avgsaved, 'o-')
legend('measured', 'average')
  • Exavgfilter.m

 

function z = getvolt() 

w = 0+randn(1,1);
z = 14 + w;         % Add noise to 14V
                    % (Assume that the system`s voltage is 14V)
  • getvolt.m

 

function avg = avgfilter(x)

persistent preavg k
persistent firstrun

if isempty(firstrun)    % If the firstrun array is empty,
    k = 1;
    preavg = 0;

    firstrun = 1;
end

alpha = (k-1) / k;
avg = alpha * preavg + (1 - alpha) * x;         % Main Part of Average Filter

preavg = avg;
k = k+1;
  • avgfilter.m

 

실행 결과

 

 

 

2. Moving Average Filter

  • 측정하려는 값이 위처럼 일정하지 않고, 지속적으로 변하면 Average Filter로는 대상의 동적인 움직임을 따라가지 못함
    • Average Filter는 전체 데이터에 대한 평균만을 측정하므로 최근 데이터의 변화량을 감지할 수 없다
    • 이로 인해 시간이 지날수록 오차가 쌓이게 됨
  • Ex) 1 ~ 5까지의 입력이 들어오는 경우
측정 값 1 2 3 4 5
Average Filter 1 1.5 2 2.5 3
Moving Avg Filter 1 1.5 2.5 3.5 4.5

 

추후 직접 Plot한 그래프로 대체

 

  • 즉 동적인 대상체의 값을 추정하려는 경우 시간의 변화에 따른 변화를 반영하기 위해 Moving Average Filter 사용
  • 현재 시점에서 과거의 일부분만 보며 계속 평균을 구하는 방식
  • 혹은 구간을 이동시키며 그 구간에 있는 값들의 평균값을 구하여 현재 값을 추정하는 Filter

(추후 직접 만든 표로 대체)

 

 

  • $ \tilde{x}_{k} = \frac{x_{k-n+1} + x_{k-n+2} ... + x_{k}}{n} = \tilde{x}_{k-1} + \frac{x_{k}-x_{k-n}}{n} $

(수식으로 대체)

 

  • 이후 추정값이 설정치보다 크고 작음에 따른 동작 설정 필요
    • Ex) 모터 속도
    • 추정값이 설정 속도보다 크다면 감속, 작다면 가속
  • 구간 크기가 클 경우 추정치의 정확도는 향상되나 구간 크기만큼의 값이 들어오기 전까지는 정확한 추정치를 얻지 못하는 지연 구간이 발생
  • 또한 해당 길이만큼의 데이터를 가지고 있어야 하므로 메모리를 많이 차지하고, 연산량이 증가하게 됨

 

 

구간 크기가 50인 경우가 20인 경우보다 지연이 더 길게 발생

 

 

- MovAvgFilter C코드

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#define FALSE (0)
#define TRUE (!FALSE)

typedef struct {
	int32_t* buffer;
	int32_t sum;
	uint32_t length;
	uint32_t currentIdx;
}ST_MovingAverage;

int32_t MovingAverageInit(ST_MovingAverage* movingAverage, uint32_t length)
{
	int32_t result;

	movingAverage->currentIdx = 0;
	movingAverage->sum = 0;
	movingAverage->length = length;

	movingAverage->buffer = (int32_t*)malloc(length * sizeof(int32_t));

	if (movingAverage->buffer == NULL) {
		result = FALSE;
	}
	else {
		memset(movingAverage->buffer, 0, length * sizeof(int32_t));
		result = TRUE;
	}

	return result;
}

void MovingAverageDelete(ST_MovingAverage* movingAverage)
{
	free(movingAverage->buffer);
}

int32_t MovingAverage(ST_MovingAverage* movingAverage, int32_t value)
{
	int32_t result;

	movingAverage->sum -= movingAverage->buffer[movingAverage->currentIdx];
	movingAverage->sum += value;
	movingAverage->buffer[movingAverage->currentIdx] = value;

	movingAverage->currentIdx++;
	movingAverage->currentIdx %= movingAverage->length;

	result = movingAverage->sum / movingAverage->length;

	return result;
}

int main()
{
	int32_t InitResult = 0;
	int32_t sensorOutput = 0;
	ST_MovingAverage movingAverage[2];

	InitResult = MovingAverageInit(&movingAverage[0], 10);
	if (InitResult == FALSE) {
		printf("Fail MovingAverage[0] Init\n");
		return 0;
	}
	InitResult = MovingAverageInit(&movingAverage[1], 50);
	if (InitResult == FALSE) {
		printf("Fail MovingAverage[1] Init\n");
		return 0;
	}
	
	for (int i = 0; i < 100; i++) {
		sensorOutput = 50 + (rand() % 21 - 10);
		
		printf("%d, %d, %d, %d\n", i, sensorOutput, MovingAverage(&movingAverage[0], sensorOutput), MovingAverage(&movingAverage[1], sensorOutput));
	}

	MovingAverageDelete(&movingAverage[0]);
	MovingAverageDelete(&movingAverage[1]);

	return 0;
}

 

 

- Matlab 코드

clear all

Nsamples = length(t);         
Xsaved = zeros(Nsamples, 1);  
Xmsaved = zeros(Nsamples, 1);

for k=1:Nsamples
    xm = getvolt_moving();       % y = x + 1 form 
    x = MovAvgfilter(xm);      

    Xsaved(k) = x;         
    Xmsaved(k) = xm;
end

dt = 1;
t = 0:dt:Nsamples*dt - dt;

figure
hold on
plot(t, Xmsaved, 'r.')
plot(t, Xsaved, 'b')
legend('measured', 'moving average')
  • ExMovAvgfilter.m
  • 1초 간격으로 총 100개의 샘플에 Moving Average Filter를 적용하는 코드

 

function avg = MovAvgfilter(x)

persistent preAvg n xbuf
persistent firstrun

if isempty(firstrun)    
    n = 5;			% Take Mov Avg Filter to 5 previous values
    xbuf = x*ones(n+1, 1);	% Initialize xbuf to [1 1 1 1 1]*input(x)
    
    k = 1;
    preavg = x;

    firstrun = 1;
end

for m = 1:n			% Renew input values to 1 ~ n	
	xbuf(m) = xbuf(m+1);	% Ex) [1,2,3,4,5] -> [2,3,4,5,6] -> [3,4,5,6,7]
    				% As [1,2,3,4,5,6,7] is input sequentially
end

xbuf(n+1) = x;				% [1,2,3,4,5] -> [2,3,4,5,6]
					% Remove the first value and add the input value
avg = preAvg + (x - xbuf(1)) / n;

preAvg = avg;
  • MovAvgFilter.m
  • 평균 값 산출에 5개의 Sample 사용

 

 

 

3. Low Pass Filter (1st Order)

  • Low Frequency 신호는 통과시키고 High Frequency 신호는 차단하는 Filter
    • 보통 측정하려는 신호는 Low Frequency이고 Noise는 High Frequency인 경우가 많아 Noise 제거용으로 사용
    • (LPF 회로 사진 추가)
    • 회로 중 C(Capacitor)는 Frequency에 따라 바뀌는 하나의 가변저항이라 생각할 수 있다

Low Pass Filter 구성
Cutoff Frequency 지점 및  주파수 응답 특성 곡선

 

  • 위와 같은 주파수 응답 특성 곡선에서 -3dB가 되는 지점을 Cutoff Frequency라 한다
    • -3dB는 아래와 같이 전력 (입력 대비 출력)이 1/2가 되는 주파수 지점이다

 

  • 특정 수식의 Filter가 아닌 Low Frequency 신호만을 통과시키는 특성을 갖는 모든 Filter를 총칭
  • 위의 Moving Average Filter에서 과거의 값들보다 현재에 가까운 값에 가중치를 더 크게 부여하는 방식
    • Moving Average Filter의 경우 아래와 같이 모든 데이터에 동일한 가중치를 적용
    • (수식 추가)

MovAvgFilter 수식

 

  •  이는 가장 최근의 데이터와 가장 오래된 데이터에 동일한 가중치를 적용하는 방식으로, 자동차나 비행기 처럼 빠르게 움직이는 물체에서는 노이즈를 제거하며 변화 추이를 반영하기 어려움

 

LPF 수식

  • Average Filter와 동일한 식
  • 스텝이 지날 수록 이전 데이터에는 낮은 가중치가 곱해지게 됨
  • α가 크면 Noise 제거율이 올라가나 변화에 둔감해짐
    • α가 크면  추정값 x^_k-1 의 비중이 더 커지게 되어 직전 추정값과 현재 추정값이 크게 달라지지 않게 됨
  •  α가 작으면 Noise는 많아지나 변화에 민감해짐
    • α가 작으면 1 - α 가 상대적으로 카져 추정값 계산에 측정값 x_k가 더 많이 반영되게 되어 측정값의 변화에 더 민감해짐 

 

function avg = MovingFilter(x)

persistent preAvg n xbuf
persistent firstRun

if isempty(firstRun)
	n = 5;
    xbuf = x*ones(n+1, 1);
    
    k = 1;
    preAvg = x;
    
    firstRun = 1;
end

for m = 1:n
	xbuf(m) = xbuf(m+1);
end
xbuf(n+1) = x;

avg = preAvg + 1.5*(x - xbuf(1)) / n;	% Give 1.5 weighting value to present input value 

preAvg = avg;
  • MovAvgFilter.m
  • 기존의 MovAvgFilter 코드에서 Weighting 부분만 추가

 

 

 

 

 

 

 

 


참고 자료 : 

https://limitsinx.tistory.com/69

 

[제어시스템공학-1] Average Filter(평균필터)

오늘 정리해볼 주제는 Average Filter(평균필터)입니다. 정말 간단한것부터 출발하는데요, 평균필터란 N개의 샘플이 있다고하면, N개를 모두 더하고 N으로 나누는것을 의미합니다. 즉, [1,2,3,4,5]라는

limitsinx.tistory.com

 

https://gaussian37.github.io/autodrive-ose-table/

 

Optimal State Estimation 관련 글 목록

gaussian37's blog

gaussian37.github.io

 

'Study_Engineering' 카테고리의 다른 글

표준편차, 분산, 공분산  (0) 2024.01.16
EKF를 통한 자율주행 로봇의 Localization  (2) 2024.01.15
State Space Equation이란  (0) 2024.01.12
About Electric Circuit  (1) 2024.01.08
전기/전자 관련 기초 지식  (0) 2023.12.15