간단한 칼만 필터(Kalman Filter) 소스 코드와 사용 예제

칼만 필터(Kalman filter)는 노이즈가 포함된 측정치로 부터 실체 상태를 추정(推定, estimation)하는 도구다. 본 포스트의 칼만 필터 소스는 한 타겟의 위치를 추정하는 용도로 만들어 졌다. 
위키피디아 페이지(https://en.wikipedia.org/wiki/Kalman_filter)와 “Human Target Tracking in Multistatic Ultra-Wideband Radar” 논문 등을 참조하여 칼만 필터의 공식을 구현하였다.


F,H,Q,R matrix는 아래와 같은 값으로 정하여 사용하였다.

칼만 필터 c++ 소스는 아래와 같다. 

#include <malloc.h>
#include <Eigen/Dense>

__declspec(align(16)) class CKalmanFilter
{
private:

BOOL mFirst;
Eigen::MatrixXd mX;
Eigen::Matrix4d mP;
Eigen::Matrix4d mF;
Eigen::MatrixXd mH;
Eigen::Matrix2d mR; // measurement noise covariance
Eigen::Matrix4d mQ; // process noise covariance

public:

void* operator new(size_t i)
{
return _mm_malloc(i, 16);
}

void operator delete(void* p)
{
_mm_free(p);
}

CKalmanFilter(double process_var, double measure_var, double T)
{
Eigen::MatrixXd x(4, 1);
Eigen::MatrixXd h(2, 4);
mFirst = TRUE;

mX = x;
mX << 0, 0, 0, 0;

mP = Eigen::Matrix4d::Identity();

mF = Eigen::Matrix4d::Identity();
mF(0, 1) = T;
mF(2, 3) = T;

mH = h;
mH << 1, 0, 0, 0,
0, 0, 1, 0;

mR << measure_var, 0, 0, measure_var;

mQ = Eigen::Matrix4d::Zero();
mQ(1, 1) = pow(T, 2)*process_var;
mQ(3, 3) = pow(T, 2)*process_var;
}

~CKalmanFilter()
{

}

void filtering(double measure[2], double correct[2])
{
Eigen::MatrixXd Zkm1(2, 1);
Eigen::MatrixXd Zk(2, 1);
Eigen::MatrixXd S;
Eigen::MatrixXd K;

if (mFirst)
{
mX << measure[0], 0, measure[1], 0;
mFirst = FALSE;
}

Zk(0, 0) = measure[0];
Zk(1, 0) = measure[1];

// Prediction of state estimation :
// X(k|k-1) = F * X(k|k?1)
mX = mF*mX;

// Prediction of error covariance:
//P( k|k?1) = F*P(k?1|k?1)*FT + Q(k)
mP = mF*mP*mF.transpose() + mQ;

//Prediction of observation
//z(k|k?1) = H*x(k|k?1)
Zkm1 = (mH*mX);
//Compute innovation covariance:
//S(k) = H*P(k|k?1)*HT + R(k)
S = mH*mP*mH.transpose() + mR;

//Kalman’s gain:
//K(k) = P(k|k?1)*HT*invS(k)
K = mP*mH.transpose()*S.inverse();

//  State estimation update:
// x^(k|k) = x?(k|k?1) + K(k)*[z(k) ? z(k|k?1)]
mX = mX + (K*(Zk - Zkm1));
// Error covariance update:
//P(k|k) = [I ? K(k)*H]*P(k|k?1)
mP = (Eigen::Matrix4d::Identity() - (K*mH))*mP;

correct[0] = mX(0, 0);
correct[1] = mX(2, 0);
}
};

matrix 연산을 위해 Eigen 라이브러리를 사용하였으며, class 의 operator new/delete는 visual c/c++에서 C4316 warning을 피하기 위해 추가했다. (https://stackoverflow.com/questions/20104815/warning-c4316-object-allocated-on-the-heap-may-not-be-aligned-16).

Class 생성자 파라메터
  • double process_var - process noise variance
  • double measure_var - measurement noise variance
  • double T: 위치 측정 시간 간격 Δt seconds.

filtering 함수 파라메터
  • double measure[2] - measured location data, measure[0]=x, measure[1]=y
  • double correct[2] -  estimated location data, x=correct[0], y=correct[1]
아래 비디오는 위 칼만 필터 소스를 사용해 만든 예제이며, 마우스 위치를 측정 데이터(붉은색 선)로 사용하여 위치를 추정(녹색 선)한다. 


위 예제에서 사용된 칼만 필터는 아래와 같이 사용 되었다.

  • 생성
CKalmanFilter *kalmanfilter = NULL;
kalmanfilter = new CKalmanFilter(9.0, 1.0, 0.01);


  • 필터링
double measure[2] = { 0, };
double correct[2] = { 0, };

measure[0] = (double)x;
measure[1] = (double)y;

kalmanfilter->filtering(measure, correct);


[관련 포스트]

댓글

이 블로그의 인기 게시물

간단한 cfar 알고리즘에 대해

쉽게 설명한 파티클 필터(particle filter) 동작 원리와 예제

windows에서 간단하게 크롬캐스트(Chromecast)를 통해 윈도우 화면 미러링 방법

CA-CFAR 예제 코드

Keras 모델 저장(save_model) 및 불러오기 (load_model) 방법