본문 바로가기
개발/android

안드로이드에서의 가장 간단하고 확실한 칼만필터(Kalman Filter) 테스트

by 매몰 2014. 3. 17.

칼만필터 테스트

 

 

얼마 전 아는 지인을 통해 칼만필터(Kalman Filter)라는것을 알게 되었다.

 

오래전 기울기센서를 이용한 "운전좀하냐" 라는 게임을 만들때에 자동차가 엄청 흔들리고 불안정해서 온갖방법과 테스트를 해보았지만 결국 만족스러운 결과를 못내고 출시해야 했다ㅠㅠ

 

그런데 우연히 지인을 통해 알게된 칼만필터를 써보니!! 한방에 해결이 되는게 아닌가ㅎㅎ

물론 좀더 손을 봐야 할것 같지만 어쨋든 예전소스랑 칼만필터를 결합하니 제법 만족스런 결과를 얻어냈다

 

그래서 여기에 직접 칼만필터의 위력을 보여주고자 한다...

 

우선 칼만필터란 잡음같은것을 없에는 기법이다. 기울기센서에서는 민감한 센서에 의해 아주작은 손떨림에도 반응하여 값이 흔들리는 현상을 보정해 준다

 

기본원리는 간단하다. 

기울기센서 값을 계속 저장해 두었다가 평균값을 계산하여 현재값에 적용해 주는 것이다. 그러면 어느정도 값이 평탄해진다. 여기에 가중치가 들어간 평균값을 사용하면 더 정확해 진다.

 

이론적으로 들어가면 이보다 더 복잡하지만 내가 머리가 나빠서ㅎㅎ 그냥 내 식으로 직접 소스를 짜서 확인해 보았다.

 

 

아래 프로그램은 하나의 뷰객체(오브젝트)를 기울기센서를 이용해 움직인다

즉, 아주 간단한 게임인것이다ㅎㅎ 여기에 적오브젝트를 넣어 피해다니게 하면 게임이 된다ㅎㅎ

한번 해보시길~ㅎㅎ

 

 

-------------- .jave --------------

 

public class MainActivity extends Activity implements SensorEventListener {

 

private SensorManager mSensorManager;

private Sensor mSensor; 

 

private View mLayout;

private float mX, mY;

 

private KalmanFilter mKalmanAccX;

private KalmanFilter mKalmanAccY;

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

 

                //움직일 오브젝트(뷰객체)가 있는 부모 레이아웃

mLayout = this.findViewById(R.id.Layout);

 

    //칼만필터 초기화

mKalmanAccX = new KalmanFilter(0.0f);

mKalmanAccY = new KalmanFilter(0.0f);

 

//기울기 센서 등록

mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);

mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_GAME);

}

 

@Override

public void onAccuracyChanged(Sensor sensor, int accuracy) {

// TODO Auto-generated method stub

 

}

 

@Override

public void onSensorChanged(SensorEvent event) {

float x = event.values[0];

float y = event.values[1];

 

    //칼만필터를 적용한다

float filteredX = (float) mKalmanAccX.update(x);

float filteredY = (float) mKalmanAccY.update(y);

                

                //이주석을 풀면 칼만필터를 사용하지 않는다

    //filteredX = x;

//filteredY = y;

 

                //부모 레이아웃을 스크롤시켜 마치 뷰객체(오브젝트)가 움직이는것처럼 보이게 한다

                //저장해둔 예전값과 현재값의 차를 넣어 변화를 감지한다

                //여기에 100을 곱하는것은 차의 숫자가 워낙 작아 움직임이 보이지 않기 때문이다.

                //즉, 스피드라고도 보면 된다ㅎㅎ 더 큰숫자를 넣으면 더 빠르게 움직인다.

mLayout.scrollBy((int)((mX - filteredX) * 100), (int)((mY - filteredY) * 100));

 

                //예전값을 저장한다

mX = filteredX;

mY = filteredY;

}

 

  //칼만필터를 클래스로 선언한다. 여기에 쓰이는 공식은 이미 여러 사이트에 소개되어있다.

class KalmanFilter {

private double Q = 0.00001; 

private double R = 0.001;

private double X = 0, P = 1, K;

 

    //첫번째값을 입력받아 초기화 한다. 예전값들을 계산해서 현재값에 적용해야 하므로 반드시 하나이상의 값이 필요하므로~

KalmanFilter(double initValue) {

X = initValue;

}

 

    //예전값들을 공식으로 계산한다

private void measurementUpdate(){

K = (P + Q) / (P + Q + R);

P = R * (P + Q) / (R + P + Q);

}

 

    //현재값을 받아 계산된 공식을 적용하고 반환한다

public double update(double measurement){

measurementUpdate();

X = X + (measurement - X) * K;

 

return X;

}

}

 

}

 

 

-------------- .xml --------------

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

 

    <!-- 부모 레이아웃 -->

    <RelativeLayout android:id="@+id/Layout"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent">

    

  <!-- 뷰객체(오브젝트) -->

    <TextView android:id="@+id/textview"

        android:layout_width="100dp"

        android:layout_height="100dp"

  android:layout_centerInParent="true"

        android:background="#000000" />

    

</RelativeLayout>

 

</RelativeLayout>

 

 

칼만필터 미적용 상태

 

 

 

 

칼만필터 적용 상태

 

 

 

별거 아닐수도 있지만 

당시 저는 위와같이 칼만필터를 적용한것과 아닌것을 비교해보고 완전 감동받았습니다ㅎㅎ

역시 세상에는 천재들이 많은것 같아요~ 저런 필터를 다 만들다니... 고맙습니다ㅎㅎ

잘 이용해서 잘 쓸게요~

 

 

 

 

 

사업자 정보 표시
주식회사 머리말 | 고영진 | 서울특별시 송파구 중대로 135 서관 10층 (가락동, 아이티벤처타워) | 사업자 등록번호 : 524-88-00727 | TEL : 010-9990-3674 | Mail : gyjmeba@hanmail.net | 통신판매신고번호 : 2017-서울강남-03941호 | 사이버몰의 이용약관 바로가기