はじめに
wiki: 「カルマンフィルタ(KalmanFilter,KFと略す) は、誤差のある観測値を用いて、ある動的システムの状態を推定あるいは制御するための、無限インパルス応答フィルタの一種である」。観測値に観測雑音、状態予測値にシステム雑音があって場合により時間とともに誤差がドンドン蓄積してそのまま使えないので、観測と予測のガウス性を利用した線形センサデータフュージョンがカルマンフィルタの原点である。
状態空間モデル
時系列解析の中で、予測値と観測値の間何らかの因果関係を見つけて、何らかの方法でそれらのデータを絡んでモデル化して状態を推定していく。ここで汎用的な状態方程式、観測方程式は以下の式にする。
xt=Ft−1(xt−1)+qt−1yt=Ht(xt)+rt
ただし、システム雑音、観測雑音(qt,rt)は期待値が0、分散が(Qt,Rt)の独立正規分布(ガウス分布)にする。
p(qt)~N(0,Qt)p(rt)~N(0,Rt)E[qtrt]=0
基本原理
カルマンフィルタの原理は以下のイメージに示すように、最小解析誤差推定(最小二乗)から予測値、観測値をそれぞれの割合I−KtHt,Ktで線形合成した値を状態推定値にする。

式の導出
ベイズの定理やガウス分布からいくつかのの導出方法はあるが、本記事はシンプルな最小二乗法からカルマンフィルタの黄金5式 ∗を誘導する。
線形システム
F(.),H(.)とも線形関数の場合、以下線形カルマンフィルタの誘導となる。例えばF(x)=Ax+B、A,Bとも実数行列、xは変数行列とする。
まずは、予測値(数学期待)を求めるのは出発点なので、すべては以下の式から始まる。
γt=Ft−1(γt−1) c
推定値xesttは、重みKtの調整で予測値xtと観測値ytの間にあろうとして、以下線形表現がある。
xestt=xt+Kt(yt−Htxt)=Ft−1(xtruet−1+pt−1)+qt−1+Kt{(Htxtruet+rt)–Ht(Ft−1(xtruet+pt−1)+qt−1)}=xtruet+Ft−1pt−1+qt−1+Kt(rt−HtFt−1pt−1−Htqt−1)
解析誤差(共分散Pt)は以下の式より求める。
Pt=E[(xestt−xtruet)2] =E[(Ft−1pt−1+qt−1+Ktrt−KtHtFt−1pt−1−KtHtqt−1)2]=Ft−1Pt−1FTt−1−2Ft−1PtFTt−1HTtKTt+Qt−1−2Qt−1HTtKTt+KtRtKTt+KtHtFt−1Pt−1FTt−1HTtKTt+KtHtQt−1HTtKTt
ここから二乗の最小化より解析誤差(共分散Pt)を最小値に至らせるKtを求める。
∂Pt∂Kt=0∂Pt∂Kt=−2Ft−1Pt−1FTt−1HTt−2Qt−1HTt+2KtRt+2KtHtFt−1Pt−1FTt−1HTt+2KtHtQt−1HTtKt=(Ft−1Pt−1FTt−1+Qt−1)HTt{Rt+Ht(Ft−1Pt−1FTt−1+Qt−1)HTt}−1
これで、状態予測時Kt=0より、式⋅をPt=Ft−1Pt−1FTt−1+Qt−1 ∗∗に、Ktは、以下のように簡略化する。
Kt=PtHTt(Rt+HtPtHTt)−1 ∗∗∗
これから観測値を入れて、Kt を使って推定値を求める。
xestt=xt+Kt(yt–Htxt) ∗∗∗∗
推定値を求めたら、続いてPtを更新する。前述した#式の展開の項らより、最後の式は誘導できる。
P′t=(I–KtHt)Pt ∗∗∗∗∗
P′tは、(t+1)時刻のPtとして利用される。
非線形システム
線形カルマンフィルタのF(.),H(.)は非線形関数の場合、f(.),h(.)と記す。例えばf(x)=Ax2+B、A,Bとも実数行列、xは変数行列として、ティラー展開の最初の2項のみ使って、ˆf(x)=f(a)+∂f(x)∂x|x=ax のようにAa2+B+2A(Aa2+B)xに線形化することができる。3項目以降は捨てるので大いに誤差を招く可能性ある。状態予測の際に線形カルマンフィルタのFをf、観測値の取り入れる際に線形カルマンフィルタのHをhに、共分散行列の計算の際にF,Hを∂f(x)∂x|x=xt−1,∂h(x)∂x|x=xtに置き換えて済む。
これまでカルマンフィルタの誘導で、状態値推定の手順を以下のとおり整理しておく。
推定の手順
時系列の状態推定に応用して、以下状態予測Predict→測定更新 Measurement Update→状態更新Correct,Update→時間更新Time Update→次の状態予測Predict→…の繰り返すことによって、時系列とともに状態の数学期待と最小解析誤差(共分散)を求める手順となる。
Step0=パラメータ初期化(t=0)
状態推定(数学期待)、解析誤差共分散の初期化
ˆx0=E[x0]^P0=E[(x0−^x0)(x0−^x0)T]
Step1=状態値、共分散行列予測(t>0)
¯xt=Ft−1(ˆxt−1)¯Pt=Ft−1ˆPt−1FTt−1+Qt−1
ただし、¯xtは予測値、¯Ptは事前共分散行列、Qt−1=E[qt−1qTt−1]
Step2=カルマンゲイン、状態値、共分散行列更新
Kt=¯PtHTt(Ht¯PtHTt+Rt)−1^xt=¯xt+Kt(yt–Ht¯xt)^Pt=(I−KtHt)¯Pt
ただし、Ktはカルマンゲイン、^xtは状態推定値、^Ptは事後共分散行列、Rt=E[rtrTt]
KFフローチャート

拡張カルマンフィルタ
拡張カルマンフィルタ(ExtendedKalmanFilter,EKFと略す)は、非線形フィルタリングである。前述した状態方程式、観測方程式より、以下の状態空間モデルのf(⋅)またはh(⋅)が非線形関数であり、拡張カルマンフィルタが適用される。テイラー展開より、2次微分以降の項目を省略して、非線形であるf(⋅),h(⋅)の1次微分を線形化とし、前述したカルマンフィルタのアルゴリズムが適用可能となる。しかし、f(⋅),h(⋅)の微分ではf(⋅),h(⋅)の一部しか表現できず、この線形化処理(1次微分)が誤差を大きく招く可能性がある。
Ft−1=∂ft−1(x)∂x|x=ˆxt−1Ht=∂ht(x)∂x|x=ˆxt
状態空間モデル
xt=ft−1(xt−1)+qt−1yt=ht(xt)+rt
Step0=パラメータ初期化(t=0)
ˆx0=E[x0]^P0=E[(x0−^x0)(x0−^x0)T]
Step1=状態値、共分散行列予測(t>0)
¯xt=ft−1(ˆxt−1)¯Pt=Ft−1ˆPt−1FTt−1+Qt−1
ただし、¯xtは予測値、¯Ptは事前共分散行列、Qt−1=E[qt−1qTt−1]
Step2=カルマンゲイン、状態値、共分散行列更新
Kt=¯PtHTt(Ht¯PtHTt+Rt)−1^xt=¯xt+Kt(yt–ht¯xt)^Pt=(I−KtHt)¯Pt
ただし、Ktはカルマンゲイン、^xtは状態推定値、^Ptは事後共分散行列、Rt=E[rtrTt]
EKFフローチャート

拡張カルマンフィルタを6軸IMUへの適用
6軸IMUへの適用例として、本サイトの記事 6軸IMU~拡張カルマンフィルタ に載ってある。
カルマンフィルタの再考
カルマンフィルタでは、状態推定値を予測結果xt(実装例ではジャイロセンサーデータ)と観測データyt(実装例では加速度センサデータ)の線形結合で合成し,その誤差を最小にする推定法だと分かる。これはシステム誤差、観測誤差の数学期待が0の正規分布との前提条件から由来した推定法である。しかし、カルマンフィルタをかけることで、状態推定値は予測結果と観測データの間にあるのは、真値からかなり乖離してしまう場合にあるのか。これはシステム誤差と観測誤差が無相関かつ直交という前提から、勿論真値が推定値と観測値の間にある結論を結ぶ考えである。また、ジャイロセンサーデータと、加速度センサデータとも観測値ytにする方法がある。それぞれのパーフォーマンスの検証は、比較的精確な実験環境(比較用の高精度ジャイロセンサ、加速度センサ、エンコーダ、モータ)がないと、実は容易ではない。というよりも、シミュレーションをかけてカルマンフィルタのアルゴリズムを検証するのが、確実に可能である。
参考文献
1-wikipedia: カルマンフィルタ、オイラー角
2-Greg Welch氏、Gary Bishop氏: An Introduction to the Kalman Filter
3-田島洋氏: マルチボディダイナミクスの基礎―3次元運動方程式の立て方
関連記事
オイラー角~ジンバルロック~クォータニオン
SLAM~拡張カルマンフィルタ
SLAM~Unscentedカルマンフィルタ
9軸IMUセンサ 6軸/9軸フュージョン 低遅延 USB出力 補正済み ROS対応
9軸IMU ICM-20948をロボットに組み込もう
YDLIDAR G4=16m 薄型 ROS対応SLAM LIDAR
研究開発用 台車型ロボット キット