Booil Jung

칼만 필터

우리가 사는 세상은 불확실성으로 가득 차 있다. 우리가 만드는 시스템 모델은 현실을 완벽하게 반영하지 못하고, 우리가 사용하는 센서의 측정값에는 항상 노이즈가 섞여 있다.1 예를 들어, GPS 수신기는 현재 위치를 알려주지만 수 미터의 오차 범위를 가지며 5, 로켓의 움직임은 물리 법칙에 기반한 모델로 예측할 수 있지만, 예상치 못한 바람이나 대기 저항 같은 외부 요인 때문에 예측은 항상 빗나간다.6 칼만 필터는 바로 이러한 불확실성 속에서 시스템의 상태를 가장 정확하게 추정하기 위해 탄생한 알고리즘이다.

칼만 필터(Kalman Filter)는 시간에 따라 변하는 동적 시스템의 상태를 추정하는 재귀적(recursive) 알고리즘이다. 이 알고리즘은 불완전하고 노이즈가 포함된 일련의 측정값들을 사용하여, 그 어떤 단일 측정값보다도 더 정확한 상태 추정치를 계산해낸다.1

여기서 두 가지 핵심 단어에 주목해야 한다. 첫째, ‘필터(filter)’라는 단어는 이 알고리즘이 원하는 정보(시스템의 실제 상태)를 원하지 않는 노이즈로부터 걸러내는 역할을 한다는 의미다.3 둘째, ‘재귀적(recursive)’이라는 단어는 칼만 필터의 가장 중요한 특징 중 하나를 설명한다. 현재 상태를 추정하기 위해 과거의 모든 데이터를 저장하고 계산할 필요 없이, 오직 직전 시간 단계의 추정값과 현재 시간의 측정값만 있으면 된다.2 이러한 특성 덕분에 칼만 필터는 계산 효율성이 매우 높고 메모리 사용량이 적어, 아폴로 우주선의 유도 컴퓨터와 같은 제한된 자원을 가진 시스템부터 오늘날의 실시간 로봇, 드론, IoT 장치에 이르기까지 광범위하게 사용될 수 있었다.3

단순히 노이즈를 제거하여 데이터를 매끄럽게 만드는 것(smoothing)을 넘어, 칼만 필터의 본질은 두 가지 불완전한 정보 소스, 즉 ‘시스템 모델의 예측’과 ‘센서의 측정’을 융합하여 통계적으로 최적의 추정치를 만들어내는 데 있다. 이는 최소 평균 제곱 오차(Minimum Mean-Square Error, MMSE) 관점에서 최적의 해를 제공하는 추정기(estimator)이다.2

graph TD
    subgraph "입력: 불완전한 정보 소스"
        A["<b>시스템 모델의 예측</b><br/><i>'아마도 여기 있을 것이다'</i><br/>(예: 항해 계획, 물리 법칙)<br/>불확실성 포함 (프로세스 노이즈)"]
        B["센서의 측정값"]
    end

    subgraph "처리"
        C<b>칼만 필터</b><br/>(최적의 융합 엔진)
    end

    subgraph "출력: 개선된 정보"
        D["<b>최적 상태 추정치</b><br/><i>'가장 가능성 높은 현재 상태'</i><br/>(어떤 단일 정보보다 정확함)"]
    end

    A -- "예측된 상태와 불확실성" --> C
    B -- "측정된 상태와 불확실성" --> C
    C -- "각 정보의 불확실성을<br/>가중치로 사용하여 융합" --> D

[그림] 칼만 필터는 불확실한 예측과 불확실한 측정을 현명하게 조합하여 최상의 추정치를 만들어내는 알고리즘이다.

graph TD
    A("k-1 시점의 최종 추정치<br>x̂<sub>k-1|k-1</sub>") --> B{"칼만 필터 계산 루프"};
    C("k 시점의 새로운 측정치<br>z<sub>k</sub>") --> B;
    B --> D("k 시점의 최종 추정치<br>x̂<sub>k|k</sub>");
    D -- "다음 계산을 위한 입력으로 사용" --> E(("k+1 시점의 루프"));

칼만 필터의 작동 원리를 직관적으로 이해하기 위해, 폭풍우가 몰아치는 바다 한가운데서 자신의 위치를 파악하려는 선장의 상황을 상상해 보자.10

칼만 필터는 이 과정을 수학적으로 정립하여, 각 정보의 불확실성을 정량화하고 이를 바탕으로 최적의 가중치를 계산하여 두 정보를 융합하는 알고리즘이다.

용어를 명확히 할 필요가 있다. 이 자습서에서는 주로 필터링에 초점을 맞추지만, 세 가지 개념은 미묘하게 다르다.11

이 자습서는 실시간 처리에 가장 널리 사용되는 필터링을 중심으로 칼만 필터의 세계를 탐험할 것이다.

gantt
    title 필터링, 예측, 스무딩 개념 비교
    dateFormat  X
    axisFormat  %S
    
    section 데이터<br>사용 범위
    측정값 (z_1... z_k... z_{k+n}) : 0, 100
    
    section 추정 시점
    필터링 (현재 k 추정)       : crit, 50, 1s
    예측 (미래 k+n 추정)      : 75, 25s
    스무딩 (과거 k 재추정)     : milestone, 50, 0s

    section 사용 데이터<br>설명
    필터링 (z_1... z_k 사용)      : 0, 51s
    예측 (z_1... z_k 사용)        : 0, 51s
    스무딩 (z_1... z_{k+n} 사용)  : 0, 100s

칼만 필터 알고리즘의 심장은 ‘예측(Prediction)’과 ‘갱신(Update)’이라는 두 단계가 끊임없이 반복되는 루프에 있다.2 이 두 단계의 춤을 통해 필터는 불확실성을 길들이고 최적의 추정치에 점차 수렴해 나간다.

  1. 예측 단계 (시간 갱신, Time Update): 이 단계에서 필터는 시스템의 동역학 모델을 사용하여 현재 상태와 오차 공분산을 다음 시간 단계로 전파(propagate)한다. 즉, 새로운 측정값이 들어오기 에, 이전 상태를 기반으로 다음 상태가 어떠할지를 예측한다.8 이 예측된 상태를 사전 추정치(a priori estimate)라고 부른다.9 이는 “우리가 어디에 있었다고 생각하는지”와 “시스템이 어떻게 움직이는지”에 대한 지식을 바탕으로 한 최선의 추측이다.
  2. 갱신 단계 (측정 갱신, Measurement Update): 새로운 측정값이 들어오면, 필터는 이 정보를 사용하여 사전 추정치를 보정한다. 먼저, 예측된 상태라면 어떤 측정값이 관측되었을지를 계산하고, 이를 실제 측정값과 비교한다. 이 둘의 차이를 혁신(innovation) 또는 잔차(residual)라고 부른다.2 이 혁신 값에 ‘칼만 이득(Kalman Gain)’이라는 최적의 가중치를 곱하여 사전 추정치를 보정하고, 새로운 사후 추정치(a posteriori estimate)를 얻는다.9 이 사후 추정치는 예측과 측정을 모두 반영한 현재 시간의 최종 추정치가 된다.

이 사후 추정치는 다시 다음 루프의 예측 단계를 위한 입력으로 사용되며, 이 과정이 재귀적으로 무한히 반복된다.

graph TD
    subgraph "k-1 시점"
        A["<b>사후 추정치 (k-1)</b><br><i>Posteriori Estimate</i><br><b>x̂<sub>k-1|k-1</sub>, P<sub>k-1|k-1</sub></b><br>이전 단계의 최종 결과"]
    end

    A -- "시스템 모델(F)을 통해<br>다음 상태를 추측" --> B

    subgraph "k 시점: 예측 단계 (Time Update)"
        B["<b>사전 추정치 (k)</b><br><i>A Priori Estimate</i><br><b>x̂<sub>k|k-1</sub>, P<sub>k|k-1</sub></b><br>측정값 없이 예측만 한 상태<br><i>불확실성 증가!</i>"]
    end
    
    C["<b>새로운 측정값 (k)</b><br><i>Measurement</i><br><b>z<sub>k</sub></b>"] -- "예측과 실제 측정의<br>차이(혁신) 계산" --> D

    B --> D

    subgraph "k 시점: 갱신 단계 (Measurement Update)"
        D{"<b>칼만 이득(K) 계산 및<br>상태 갱신</b>"}
    end

    D -- "예측과 측정을 융합하여<br>추정치 보정" --> E

    subgraph "k 시점"
        E["<b>사후 추정치 (k)</b><br><i>Posteriori Estimate</i><br><b>x̂<sub>k|k</sub>, P<sub>k|k</sub></b><br>현재 단계의 최종 결과<br><i>불확실성 감소!</i>"]
    end

    E -- "다음 루프(k+1)의<br>입력으로 재귀" --> A

이 예측과 갱신의 춤을 추기 위해, 우리는 세상을 수학적으로 모델링해야 한다. 칼만 필터는 이를 ‘상태’와 ‘불확실성’이라는 두 가지 개념으로 표현한다.

상태(state)란 특정 시간에 시스템을 완벽하게 설명하는 데 필요한 변수들의 집합이다.2 이 변수들은 벡터 형태로 표현되며, 이를 상태 벡터라고 한다. 예를 들어, 1차원 공간을 움직이는 물체의 상태는 위치와 속도로 나타낼 수 있다. \(x = \begin{bmatrix} \text{위치} \\ \text{속도} \end{bmatrix}\) 만약 로켓의 고도를 추적한다면, 상태 벡터는 고도, 속도, 가속도를 포함할 수 있다.7 \(x = \begin{bmatrix} \text{고도} \\ \text{속도} \\ \text{가속도} \end{bmatrix}\) 칼만 필터의 궁극적인 목표는 바로 이 숨겨진 상태 벡터 $x$를 추정하는 것이다.

현실 세계에서 우리는 시스템의 상태를 단 하나의 값으로 완벽하게 알 수 없다. 항상 불확실성이 존재한다. 칼만 필터는 이러한 불확실성을 가우시안 분포(정규 분포)로 모델링한다.3 가우시안 분포는 두 개의 매개변수로 완벽하게 정의된다.

칼만 필터는 시스템에 존재하는 불확실성을 두 가지 주요 원인으로 나누어 모델링한다.

  1. 프로세스 노이즈 (Process Noise, $w$): 우리의 모델은 현실을 완벽하게 설명하지 못한다. 등속도로 움직인다고 가정한 자동차는 실제로는 운전자의 미세한 가속 페달 조작, 도로의 마찰 변화, 바람의 영향 등으로 인해 완벽한 등속도 운동을 하지 않는다.6 이처럼 시스템 모델 자체의 불완전함이나 예측 불가능한 외부 요인으로 인해 발생하는 오차를 프로세스 노이즈라고 한다. 이 노이즈는 평균이 0인 가우시안 분포를 따른다고 가정하며, 그 공분산 행렬을 $Q$로 표기한다.6

    $Q$가 크다는 것은 우리의 시스템 모델을 별로 신뢰하지 않는다는 의미다.

  2. 측정 노이즈 (Measurement Noise, $v$): 센서는 완벽하지 않다. GPS는 대기 상태에 따라 오차를 내고, 레이더는 신호 반사 과정에서 노이즈가 발생한다.6 이처럼 센서 측정 과정에서 발생하는 오차를 측정 노이즈라고 한다. 이 노이즈 역시 평균이 0인 가우시안 분포를 따른다고 가정하며, 그 공분산 행렬을 $R$로 표기한다.19

    $R$이 크다는 것은 센서 측정값을 별로 신뢰하지 않는다는 의미다.

graph TD
    subgraph "시스템 동역학 (이상적 모델)"
        X_km1(실제 상태<br>x<sub>k-1</sub>)
        F_model["상태 전이 모델<br><b>x<sub>k</sub> = Fx<sub>k-1</sub></b>"]
        X_k_ideal(이상적인 다음 상태)
        
        X_km1 --> F_model --> X_k_ideal
    end

    subgraph "현실 세계"
        Q_noise["<b>프로세스 노이즈 (w)</b><br><i>Process Noise</i><br>모델의 불완전성, 외부 교란<br>공분산: <b>Q</b>"]
        X_k_real(실제 다음 상태<br>x<sub>k</sub>)
        H_model["관측 모델<br><b>z<sub>k</sub> = Hx<sub>k</sub></b>"]
        Z_k_ideal(이상적인 측정값)
        R_noise("측정 노이즈 공분산<br><b>R<b>")
        Z_k_meas(실제 측정값<br>z<sub>k</sub>)

        X_k_ideal -- "현실의 불확실성" --> X_k_real
        Q_noise -.-> X_k_real
        
        X_k_real --> H_model --> Z_k_ideal
        Z_k_ideal -- "센서의 불확실성" --> Z_k_meas
        R_noise -.-> Z_k_meas
    end
    
    linkStyle 1,4 stroke-width:2px,stroke:blue,stroke-dasharray: 5 5;
    linkStyle 2,5 stroke-width:2px,stroke:red,stroke-dasharray: 5 5;

이 예측-갱신 사이클은 사실 베이즈 정리(Bayes’ Theorem)의 재귀적 적용과 같다.5

예측 단계는 이전의 믿음(사후 확률)을 시스템 모델에 통과시켜 현재의 믿음(사전 확률, $P(H)$)을 만들어내는 과정이다. 갱신 단계는 이 사전 확률에 새로운 증거(측정값)의 가능도(likelihood, $P(E H)$)를 결합하여 더 정제된 현재의 믿음(사후 확률, $P(H E)$)을 계산하는 과정이다. 즉, 칼만 필터는 임의의 수식 집합이 아니라, 선형 시스템과 가우시안 노이즈라는 가정 하에서 베이즈 추론 문제를 푸는 최적의 해법인 것이다.

이 과정에서 ‘혁신(innovation)’은 필터가 세상을 배우는 창구 역할을 한다. 혁신, 즉 예측과 측정의 차이는 모델이 예측하지 못한 ‘새로운 정보’를 의미한다. 혁신이 0에 가깝다면, 현실이 모델의 예측대로 움직였다는 뜻이므로 배울 것이 별로 없다. 혁신이 크다면, 모델이 현실을 제대로 예측하지 못했다는 신호이며, 필터는 이 차이를 통해 자신의 상태 추정치를 수정하며 ‘학습’한다. 칼만 이득은 이 학습의 강도를 조절하는 역할을 하며, 예측과 측정의 불확실성을 비교하여 혁신을 얼마나 신뢰할지 동적으로 결정한다.

칼만 필터의 방정식을 제대로 이해하려면, 그 바탕에 깔린 수학적 원리를 먼저 알아야 한다. 복잡해 보일 수 있지만, 핵심은 가우시안 분포의 두 가지 강력한 성질에 있다. 칼만 필터가 선형 시스템에서 최적의 성능을 보이는 이유는 바로 이 성질들 덕분이다.3

칼만 필터가 시스템의 상태와 노이즈가 모두 가우시안 분포를 따른다고 가정하는 데에는 중요한 이유가 있다.3

  1. 단순성: 가우시안 분포는 오직 두 개의 매개변수, 즉 평균 벡터 $\mu$와 공분산 행렬 $\Sigma$만으로 완벽하게 기술된다.5 이는 복잡한 확률 분포를 다루는 대신, 평균과 공분산만 추적하면 된다는 의미이므로 계산이 매우 효율적이다.
  2. 닫힘 속성 (Closure Property): 가우시안 분포의 가장 중요한 특징은 ‘닫혀있다’는 것이다. 가우시안 분포를 따르는 확률 변수에 선형 변환을 가해도 그 결과는 여전히 가우시안 분포를 따른다. 또한, 두 개의 가우시안 분포를 결합(합성곱 또는 곱)해도 그 결과는 또 다른 가우시안 분포가 된다.3 이 ‘닫힘’ 속성 덕분에 칼만 필터는 예측과 갱신 단계를 무한히 반복해도 항상 가우시안 분포라는 일관된 형태로 시스템의 상태를 표현할 수 있다. 만약 이 속성이 없다면, 매 단계를 거칠 때마다 확률 분포의 형태가 점점 더 복잡해져 결국 계산이 불가능해질 것이다.

상태가 여러 변수(예: 위치와 속도)로 구성된 다차원 시스템에서, 공분산 행렬 $P$는 불확실성을 입체적으로 표현한다. \(P = \begin{bmatrix} P_{00} & P_{01} & P_{02} \\ P_{10} & P_{11} & P_{12} \\ P_{20} & P_{21} & P_{22} \\ \end{bmatrix}\)

예를 들어, 자동차의 위치와 속도를 추정하는 경우를 생각해 보자. 만약 자동차가 빠르게 움직이고 있다는 강한 믿음이 있다면, ‘높은 위치’ 추정치와 ‘높은 속도’ 추정치는 서로 강한 양의 상관관계를 가질 것이다. 이 관계가 공분산 행렬의 비대각 원소에 인코딩되며, 시각적으로는 기울어진 타원 형태로 나타난다.5 칼만 필터는 이 상관관계까지 고려하여 추정을 수행한다.

칼만 필터의 예측과 갱신 단계는 각각 가우시안 분포에 대한 두 가지 다른 연산으로 수학적으로 모델링된다. 이 두 연산을 이해하면 칼만 필터의 작동 방식이 명확해진다.21

예측 단계는 “현재 상태에 대한 믿음”에 “움직임에 대한 믿음”을 더하는 과정이다. 확률 분포의 덧셈은 합성곱 연산으로 정의된다.

두 가우시안 분포의 합성곱 결과는 놀랍게도 또 다른 가우시안 분포이며, 그 평균과 분산은 원래 두 분포의 평균과 분산을 단순히 더한 것과 같다.3 \(N(\mu_{k-1}, \sigma^2_{k-1}) * N(\mu_{motion}, \sigma^2_Q) = N(\mu_{k-1} + \mu_{motion}, \sigma^2_{k-1} + \sigma^2_Q)\) 여기서 가장 중요한 점은 예측 단계에서 불확실성(분산)이 항상 증가한다는 것이다 ($\sigma^2{k-1} + \sigma^2_Q > \sigma^2{k-1}$). 이는 매우 직관적이다. 미래를 예측하는 행위는 본질적으로 불확실성을 더하는 과정이기 때문이다. 시간이 지날수록 우리의 예측은 점점 더 불확실해진다.21

graph LR
    subgraph "입력"
        A["<b>이전 믿음 (k-1)</b><br><br>N(μ<sub>k-1</sub>, σ²<sub>k-1</sub>)<br><br>  ^<br> / \\<br>/___\\<br><i>(상대적으로 좁은 분포)</i>"]
        B["<b>움직임/프로세스 노이즈</b><br><br>N(μ<sub>motion</sub>, σ²<sub>Q</sub>)"]
    end

    subgraph "연산"
        C{"<b>예측<br>(합성곱)</b>"}
    end

    subgraph "출력"
        D["<b>예측된 믿음 (사전 추정치, k)</b><br><br>N(μ<sub>k-1</sub>+μ<sub>motion</sub>, σ²<sub>k-1</sub>+σ²<sub>Q</sub>)<br><br>   ^<br>  /   \\<br> /_____\\<br><i>(더 넓어진 분포 = <b>불확실성 증가</b>)</i>"]
    end

    A -- " \+ " --> C
    B -- " " --> C
    C --> D

갱신 단계는 “예측된 상태에 대한 믿음(사전 확률)”과 “측정된 값에 대한 믿음(가능도)”을 결합하는 과정이다. 베이즈 정리에 따르면, 사후 확률은 사전 확률과 가능도의 곱에 비례한다. 따라서 이 결합 과정은 두 확률 밀도 함수의 으로 계산된다.

두 가우시안 분포의 곱 역시 놀랍게도 또 다른 가우시안 분포가 된다. 그 새로운 평균 $\mu_{new}$와 분산 $\sigma^2{new}$는 다음과 같이 계산된다.21 \(\mu_{new} = \frac{\sigma^2_{meas}\mu_{prior} + \sigma^2_{prior}\mu_{meas}}{\sigma^2_{prior} + \sigma^2_{meas}} \\ \sigma^2_{new} = \frac{\sigma^2_{prior}\sigma^2_{meas}}{\sigma^2_{prior} + \sigma^2_{meas}} \quad \text{또는} \quad \frac{1}{\sigma^2_{new}} = \frac{1}{\sigma^2_{prior}} + \frac{1}{\sigma^2_{meas}}\) 여기서 가장 중요한 점은 갱신 단계에서 불확실성(분산)이 항상 감소한다는 것이다 ($\sigma^2{new} < \sigma^2{prior}$ 이고 $\sigma^2{new} < \sigma^2_{meas}$). 두 개의 불확실한 정보를 융합하면, 각각의 정보보다 더 확실한 새로운 정보를 얻게 된다. 이는 우리의 직관과 완벽하게 일치한다.21

graph LR
    subgraph "입력"
        A["<b>예측된 믿음 (사전)</b><br><br>N(μ<sub>prior</sub>, σ²<sub>prior</sub>)<br><br>   ^<br>  /   \\<br> /_____\\<br><i>(넓은 분포)</i>"]
        B["<b>측정값의 믿음 (가능도)</b><br><br>N(μ<sub>meas</sub>, σ²<sub>meas</sub>)<br><br>     ^<br>    /   \\<br>   /_____\\<br><i>(넓은 분포)</i>"]
    end

    subgraph "연산"
        C{"<b>갱신<br>(곱)</b>"}
    end

    subgraph "출력"
        D["<b>갱신된 믿음 (사후 추정치)</b><br><br>N(μ<sub>new</sub>, σ²<sub>new</sub>)<br><br>^<br>/\\<br>/__\\<br><i>(더 좁아진 분포 = <b>불확실성 감소</b>)</i>"]
    end

    A -- " × " --> C
    B -- " " --> C
    C --> D

이처럼 가우시안 분포의 수학적 특성은 칼만 필터의 직관적인 원리를 완벽하게 뒷받침한다. 예측을 통해 불확실성이 커지고, 갱신을 통해 불확실성이 줄어드는 과정의 반복. 이것이 바로 칼만 필터가 불확실성 속에서 최적의 추정치를 찾아가는 여정의 수학적 표현이다. 하지만 이 우아한 해법은 가우시안과 선형성이라는 두 가지 가정에 깊이 의존하고 있다. 이 가정이 깨지는 순간, 칼만 필터의 최적성은 보장되지 않으며, 이것이 바로 확장 칼만 필터(EKF)나 무향 칼만 필터(UKF)와 같은 더 복잡한 필터들이 필요한 이유가 된다.

이제 칼만 필터의 심장부로 들어가, 알고리즘을 구성하는 5개의 핵심 방정식을 해부해 보자. 이 방정식들은 앞서 설명한 예측과 갱신이라는 두 단계를 수학적으로 구현한 것이다. 방정식을 이해하기 위해 먼저 시스템을 어떻게 수학적으로 표현하는지부터 정의해야 한다.

칼만 필터는 시스템을 상태 공간 모델이라는 표준적인 형식으로 기술한다. 이 모델은 두 개의 선형 방정식으로 구성된다.2

  1. 상태 방정식 (State Equation): 시스템의 상태가 시간이 지남에 따라 어떻게 변하는지를 설명한다. \(x_k = F_k x_{k-1} + B_k u_k + w_{k-1}\)

    • $x_k$ : 시간 $k$에서의 상태 벡터.
    • $x_{k-1}$ : 시간 $k-1$에서의 상태 벡터.
    • $F_k$ : 상태 전이 행렬(State Transition Matrix). 이전 상태가 현재 상태에 어떻게 영향을 미치는지를 나타낸다. 예를 들어, 등속도 모델에서는 위치와 속도를 업데이트하는 역할을 한다.
    • $B_k$ : 제어 입력 행렬(Control-Input Matrix). 외부 제어 입력이 상태에 어떤 영향을 미치는지를 나타낸다.
    • $u_k$ : 제어 벡터(Control Vector). 시스템에 가해지는 외부 입력(예: 자동차의 가속, 로봇 팔의 모터 전압)이다. 많은 경우 이 항은 없다.
    • $w_{k-1}$ : 프로세스 노이즈(Process Noise). 모델의 불확실성을 나타내며, 평균이 0이고 공분산이 $Q_k$인 가우시안 분포 $N(0, Q_k)$를 따른다고 가정한다.
  2. 측정 방정식 (Measurement Equation): 시스템의 상태와 센서 측정값 사이의 관계를 설명한다. \(z_k = H_k x_k + v_k\)

    • $z_k$ : 시간 $k$에서의 측정 벡터(Measurement Vector). 센서로부터 받은 실제 측정값이다.
    • $H_k$ : 관측 행렬(Observation Matrix). 상태 벡터를 측정 벡터로 변환하는 역할을 한다. 예를 들어, 상태 벡터는 위치와 속도를 모두 포함하지만 센서는 위치만 측정할 경우, $H_k$는 상태 벡터에서 위치 성분만 “추출”하는 역할을 한다.
    • $v_k$ : 측정 노이즈(Measurement Noise). 센서의 불확실성을 나타내며, 평균이 0이고 공분산이 $R_k$인 가우시안 분포 $N(0, R_k)$를 따른다고 가정한다.

이 상태 공간 모델을 바탕으로, 칼만 필터는 다음 5개의 방정식을 재귀적으로 계산한다.11

1. 상태 추정치 예측 (사전 추정치): \(\hat{x}_{k|k-1} = F_k \hat{x}_{k-1|k-1} + B_k u_k\) 이 방정식은 이전 시간 단계의 최종 추정치($\hat{x}_{k-1|k-1}$)를 사용하여 현재 시간 단계의 상태를 예측한다. 상태 전이 행렬 $F_k$를 곱하여 시스템의 동역학을 반영하고, 제어 입력 $u_k$의 효과를 더한다.

2. 오차 공분산 예측 (사전 추정치): \(P_{k|k-1} = F_k P_{k-1|k-1} F_k^T + Q_k\) 이 방정식은 추정치의 불확실성이 어떻게 변하는지를 예측한다. 이전 단계의 오차 공분산 $P_{k-1|k-1}$이 상태 전이 행렬 $F_k$를 통해 어떻게 전파되는지 계산하고($F_k P_{k-1|k-1} F_k^T$), 여기에 프로세스 노이즈의 불확실성 $Q_k$를 더한다. 이 과정에서 불확실성은 항상 증가하거나 유지된다.

3. 칼만 이득 계산: \(K_k = P_{k|k-1} H_k^T (H_k P_{k|k-1} H_k^T + R_k)^{-1}\) 칼만 이득 $K_k$는 칼만 필터의 ‘뇌’와 같다. 이 값은 예측된 상태와 실제 측정값 중 어느 쪽을 더 신뢰할지를 결정하는 가중치 역할을 한다.

4. 상태 추정치 갱신 (사후 추정치): \(\hat{x}_{k|k} = \hat{x}_{k|k-1} + K_k (z_k - H_k \hat{x}_{k|k-1})\) 이 방정식은 실제 측정값 $z_k$를 사용하여 사전 추정치 $\hat{x}{k|k-1}$를 보정한다. 괄호 안의 $z_k - H_k \hat{x}{k|k-1}$ 항이 바로 혁신(innovation)이다. 즉, (실제 측정값) - (예측된 측정값)의 차이다. 이 혁신에 칼만 이득 $K_k$를 곱한 만큼 사전 추정치를 보정하여 최종 사후 추정치 $\hat{x}_{k|k}$를 얻는다.

5. 오차 공분산 갱신 (사후 추정치): \(P_{k|k} = (I - K_k H_k) P_{k|k-1}\) 마지막으로, 새로운 측정값을 반영하여 불확실성을 업데이트한다. 칼만 이득 $K_k$를 사용했기 때문에, 갱신된 오차 공분산 $P_{k|k}$는 예측된 공분산 $P_{k|k-1}$보다 항상 작아진다. 즉, 측정값을 통해 정보를 얻었으므로 불확실성이 감소하는 것이다.

이 5개의 방정식이 한 사이클을 이루며, 새로운 측정값이 들어올 때마다 반복적으로 실행되어 시스템의 상태를 지속적으로 추적하고 추정한다.

graph TD
    %% Inputs
    X_prev[("<b>x̂<sub>k-1|k-1</sub></b><br>이전 사후 상태")]
    P_prev[("<b>P<sub>k-1|k-1</sub></b><br>이전 사후 공분산")]
    Z_curr[("<b>z<sub>k</sub></b><br>현재 측정값")]
    U_curr[("<b>u<sub>k</sub></b><br>현재 제어입력")]
    
    subgraph "예측 단계 (Time Update)"
        direction LR
        %% Equation 1
        X_pred_calc
        X_prev --> X_pred_calc
        U_curr --> X_pred_calc
        X_pred_calc --> X_pred_out[("<b>x̂<sub>k|k-1</sub></b><br>사전 상태")]

        %% Equation 2
        P_pred_calc
        P_prev --> P_pred_calc
        P_pred_calc --> P_pred_out[("<b>P<sub>k|k-1</sub></b><br>사전 공분산")]
    end

    subgraph "갱신 단계 (Measurement Update)"
        direction LR
        %% Equation 3
        K_calc
        P_pred_out --> K_calc
        K_calc --> K_out[("<b>K<sub>k</sub></b><br>칼만 이득")]

        %% Equation 4
        X_upd_calc["<b>4. 상태 갱신</b><br>x̂<sub>k|k</sub> = x̂<sub>k|k-1</sub> + K<sub>k</sub>(z<sub>k</sub>-Hx̂<sub>k|k-1</sub>)"]
        X_pred_out --> X_upd_calc
        K_out --> X_upd_calc
        Z_curr --> X_upd_calc
        X_upd_calc --> X_upd_out[("<b>x̂<sub>k|k</sub></b><br>사후 상태")]

        %% Equation 5
        P_upd_calc["<b>5. 공분산 갱신</b><br>P<sub>k|k</sub> = (I - K<sub>k</sub>H)P<sub>k|k-1</sub>"]
        P_pred_out --> P_upd_calc
        K_out --> P_upd_calc
        P_upd_calc --> P_upd_out[("<b>P<sub>k|k</sub></b><br>사후 공분산")]
    end

    %% Loop back for recursion
    X_upd_out -.-> X_prev
    P_upd_out -.-> P_prev

칼만 필터 관련 자료들은 표기법이 조금씩 다를 수 있어 혼란을 유발할 수 있다. 다음 표는 이 자습서에서 사용하는 주요 변수와 행렬을 정리한 것이다.14

기호 이름 다른 이름 차원  
$x$ 상태 벡터 상태 $n_x \times 1$  
$\hat{x}_{k k-1}$ 사전 상태 추정치 예측된 상태 $n_x \times 1$
$\hat{x}_{k k}$ 사후 상태 추정치 갱신된 상태, 필터링된 상태 $n_x \times 1$
$P$ 오차 공분산 행렬 상태 공분산, 추정 공분산 $n_x \times n_x$  
$F$ 상태 전이 행렬 시스템 행렬, 동역학 행렬, $\Phi, A$ $n_x \times n_x$  
$B$ 제어 입력 행렬 입력 행렬 $n_x \times n_u$  
$u$ 제어 벡터 입력 벡터 $n_u \times 1$  
$Q$ 프로세스 노이즈 공분산 시스템 노이즈 공분산 $n_x \times n_x$  
$z$ 측정 벡터 관측 벡터, $y$ $n_z \times 1$  
$H$ 관측 행렬 측정 행렬, $C$ $n_z \times n_x$  
$R$ 측정 노이즈 공분산 관측 노이즈 공분산 $n_z \times n_z$  
$K$ 칼만 이득 칼만 게인, 가중치 행렬 $n_x \times n_z$  
$I$ 단위 행렬 - -  
$n_x, n_u, n_z$ 상태, 입력, 측정 벡터의 차원 - -  

추상적인 방정식만으로는 감을 잡기 어렵다. 이제 간단한 1차원 예제를 통해 5개의 방정식이 실제로 어떻게 작동하는지 단계별로 따라가 보자.23

직선 철로 위를 대략 일정한 속도로 움직이는 기차가 있다고 가정하자. 우리는 이 기차의 정확한 위치와 속도를 알고 싶지만, 가지고 있는 센서는 노이즈가 섞인 위치 정보만 제공한다.

  1. 상태 벡터 ($x$): 기차의 상태는 위치($p$)와 속도($v$)로 정의한다. \(x = \begin{bmatrix} p \\ v \end{bmatrix}\) 상태 전이 행렬 ($F$): 기본 물리 법칙에 따라 다음 상태를 모델링한다. 시간 간격을 $\Delta t$라고 할 때,

    • 새로운 위치 = 이전 위치 + (이전 속도 $\times \Delta t$)

    • 새로운 속도 = 이전 속도 (등속도 가정이므로)

      이를 행렬로 표현하면 다음과 같다.

    \[F = \begin{bmatrix} 1 & \Delta t \\ 0 & 1 \end{bmatrix}\]

    관측 행렬 ($H$): 센서는 위치만 측정하므로, 상태 벡터에서 위치 성분만 골라내는 역할을 한다. \(H = \begin{bmatrix} 1 & 0 \end{bmatrix}\) 프로세스 노이즈 공분산 ($Q$): 기차가 완벽한 등속도 운동을 하지 않을 수 있다(미세한 가감속). 이 불확실성을 모델링하기 위해 작은 프로세스 노이즈를 추가한다. 여기서는 간단한 값을 가정한다. \(Q = \begin{bmatrix} 0.0001 & 0 \\ 0 & 0.0001 \end{bmatrix}\) 측정 노이즈 공분산 ($R$): 위치 센서의 노이즈 분산을 나타낸다. 센서의 표준편차가 1m라고 가정하면, 분산은 $1^2 = 1$이다. 측정값은 스칼라이므로 $R$도 스칼라다. \(R = [1]\)

시간 간격 $\Delta t = 1$초라고 가정하고 계산을 시작해 보자.

필터를 시작하기 위해 초기 상태와 불확실성을 가정해야 한다. 보통 초기값은 불확실하므로, 공분산 $P$를 큰 값으로 설정하여 필터가 초기 측정값에 더 큰 가중치를 두도록 한다.4

1. 예측 (Time Update)

2. 갱신 (Measurement Update)

이제 첫 번째 측정값이 들어왔다고 가정하자. $z_1 = 0.9$m.

이제 갱신된 $\hat{x}_{1 1}$과 $P_{1 1}$을 가지고 두 번째 사이클을 시작한다.

1. 예측 (Time Update)

2. 갱신 (Measurement Update)

두 번째 측정값이 들어왔다고 가정하자. $z_2 = 1.5$m.

이전과 동일한 방식으로 칼만 이득 $K_2$를 계산하고, $\hat{x}_{2 1}$과 $P_{2 1}$을 갱신하여 $\hat{x}_{2 2}$와 $P_{2 2}$를 얻는다.

이 간단한 예제는 몇 가지 중요한 사실을 보여준다.

이제 더 현실적인 2차원(2D) 객체 추적 문제를 Python 코드로 직접 구현해 보자. 이 예제를 통해 이론이 실제 코드로 어떻게 변환되는지 명확하게 이해할 수 있을 것이다. numpy 라이브러리를 사용하여 행렬 연산을 수행하고, matplotlib으로 결과를 시각화할 것이다.27

2차원 평면 위를 움직이는 물체(예: 드론, 자동차)를 추적하는 시나리오를 가정한다. 물체는 대략 일정한 속도로 움직이지만 약간의 무작위적인 가속이 있을 수 있다. 센서는 노이즈가 포함된 물체의 $(x, y)$ 위치 좌표를 주기적으로 제공한다.

  1. 상태 벡터 ($x$): 2D 위치($p_x, p_y$)와 2D 속도($v_x, v_y$)를 포함한다. \(x = \begin{bmatrix} p_x \\ p_y \\ v_x \\ v_y \end{bmatrix}\) 상태 전이 행렬 ($F$): 1D 예제와 동일한 등속도 운동 모델을 각 축에 독립적으로 적용한다. \(F = \begin{bmatrix} 1 & 0 & \Delta t & 0 \\ 0 & 1 & 0 & \Delta t \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} $\) 이 행렬의 구조는 물리 법칙을 직접적으로 반영한다. 첫 번째 행은 $p_{x, k} = p_{x, k-1} + v_{x, k-1} \cdot \Delta t$를, 두 번째 행은 $p_{y, k} = p_{y, k-1} + v_{y, k-1} \cdot \Delta t$를 나타낸다.

  2. 관측 행렬 ($H$): 센서가 $(x, y)$ 위치만 측정하므로, 4차원 상태 벡터에서 두 개의 위치 성분만 선택한다. \(H = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \end{bmatrix}\) 프로세스 노이즈 공분산 ($Q$): 물체의 움직임이 완벽한 등속도가 아니라는 사실을 모델링한다. 짧은 시간 동안의 무작위 가속이 위치와 속도에 미치는 영향을 공분산 행렬로 표현한다. 이 행렬은 물리 모델로부터 유도될 수 있으며, 가속도의 분산 $\sigma_a^2$에 의존한다.27 \(Q = \begin{bmatrix} \frac{\Delta t^4}{4} & 0 & \frac{\Delta t^3}{2} & 0 \\ 0 & \frac{\Delta t^4}{4} & 0 & \frac{\Delta t^3}{2} \\ \frac{\Delta t^3}{2} & 0 & \Delta t^2 & 0 \\ 0 & \frac{\Delta t^3}{2} & 0 & \Delta t^2 \end{bmatrix} \sigma_a^2\) 측정 노이즈 공분산 ($R$): $x$축과 $y$축의 측정 노이즈가 독립적이라고 가정하고, 각각의 분산을 $\sigma_x^2$와 $\sigma_y^2$라고 하면 다음과 같다. \(R = \begin{bmatrix} \sigma_x^2 & 0 \\ 0 & \sigma_y^2 \end{bmatrix}\)

구현의 핵심은 앞서 배운 5개의 방정식을 코드로 그대로 옮기는 것이다. 각 행렬 연산은 numpy@ 연산자(행렬 곱) 또는 np.dot() 함수를 사용하여 간결하게 표현할 수 있다. 코드는 KalmanFilter 클래스로 구조화하여 재사용성을 높인다.27

import numpy as np

class KalmanFilter2D:
    def __init__(self, dt, std_acc, std_meas_x, std_meas_y):
        # 시간 간격
        self.dt = dt

        # 상태 전이 행렬 F (Constant Velocity Model)
        self.F = np.array([[1, 0, self.dt, 0],
                           [0, 1, 0, self.dt],
                           [0, 0, 1, 0],      # 3번째 행 추가
                           [0, 0, 0, 1]])     # 4번째 행 추가

    	# 관측 행렬 H
		self.H = np.array([[1, 0, 0, 0],  # 1번째 행 추가
        		           [0, 1, 0, 0]]) # 2번째 행 추가

        # 프로세스 노이즈 공분산 Q
        # 가속도의 불확실성을 모델링
        self.q_val = std_acc**2
        self.Q = self.q_val * np.array([[(self.dt**4)/4, 0, (self.dt**3)/2, 0],
                                        [0, (self.dt**4)/4, 0, (self.dt**3)/2],
                                        [(self.dt**3)/2, 0, self.dt**2, 0],
                                        [0, (self.dt**3)/2, 0, self.dt**2]])

        # 측정 노이즈 공분산 R
        self.R = np.array([[std_meas_x**2, 0],
                           [0, std_meas_y**2]])

        # 초기 상태 벡터 [px, py, vx, vy]
        self.x = np.zeros((4, 1))
        
        # 초기 오차 공분산 P
        self.P = np.eye(4) * 1000  # 큰 값으로 초기화하여 불확실성을 표현

    def predict(self):
        # 1. 상태 예측 (a priori)
        # x_k|k-1 = F * x_k-1|k-1
        self.x = self.F @ self.x
        
        # 2. 오차 공분산 예측 (a priori)
        # P_k|k-1 = F * P_k-1|k-1 * F^T + Q
        self.P = self.F @ self.P @ self.F.T + self.Q
        
        return self.x

    def update(self, z):
        # z: 측정값 [px, py]
        z = np.array(z).reshape(2, 1)

        # 3. 칼만 이득 계산
        # S = H * P_k|k-1 * H^T + R
        S = self.H @ self.P @ self.H.T + self.R
        # K_k = P_k|k-1 * H^T * S^-1
        K = self.P @ self.H.T @ np.linalg.inv(S)

        # 4. 상태 갱신 (a posteriori)
        # x_k|k = x_k|k-1 + K * (z - H * x_k|k-1)
        self.x = self.x + K @ (z - self.H @ self.x)

        # 5. 오차 공분산 갱신 (a posteriori)
        # P_k|k = (I - K * H) * P_k|k-1
        I = np.eye(4)
        self.P = (I - K @ self.H) @ self.P

이제 이 클래스를 사용하여 가상의 물체를 추적하고, 그 결과를 시각화해 보자.

import matplotlib.pyplot as plt

# 시뮬레이션 설정
dt = 0.1
total_time = 10
steps = int(total_time / dt)

# 실제 물체 궤적 생성 (예: 등속도 운동)
true_x = np.linspace(0, 10, steps)
true_y = np.linspace(0, 5, steps)
true_states = np.vstack((true_x, true_y))

# 측정값 생성 (실제 궤적 + 노이즈)
std_meas_x = 0.5
std_meas_y = 0.5
measurements = np.vstack((
    true_x + np.random.randn(steps) * std_meas_x,
    true_y + np.random.randn(steps) * std_meas_y
))

# 칼만 필터 생성 및 실행
std_acc = 0.2 # 프로세스 노이즈 표준편차 (튜닝 파라미터)
kf = KalmanFilter2D(dt, std_acc, std_meas_x, std_meas_y)

estimated_states = [] # 빈 리스트로 초기화
for i in range(steps):
    kf.predict()
    kf.update(measurements[:, i])
    estimated_states.append(kf.x.flatten())

estimated_states = np.array(estimated_states)

# 결과 시각화
plt.figure(figsize=(12, 8))
plt.plot(true_states[0, :], true_states[1, :], 'g-', label='True Trajectory')
plt.plot(measurements[0, :], measurements[1, :], 'rx', label='Measurements')
plt.plot(estimated_states[:, 0], estimated_states[:, 1], 'b-', label='Kalman Filter Estimate')
plt.title('2D Object Tracking with Kalman Filter')
plt.xlabel('X Position')
plt.ylabel('Y Position')
plt.legend()
plt.grid(True)
plt.axis('equal')
plt.show()

이 코드를 실행하면, 노이즈가 심한 붉은색 ‘x’ 표시(측정값)들 사이로, 칼만 필터가 추정한 파란색 궤적이 실제 녹색 궤적을 부드럽게 따라가는 것을 확인할 수 있다. 이는 칼만 필터가 어떻게 노이즈를 효과적으로 걸러내고 시스템의 동역학 모델을 활용하여 더 정확한 추정치를 생성하는지를 시각적으로 보여준다. 이 코드는 칼만 필터의 5가지 핵심 방정식이 어떻게 실제 문제 해결에 직접적으로 적용되는지를 명확히 보여주는 사례이다.

칼만 필터를 실제 문제에 적용할 때 가장 어렵고 중요한 과정은 바로 프로세스 노이즈 공분산($Q$)과 측정 노이즈 공분산($R$) 행렬을 결정하는 것이다. 이 두 행렬을 어떻게 설정하느냐에 따라 필터의 성능이 극적으로 달라지기 때문에, 이를 ‘튜닝(tuning)’이라고 부른다. 튜닝은 때로는 과학적 분석에 기반하지만, 때로는 경험과 직관이 필요한 예술의 영역이기도 하다.32

필터의 동작을 지배하는 것은 $Q$와 $R$의 절대적인 크기보다는 그 둘 사이의 비율이다.35 이 비율은 칼만 이득($K$)의 크기를 결정하며, 필터가 모델 예측과 센서 측정 중 어느 쪽을 더 신뢰할지를 조절한다.

graph TD
    subgraph "Q >> R : 모델 불신, 측정 신뢰"
        direction TB
        A1
        A2{"칼만 이득 (K)가 커짐"}
        A3["필터가 측정값(z)을 더 많이 신뢰"]
        A4["<b>결과:</b> 측정값의 노이즈까지 따라가<br>추정치가 거칠고 불안정함"]
        A5["<b>장점:</b> 응답성이 빠름 (상태 급변에 잘 추종)<br><b>단점:</b> 노이즈 제거 성능 저하"]
        A1 --> A2 --> A3 --> A4 --> A5
    end

    subgraph "R >> Q : 모델 신뢰, 측정 불신"
        direction TB
        B1
        B2{"칼만 이득 (K)가 작아짐"}
        B3["필터가 모델 예측(Fx)을 더 많이 신뢰"]
        B4["<b>결과:</b> 측정값의 노이즈를 무시하여<br>추정치가 매우 부드러움"]
        B5["<b>장점:</b> 노이즈 제거 성능 탁월<br><b>단점:</b> 응답성이 느림 (상태 급변 시 지연 발생)"]
        B1 --> B2 --> B3 --> B4 --> B5
    end

$R$ 행렬은 비교적 튜닝하기 쉽다. 이는 센서의 물리적 특성과 직접적으로 관련이 있기 때문이다.

$R$과 달리 $Q$는 튜닝하기가 훨씬 까다롭다. $Q$는 눈에 보이지 않는 ‘모델의 불확실성’을 나타내기 때문이다.32 실제로 $Q$는 종종 우리가 사용하는 시스템 모델이 현실을 얼마나 잘 반영하지 못하는지를 보상하는 ‘조절 손잡이(tuning knob)’ 역할을 한다.34

예를 들어, 우리는 자동차를 ‘등속도 모델’로 가정했지만 실제 자동차는 가속하고 회전한다. 이처럼 모델이 현실을 따라가지 못할 때 발생하는 오차를 $Q$가 흡수해주는 것이다. $Q$를 크게 설정하는 것은 필터에게 “내 모델은 단순해서 현실의 모든 움직임을 설명하지 못하니, 측정값이 모델과 크게 다르더라도 너무 놀라지 말고 유연하게 받아들여라”라고 말해주는 것과 같다.

체계적인 튜닝을 위해 다음 전략을 따를 수 있다.35

  1. R 고정: 먼저 센서 데이터시트나 실험을 통해 $R$ 값을 합리적으로 설정하고 고정한다.
  2. Q 초기화: $Q$를 매우 작은 값으로 설정하여 시작한다. 이는 모델을 매우 강하게 신뢰한다는 의미다.
  3. 시뮬레이션 및 평가: 실제 데이터나 시뮬레이션을 통해 필터를 실행한다. 만약 실제 참값(ground truth)을 알고 있다면, 추정치와 참값 사이의 오차(예: RMSE)를 계산하여 필터 성능을 정량적으로 평가한다.
  4. 혁신(Innovation) 분석: 필터 튜닝에서 가장 강력한 진단 도구는 혁신(innovation), 즉 잔차($z_k - H\hat{x}_{k k-1}$)를 분석하는 것이다. 만약 필터가 최적으로 튜닝되었다면, 혁신 시퀀스는 평균이 0이고 자기상관이 없는 백색 잡음(white noise)의 특성을 보여야 한다.
    • 혁신 시퀀스를 그래프로 그려본다. 만약 그래프에 특정 패턴이 보인다면(예: 물체가 회전할 때마다 혁신 값이 한쪽으로 치우친다면), 이는 필터가 시스템의 동역학을 제대로 따라가지 못하고 있다는 증거다. 이 경우, 모델을 더 불신해야 하므로 $Q$를 높여야 한다.
    • 혁신의 자기상관(autocorrelation)을 계산해 본다. 이상적으로는 지연(lag) 0을 제외하고 모든 지연에서 상관계수가 0에 가까워야 한다. 만약 다른 지연에서도 높은 상관관계가 나타난다면, 필터가 측정값에 담긴 정보를 제대로 추출하지 못하고 있다는 신호이며, 이 역시 $Q$를 높여야 할 필요성을 시사한다.
  5. 반복 및 최적화: $Q$ 값을 점진적으로 높여가면서 3, 4번 과정을 반복한다. 추정치가 실제 움직임을 지연 없이 잘 따라가면서도, 측정 노이즈에 너무 민감해지지 않는 최적의 균형점을 찾는다. 이 과정은 종종 여러 번의 시도와 조정을 필요로 한다.

결론적으로, $R$은 센서의 물리적 특성에 대한 우리의 지식을 반영하는 ‘과학’에 가깝고, $Q$는 모델의 한계를 인정하고 보상하는 ‘예술’에 가깝다. 이 둘의 균형을 잘 맞추는 것이 칼만 필터링 성공의 핵심 열쇠이다.

지금까지 다룬 표준 칼만 필터는 강력하지만 치명적인 한계를 가지고 있다. 바로 시스템이 선형(linear)이라고 가정한다는 점이다. 상태 전이와 관측 과정이 행렬 곱으로 표현되는 선형 관계여야만 한다. 하지만 로봇의 회전 운동, 레이더의 거리/각도 측정, 위성의 궤도 등 현실 세계의 많은 시스템은 본질적으로 비선형(non-linear)이다.3

비선형 시스템에 표준 칼만 필터를 적용하면 왜 문제가 될까? 핵심은 가우시안 분포의 성질에 있다. 선형 변환을 거친 가우시안 분포는 여전히 가우시안 분포를 유지하지만, 비선형 함수를 통과한 가우시안 분포는 더 이상 가우시안 분포가 아니게 된다. 모양이 왜곡되고 찌그러져 더 이상 평균과 공분산만으로는 분포를 제대로 표현할 수 없게 된다. 이렇게 칼만 필터의 기본 가정이 무너지면, 필터의 성능은 급격히 저하되고 심지어 발산(diverge)해버릴 수도 있다.38

이 문제를 해결하기 위해 여러 비선형 필터가 개발되었으며, 그중 가장 대표적인 두 가지가 확장 칼만 필터(EKF)와 무향 칼만 필터(UKF)이다.

EKF는 비선형 문제를 풀기 위한 가장 고전적이고 직관적인 접근법이다. 그 핵심 아이디어는 “비선형 함수를 국소적으로 선형 함수로 근사하자”는 것이다.39

UKF는 EKF와는 다른 철학에서 출발한다. “비선형 함수를 근사하는 대신, 확률 분포 자체를 더 잘 근사하자”는 것이다.41

graph LR
    subgraph "확장 칼만 필터 (EKF: Extended Kalman Filter)"
        direction LR
        A1["<b>접근법: 함수를 선형으로 근사</b>"]
        A2["비선형 함수 f(x)를<br>현재 추정치 지점에서<br>1차 테일러 급수로 전개 (접선)"]
        A3["<b>f(x) ≈ f(x̂) + J(x-x̂)</b><br>여기서 J는 자코비안 행렬"]
        A4["장점: 계산량 적음<br>단점: 비선형성이 강하면<br>근사 오차가 커져 발산 위험"]
        A1 --> A2 --> A3 --> A4
    end

    subgraph "무향 칼만 필터 (UKF: Unscented Kalman Filter)"
        direction LR
        B1["<b>접근법: 확률 분포를 근사</b>"]
        B2["가우시안 분포를 대표하는<br>소수의 시그마 포인트를 선택"]
        B3["이 포인트들을 실제 비선형 함수 f(x)에<br>직접 통과시킨 후,<br>결과 분포를 재구성"]
        B4["장점: EKF보다 정확함, 자코비안 불필요<br>단점: 계산량이 더 많음"]
        B1 --> B2 --> B3 --> B4
    end
특징 확장 칼만 필터 (EKF) 무향 칼만 필터 (UKF)
비선형성 접근법 비선형 함수를 선형으로 근사 (테일러 급수) 확률 분포를 시그마 포인트로 근사 (무향 변환)
정확도 1차 근사 정확도. 비선형성이 강하면 성능 저하. 3차 근사 정확도(가우시안 가정 하). 일반적으로 EKF보다 우수.
구현 복잡도 자코비안 행렬의 해석적 유도 및 구현이 필요. 자코비안 불필요. 무향 변환 알고리즘 구현 필요.
계산 비용 상대적으로 낮음. EKF보다 높음. 상태 차원에 따라 증가.
적합한 시스템 비선형성이 약하거나, 계산 자원이 매우 제한적인 경우. 비선형성이 강하거나, 높은 정확도가 요구되는 경우.

결론적으로, EKF와 UKF 사이의 선택은 공학적인 트레이드오프 문제이다. EKF는 “충분히 좋은” 성능을 더 적은 계산 비용으로 제공하는 경우가 많아 여전히 널리 쓰인다. 반면, UKF는 더 높은 정확성이 요구되고 추가적인 계산 비용을 감당할 수 있는 현대적인 시스템에서 강력한 대안으로 자리 잡고 있다. 이 선택은 결국 해결하고자 하는 문제의 특성과 사용 가능한 자원에 따라 달라진다.

칼만 필터는 이론적인 알고리즘을 넘어, 다양한 분야에서 현실 세계의 복잡한 문제들을 해결하는 데 핵심적인 역할을 수행하고 있다. 그 응용 분야는 광범위하며, 공통적으로 ‘시간에 따라 변하는 시스템의 상태를 불확실한 정보 속에서 추정한다’는 본질적인 문제를 다룬다.

칼만 필터가 가장 활발하게 사용되는 분야 중 하나는 단연 자율주행과 로보틱스다.2

graph TD
    subgraph "입력 센서 데이터"
        GPS
        IMU
        RADAR
    end

    subgraph "중앙 처리 장치"
        KF_FUSION{"<b>센서 퓨전<br>(EKF / UKF)</b>"}
    end

    subgraph "최종 출력"
        STATE["<b>통합된 최적 차량 상태</b><br>- 정확한 위치 (x, y)<br>- 속도 (vx, vy)<br>- 방향 (heading)"]
    end

    GPS -->|위치 정보| KF_FUSION
    IMU -->|움직임 정보| KF_FUSION
    RADAR -->|주변 환경 정보| KF_FUSION
    KF_FUSION -->|강건하고 신뢰도 높은 추정치| STATE

불확실성이 지배하는 금융 시장 역시 칼만 필터의 중요한 응용 분야다.3

컴퓨터 비전 분야에서도 칼만 필터는 움직이는 객체를 추적하는 데 널리 사용된다.2

이 모든 응용 사례들의 공통점은 명확하다. 바로 ‘예측 모델’과 ‘노이즈 섞인 측정’이라는 두 가지 불완전한 정보를 시간에 따라 융합한다는 것이다. 자동차의 물리 모델과 GPS 데이터, 경제 모델과 시장 데이터, 등속도 모델과 영상 속 객체 탐지 결과 등 문제의 형태는 다르지만, 모두 상태 공간 표현으로 모델링될 수 있다. 이는 칼만 필터가 특정 분야에 국한되지 않고, 동적 시스템 추정이라는 광범위한 문제 클래스를 해결할 수 있는 일반적이고 강력한 수학적 프레임워크임을 보여준다. 특히, 직접 측정할 수 없는 속도, 가속도, 변동성, 시장 체제와 같은 ‘숨겨진 상태’를 추론해내는 능력이야말로 칼만 필터가 다양한 분야에서 귀중한 통찰력을 제공하는 핵심적인 이유다.18

이 자습서를 통해 우리는 칼만 필터의 근본적인 직관에서부터 수학적 원리, 실제 구현, 그리고 비선형 시스템을 위한 확장에 이르기까지 깊이 있는 여정을 함께했다. 이제 칼만 필터의 핵심적인 의의를 정리하고, 그 한계와 미래를 조망하며 마무리하고자 한다.

EKF와 UKF가 비선형성 문제를 해결했지만, 여전히 풀지 못한 숙제가 남아있다. 바로 비가우시안(non-Gaussian) 불확실성이다. 예를 들어, 로봇이 복도를 따라가다가 갈림길을 만났을 때, 로봇의 위치에 대한 확률 분포는 왼쪽 길과 오른쪽 길에 각각 봉우리가 있는 이중 봉우리(bimodal) 형태가 될 수 있다. 이는 단일 가우시안 분포로는 절대 표현할 수 없다.

이러한 문제를 해결하기 위해 등장한 것이 파티클 필터(Particle Filter)이다.59

결국, 어떤 필터를 선택할 것인지는 해결하려는 문제의 특성에 따라 결정되는 계층 구조를 형성한다.

  1. 선형 & 가우시안 시스템: 칼만 필터(KF)가 최적이고 가장 효율적이다.
  2. 비선형 & 가우시안 시스템: 확장 칼만 필터(EKF)(비선형성이 약하거나 계산량이 중요할 때) 또는 무향 칼만 필터(UKF)(비선형성이 강하고 정확도가 중요할 때)를 사용한다.
  3. 비선형 & 비가우시안 시스템: 칼만 필터 계열은 부적합하다. 파티클 필터(PF)가 필요하다.
graph TD
    A{"시스템이<br>선형(Linear)<br>인가?"} --"Yes"--> B{"노이즈가<br>가우시안(Gaussian)<br>인가?"}
    A --"No"--> C{"노이즈가<br>가우시안(Gaussian)<br>인가?"}
    B --"Yes"--> KF(["<b>칼만 필터 (KF)</b><br>선형/가우시안 시스템의<br>최적 해법"])
    B --"No"--> PF_Note1["(일반적으로 선형 시스템은<br>가우시안 노이즈를 가정함)"]

    C --"Yes"--> EKF_UKF([<b>EKF / UKF</b><br>EKF: 비선형성이 약하거나 계산량이 중요할 때<br>UKF: 비선형성이 강하고 정확도가 중요할 때])
    C --"No"--> PF(["<b>파티클 필터 (PF)</b><br>비선형 & 비가우시안 시스템을 위한<br>강력하지만 계산량이 많은 해법"])
칼만 필터와 그 확장들은 단순히 신호 처리 기법 중 하나가 아니다. 그것들은 불확실한 세상에 대한 우리의 ‘믿음(belief)’, 즉 사후 확률 분포($p(x_k z_{1:k})$)를 어떻게 합리적으로 갱신해 나갈 것인가에 대한 수학적 프레임워크다. KF는 엄격한 가정 하에서 이 문제를 해석적으로 정확하게 풀고, EKF와 UKF는 비선형성을 다루기 위해 각기 다른 방식으로 근사해를 찾으며, PF는 가우시안 가정마저 버리고 수치적 근사를 통해 더 넓은 범위의 문제에 도전한다.

루돌프 칼만이 1960년에 제시한 이 우아한 아이디어는 반세기가 넘는 시간 동안 수많은 공학과 과학 분야의 발전을 이끌어온 근간이 되었다. 불확실성 속에서 최적의 판단을 내리는 것은 인공지능 시대의 핵심 과제이며, 그 중심에는 여전히 칼만 필터의 깊은 통찰이 자리 잡고 있다. 이 자습서가 그 강력한 도구를 이해하고 활용하는 데 튼튼한 발판이 되기를 바란다.

  1. alida.tistory.com, accessed July 29, 2025, https://alida.tistory.com/54#:~:text=%EC%B9%BC%EB%A7%8C%20%ED%95%84%ED%84%B0(Kalman%20filter)%EB%8A%94,%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8%ED%95%98%EB%8A%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84%20%EB%A7%90%ED%95%9C%EB%8B%A4.
  2. 칼만 필터 - 위키백과, 우리 모두의 백과사전, accessed July 29, 2025, https://ko.wikipedia.org/wiki/%EC%B9%BC%EB%A7%8C_%ED%95%84%ED%84%B0
  3. Kalman filter란? - 미래기술연구소, accessed July 29, 2025, https://onnons.tistory.com/131
  4. Kalman Filter For Dummies - Bilgin’s Blog, accessed July 29, 2025, http://bilgin.esme.org/BitsAndBytes/KalmanFilterforDummies
  5. 선형 칼만 필터의 원리 이해 - gaussian37 - JINSOL KIM, accessed July 29, 2025, https://gaussian37.github.io/ad-ose-lkf_basic/
  6. Kalman Filter Tutorial, accessed July 29, 2025, https://www.kalmanfilter.net/
  7. Examples - Kalman Filter Tutorial, accessed July 29, 2025, https://www.kalmanfilter.net/multiExamples.html
  8. 앙상블 칼만필터를 이용한 실시간 수공법 저류층 특성화, accessed July 29, 2025, https://static5.apub.kr/journalsite/sites/ksmer/2006-043-02/N0330430206/N0330430206.pdf
  9. Kalman Filter란 - 천릿길도 한 걸음부터 - 티스토리, accessed July 29, 2025, https://youngseong.tistory.com/242
  10. 칼만 필터 및 투자 예측: 동적 상태 공간 모델을 사용하여 투자 매개변수를 추정하고 업데이트하는 방법 - FasterCapital, accessed July 29, 2025, https://fastercapital.com/ko/content/%EC%B9%BC%EB%A7%8C-%ED%95%84%ED%84%B0-%EB%B0%8F-%ED%88%AC%EC%9E%90-%EC%98%88%EC%B8%A1–%EB%8F%99%EC%A0%81-%EC%83%81%ED%83%9C-%EA%B3%B5%EA%B0%84-%EB%AA%A8%EB%8D%B8%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%ED%88%AC%EC%9E%90-%EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98%EB%A5%BC-%EC%B6%94%EC%A0%95%ED%95%98%EA%B3%A0-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95.html
  11. Kalman Filter Tutorial Part I – Theory and Practice - IMA, accessed July 29, 2025, https://cdn.ima.org.uk/wp/wp-content/uploads/2024/09/Kalman-Filter-Tutorial-Part-1_Mathematics-Today_2016.pdf
  12. Tutorial: The Kalman Filter - MIT, accessed July 29, 2025, https://web.mit.edu/kirtley/kirtley/binlustuff/literature/control/Kalman%20filter.pdf
  13. [SLAM] 칼만 필터(Kalman Filter)란? - Jbground - 티스토리, accessed July 29, 2025, https://jbground.tistory.com/82
  14. Kalman Filter Equations - Summary, accessed July 29, 2025, https://www.kalmanfilter.net/multiSummary.html
  15. Lecture 21: Motion and tracking - UT Computer Science, accessed July 29, 2025, https://www.cs.utexas.edu/~grauman/courses/378/slides/lecture21_full.pdf
  16. Derivation of the Kalman Filter by Using the Recursive Least-Squares Method, accessed July 29, 2025, https://aleksandarhaber.com/kalman-filter-complete-derivation-from-scratch/
  17. An explanation of the Kalman filter - Mathematics Stack Exchange, accessed July 29, 2025, https://math.stackexchange.com/questions/840662/an-explanation-of-the-kalman-filter
  18. Kalman Filter Explained Simply, accessed July 29, 2025, https://thekalmanfilter.com/kalman-filter-explained-simply/
  19. Kalman filter - Wikipedia, accessed July 29, 2025, https://en.wikipedia.org/wiki/Kalman_filter
  20. Extended Kalman Filters for Dummies by Raúl Serrano - Medium, accessed July 29, 2025, https://medium.com/@serrano_223/extended-kalman-filters-for-dummies-4168c68e2117
  21. 칼만 필터 - 공돌이의 수학정리노트 (Angelo’s Math Notes), accessed July 29, 2025, https://angeloyeo.github.io/2021/04/07/Kalman_filter.html
  22. Kalman Filters (2. Kalman Filter) - 회원님의 블로그를 잘 설명하는 이름 - 티스토리, accessed July 29, 2025, https://soohwan-justin.tistory.com/43
  23. akshaychawla/1D-Kalman-Filter - GitHub, accessed July 29, 2025, https://github.com/akshaychawla/1D-Kalman-Filter
  24. The Kalman Filter 1 Introduction 2 Introductory Example, accessed July 29, 2025, https://sites.stat.columbia.edu/liam/teaching/neurostat-spr12/papers/hmm/KF-welling-notes.pdf
  25. Kalman Filter in one dimension, accessed July 29, 2025, https://www.kalmanfilter.net/kalman1d.html
  26. Kalman Filter for 1D Motion - Cookie Robotics, accessed July 29, 2025, https://cookierobotics.com/069/
  27. Object Tracking: 2-D Object Tracking using Kalman Filter in Python -, accessed July 29, 2025, https://machinelearningspace.com/2d-object-tracking-using-kalman-filter/
  28. Kalman Filter OpenCV Python Example - Pierian Training, accessed July 29, 2025, https://pieriantraining.com/kalman-filter-opencv-python-example/
  29. Object Tracking: Simple Implementation of Kalman Filter in Python, accessed July 29, 2025, https://machinelearningspace.com/object-tracking-python/
  30. KalmanFilter - FilterPy 1.4.4 documentation, accessed July 29, 2025, https://filterpy.readthedocs.io/en/latest/kalman/KalmanFilter.html
  31. kalman 2d filter in python - Stack Overflow, accessed July 29, 2025, https://stackoverflow.com/questions/13901997/kalman-2d-filter-in-python
  32. How to Tune a Kalman Filter: Step-by-Step Guide JuliaHub, accessed July 29, 2025, https://juliahub.com/blog/how-to-tune-kalman-filter
  33. How to Tune a Kalman Filter: Step-by-Step Guide JuliaHub - juliabloggers.com, accessed July 29, 2025, https://www.juliabloggers.com/how-to-tune-a-kalman-filter-step-by-step-guide-juliahub/
  34. How to improve the Kalman filter? - ResearchGate, accessed July 29, 2025, https://www.researchgate.net/post/How-to-improve-the-Kalman-filter
  35. Tuning Kalman Filter to Improve State Estimation … - MathWorks, accessed July 29, 2025, https://www.mathworks.com/help/fusion/ug/tuning-kalman-filter-to-improve-state-estimation.html
  36. The Ultimate Guide to Kalman Filter in Practice - Number Analytics, accessed July 29, 2025, https://www.numberanalytics.com/blog/ultimate-kalman-filter-practice
  37. What is the best way to learn Kalman Filter? : r/DSP - Reddit, accessed July 29, 2025, https://www.reddit.com/r/DSP/comments/1d0tyid/what_is_the_best_way_to_learn_kalman_filter/
  38. 2 - Non-linear models: extended Kalman filter - Stone Soup’s documentation!, accessed July 29, 2025, https://stonesoup.readthedocs.io/en/v0.1b3/auto_tutorials/02_ExtendedKalmanFilterTutorial.html
  39. EKF vs. UKF performance and robustness comparison for nonlinear state estimation, accessed July 29, 2025, https://blogjtr.com/posts/ekf-vs-ukf/
  40. What is the difference between a particle filter (sequential Monte Carlo) and a Kalman filter?, accessed July 29, 2025, https://stats.stackexchange.com/questions/2149/what-is-the-difference-between-a-particle-filter-sequential-monte-carlo-and-a
  41. A Comparison of Unscented and Extended Kalman Filtering for Estimating Quaternion Motion - UCF Department of Computer Science, accessed July 29, 2025, https://www.cs.ucf.edu/~jjl/pubs/laviola_acc2003.pdf
  42. The math behind Extended Kalman Filtering by Sasha Przybylski - Medium, accessed July 29, 2025, https://medium.com/@sasha_przybylski/the-math-behind-extended-kalman-filtering-0df981a87453
  43. Using an Extended Kalman Filter for Object Tracking in Simulink - Goddard Consulting, accessed July 29, 2025, http://www.goddardconsulting.ca/simulink-extended-kalman-filter-tracking.html
  44. ken-power/SelfDrivingCarND-ExtendedKalmanFilter … - GitHub, accessed July 29, 2025, https://github.com/ken-power/SelfDrivingCarND-ExtendedKalmanFilter
  45. The Extended Kalman Filter (EKF) - Wireless Pi, accessed July 29, 2025, https://wirelesspi.com/the-extended-kalman-filter-ekf/
  46. Unscented Kalman Filter, accessed July 29, 2025, https://www.kalmanfilter.net/ukf.html
  47. EKF vs. UKF: Important Aspects in the Observation of Bioprocesses Iris Publishers, accessed July 29, 2025, https://irispublishers.com/abba/fulltext/ekf-vs-ukf-important-aspects-in-the-observation.ID.000633.php
  48. Extended and Unscented Kalman Filter Algorithms for Online State Estimation - MathWorks, accessed July 29, 2025, https://www.mathworks.com/help/ident/ug/extended-and-unscented-kalman-filter-algorithms-for-online-state-estimation.html
  49. Introduction to Unscented Kalman Filter 1 Introdution, accessed July 29, 2025, https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/AV0809/qi.pdf
  50. Why should I still use EKF instead of UKF? - Robotics Stack Exchange, accessed July 29, 2025, https://robotics.stackexchange.com/questions/3063/why-should-i-still-use-ekf-instead-of-ukf
  51. Unscented KF vs EKF - General - ArduPilot Discourse, accessed July 29, 2025, https://discuss.ardupilot.org/t/unscented-kf-vs-ekf/27052
  52. Particle Filters: A Hands-On Tutorial - Semantic Scholar, accessed July 29, 2025, https://pdfs.semanticscholar.org/fff9/cad8a37e55669bf695772fbdcf728b75fa37.pdf
  53. [논문]칼만 필터를 이용한 GPS/INS융합의 다중 보정 방법, accessed July 29, 2025, https://scienceon.kisti.re.kr/srch/selectPORSrchArticle.do?cn=JAKO201516351715140
  54. Extended-Kalman-Filter-CTRV.py - GitHub, accessed July 29, 2025, https://github.com/balzer82/Kalman/blob/master/Extended-Kalman-Filter-CTRV.py
  55. Application of Data Sensor Fusion Using Extended Kalman Filter Algorithm for Identification and Tracking of Moving Targets from - Semantic Scholar, accessed July 29, 2025, https://pdfs.semanticscholar.org/46c1/fff79fab74311f2230b31353aafb65970f77.pdf
  56. Comparison and evaluation of advanced motion models for vehicle tracking - SciSpace, accessed July 29, 2025, https://scispace.com/pdf/comparison-and-evaluation-of-advanced-motion-models-for-3bu6v6ld05.pdf
  57. 칼만 필터: 투자 예측에 칼만 필터를 사용하는 방법 - FasterCapital, accessed July 29, 2025, https://fastercapital.com/ko/content/%EC%B9%BC%EB%A7%8C-%ED%95%84%ED%84%B0–%ED%88%AC%EC%9E%90-%EC%98%88%EC%B8%A1%EC%97%90-%EC%B9%BC%EB%A7%8C-%ED%95%84%ED%84%B0%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95.html
  58. 칼만 필터 및 투자 예측: 동적 시스템의 상태를 추정하는 방법 - FasterCapital, accessed July 29, 2025, https://fastercapital.com/ko/content/%EC%B9%BC%EB%A7%8C-%ED%95%84%ED%84%B0-%EB%B0%8F-%ED%88%AC%EC%9E%90-%EC%98%88%EC%B8%A1–%EB%8F%99%EC%A0%81-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EC%83%81%ED%83%9C%EB%A5%BC-%EC%B6%94%EC%A0%95%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95.html