Kalman濾波器推導與實現(Python版本)

  • 卡爾曼濾波(Kalman Filter)

本文在參考文獻的基礎上添加了自己的理解,若有不當之處,敬請指正
卡爾曼濾波以前接觸過,但是沒有仔細推導,這次參考文獻仔細推導實現,也是第一次完全的通過vscode+markdown來完成寫作。
卡爾曼濾波,也被稱爲線性二次估計(Liner Quadratic Estimation, LQE),可以作爲平滑數據、預測數據、濾波器;本人理解:是一個觀察→預測的過程,我接觸到的卡爾曼濾波主要有KF(卡爾曼濾波,線性),EKF(擴展卡爾曼濾波,非線性),UKF(無跡卡爾曼濾波,強非線性)。此處,只研究基本的KF。

在這裏插入圖片描述
     圖1 來自老爺子的親切凝視


  • 參考:

1. 導論

1960年, R.E. Kalman發表了他使用迭代方法解決離散線性濾波問題的文章(《A New Approach to Linear Filtering and Prediction Problems》),揭開了卡爾曼濾波的歷史篇章,得益於數字計算能力的發展,卡爾曼濾波方法在得到了廣泛應用,尤其是在自主/輔助導航方面。 現在該方法在計算機圖像處理,多數據融合方面也得到廣泛應用。
1)第一個問題:什麼是卡爾曼濾波
  卡爾曼濾波是一種最優化自迴歸數據處理算法。其中最優化體現在:1)動態使用系統和測量設備的信息;2)該理論包含了系統噪聲、測量誤差、動態模型的不確定性;3)和感興趣變量初始狀態相關的各種可用信息。其中的自迴歸表現在:卡爾曼濾波器不需要使用/儲存過去所有時刻的數據,使得卡爾曼濾波器計算性能好。
2)第二個問題:爲什麼用卡爾曼濾波
  卡爾曼濾波最初是爲了解決控制問題。通常在做系統分析或者控制系統設計的時候,研究人員都會期望從變量的內在聯繫來建立一個理論模型,通過對理論模型的研究來研究問題。但是,理論模型並不完美,而且模型的結果也只是近似罷了,而觀測到的數據也不是完整和完美的。基於這些存在的問題,所以研究人員探索能夠解決這些問題的方法,也就有了卡爾曼濾波。


2. 卡爾曼濾波方法推導

本方法注重思路,詳細過程請參考文章開始列出的文獻。

2.1 lossfunction

前邊提到,卡爾曼是一種線性二次估計,相當於一種優化算法,優化算法的目標就是針對損失函數,並使得損失函數最大或者最小。首先考慮一個最簡單的線性模型:

  • yk=akxk+nky_k = a_kx_k + n_k
    其中xkx_k是系統的狀態量,但是這個狀態量一般我們建模不準確,會存在一個誤差,量化這個誤差就使用如下形式:
  • ek=xkxk^e_k = x_k - \hat{x_k}   --這個誤差越小,建模狀態量越準確,得到的輸出值也就越準確
    但是eke_k有正有負不好優化,所以引入均方差(mean squared error, MSE), 可以只向一個方向優化:
  • lossfunciton=E(ek2)lossfunciton = E(e_k^2)

2.2. 極大似然估計

原理:從已知結果出發,反推參數值,這個參數值將使得結果出現的概率最大。
抽象一下問題:已知觀測結果y,需要反推狀態參數xk^\hat{x_k}。所以最大似然估計的目標就是使得y的條件概率最大:

  • max(P[yx^])max(P[y|\hat x])
    假設的隨機噪聲是符合標準偏差爲$\sigma _k $的高斯分佈(正態分佈),那麼條件概率可以寫爲:

  • P(ykx^k)=Kkexp((ykakx^k)22σk2)P(y_k|\hat x_k) = K_kexp-(\frac{(y_k -a_k\hat x_k)^2}{2\sigma _k^2})
    那麼極大似然概率就是取得乘積:

  • P(ykx^k)=ΠkKkexp((ykakx^k)22σk2)P(y_k|\hat x_k) =\mathop{\Pi} \limits_{k} K_kexp-(\frac{(y_k -a_k\hat x_k)^2}{2\sigma _k^2})
    有exp, 可以通過取對數,將乘積轉換爲加和運算:

  • logP(ykx^k)=12k((ykakx^k)22σk2)+constantlogP(y_k|\hat x_k) = -\frac{1}{2}\sum \limits_{k} (\frac{(y_k -a_k\hat x_k)^2}{2\sigma _k^2}) + constant

    所以目標就是,找到x^k\hat x_k使得logP(ykx^k)logP(y_k|\hat x_k)最大,那麼x^k\hat x_k就是最有可能的狀態值。可以看到logP(ykx^k)logP(y_k|\hat x_k)的表達式其實就是2.1中描述的均方差的形式。我們可以通過最小化均方誤差來求x^k\hat x_k

2.3 狀態方程推導

總體思路還是比較簡單:由狀態構建一個誤差表達式,並將該表達式構建爲MSE形式,根據已知條件推導,將MES改寫稱爲一個包含已知量的表達式,求導,令導數等於零求得極小點,將該點回代至表達式,結束!整個推導過程的步驟也比較簡單,只是涉及的量比較多,以及矩陣表達的形式,看起來比較繁雜而已。


已知條件,6個
一般情況下,我們將一個系統描述爲狀態方程和觀測方程:

  • 狀態方程: xk+1=Φxk+wkx_{k+1} = \Phi x_k + w_k
  • 觀測方程: zk=Hxk+vkz_k = Hx_k + v_k

wkw_k爲已知協方差的過程白噪聲,vkv_k爲已知協方差的測量白噪聲,且二者不相關。
所以,以下兩個值已知:

  • Q=E(wkwkT)Q = E(w_kw_k^T)
  • R=E(vkvkT)R = E(v_kv_k^T)
  • ek=xkx^ke_k = x_k - \hat x_k
  • x^k=x^k+Kk(zkHx^k)\hat x_k =\hat x_k^{'} + K_k(z_k - H\hat x_k^{'}) x^k\ldots \hat x_k^{'}表示直接估計的值,該式將在下一節的極大似然估計中推導

求解問題
優化的目標根據2.1就是:

lossfunciton=E(ek2)=E(ekekT)=Pklossfunciton = E(e_k^2) = E(e_ke_k^T) = P_k 一切都是從這個方程出發


推導過程

先處理已知條件:

  • zkz_k 代入表達式:x^k=x^k+Kk(zkHx^k)=x^k+Kk(Hxk+vkHx^k)=KkHxk+(IKkH)xk+Kkvk\hat x_k =\hat x_k^{'} + K_k(z_k - H\hat x_k) = \hat x_k^{'} + K_k(Hx_k + v_k - H\hat x_k^{'}) =K_kHx_k + (I - K_kH)x_k^{'} +K_kv_k
  • x^k\hat x_k 代入表達式:ek=xkx^k=xk(KkHxk+(IKkH)xk+Kkvk)=(IKkH)(xkxk)Kkvke_k = x_k - \hat x_k =x_k -(K_kHx_k + (I - K_kH)x_k^{'} +K_kv_k) = (I - K_kH)(x_k - x_k^{'}) - K_kv_k
  • eke_k 代入
    Pk=E(ekekT)=E[[(IKkH)(xkxk)Kkvk][(IKkH)(xkxk)Kkvk]T]=(IKkH)E[(xkxk)(xkxk)T](IKkH)TKkE[vkvkT]KkT \begin{array}{l} P_k = E(e_ke_k^T) \\ = E[[(I - K_kH)(x_k - x_k^{'}) - K_kv_k][(I - K_kH)(x_k - x_k^{'}) - K_kv_k]^T] \\ =(I - K_kH)E[(x_k - x_k^{'})(x_k - x_k^{'})^T](I - K_kH)^T - K_kE[v_kv_k^T]K_k^T \end{array}
    根據ek,Pke_k, P_k的定義,可以將上式中與期望有關的項改寫成新的形式,可以得到:
  • Pk=(IKkH)Pk(IKkH)TKkRKkTP_k =(I - K_kH)P_k^{'}(I - K_kH)^T - K_kRK_k^T
    PkP_k^{'}稱爲先驗估計,這裏就得到協方差關係式,由於直接處理矩陣不好處理,所以,通過展開,再求跡(tr)然後求導,令導數等於零,求得極小值點,再回代入原方程。
    展開:
  • Pk=(IKkH)Pk(IKkH)TKkRKkT=PkKkHPkPkHTKkT+Kk(HPkHT+R)KkT\begin{array}{l} P_k =(I - K_kH)P_k^{'}(I - K_kH)^T - K_kRK_k^T \\ =P_k^{'}-K_kHP_k^{'}-P_k^{'}H^TK_k^T+K_k(HP_k^{'}H^T+R)K_k^{T} \end{array}
    求跡:
  • T[Pk]=T[Pk]2T[KkHPk]+T[Kk(HPKHT+R)KkT]T[P_k] = T[P_k^{'}] - 2T[K_kHP_k^{'}] + T[K_k(HP_K^{'}H^T+R)K_k^{T}]
    求導:
  • dT[Pk]dKk=2(HPk)T+2Kk(HPkHT+R)=0\frac{dT[P_k]}{dK_k} = - 2(HP_k^{'})^T + 2K_k(HP_k^{'}H^T+R) = 0
    2Kk(HPKHT+R)=2HPk\Rightarrow 2K_k(HP_K^{'}H^T+R) = 2HP_k^{'}
    Kk=(HPk)T(HPkHT+R)1\Rightarrow K_k = (HP_k^{'})^T(HP_k^{'}H^T+R)^{-1} {方程.1,卡爾曼增益方程}
  • KkK_k回代到PkP_k展開的關係式中,替換掉最後一項中的第一個KkK_k
    Pk=PkKkHPk2(HPk)TKkT\Rightarrow P_k = P_k^{'}-K_kHP_k^{'}-2(HP_k^{'})^TK_k^{T}
    Pk=(IKkH)Pk\Rightarrow P_k = (I -K_kH )P_k^{'} {方程.2,協方差更新方程}

推到這裏,我們已經得到卡爾曼濾波方程中的兩個關係式,但是PkP_k^{'}還是未知的
\because 直接的估計值沒有辦法估計噪聲,用上個狀態的最優值根據模型來直接估計:
\therefore xk+1=Φx^kx_{k+1}^{'} =\Phi \hat x_k {方程3.狀態估計方程}
Pk+1=E[ek+1ek+1T]\because P_{k+1}^{'} = E[e_{k+1}^{'}e_{k+1}^{T'}]
又,
ek+1=xk+1xk+1=Φxk+wkΦx^k=Φek+wk\because e_{k+1}^{'} = x_{k+1} - x_{k+1}^{'} = \Phi x_k + w_k - \Phi \hat x_k = \Phi e_k + w_k
Pk+1=E[(Φek+wk)(Φek+wk)T]=ΦE[ekekT]ΦT+E(wkwkT)=ΦPkΦT+Q\begin{array}{l} \therefore P_{k+1}^{'} = E[(\Phi e_k + w_k )(\Phi e_k + w_k )^T] \\ = \Phi E[e_ke_k^T]\Phi ^T + E(w_kw_k^T) \\ = \Phi P_k \Phi ^T + Q \end{array}
Pk+1=ΦPkΦT+Q\Rightarrow P_{k+1}^{'} = \Phi P_k \Phi ^T + Q {方程4.協方差估方程}
PkP_k^{'}採用該關係式,由上一步數據計算得到。


至此,推導出了卡爾曼濾波方程當中的四個,還缺少一個最優估計方程,也就是已知條件的最後一個。

2.4 極大似然估計的推導

爲什麼有這部分?已知條件的最後一個是直接給出的,這裏解釋關係式是怎麼來的。
從2.2知道,極大似然估計就是在觀測值
卡爾曼濾波尋求最小化均方差的目標和卡方分佈(chi-square)有很多相似之處,卡方分佈的觀察頻數與期望頻數越接近,兩者之間的差異越小,也就是觀測值會更加接近真實值。這裏直接推導chi-square,最後從結論得到最優估計。
拋開前邊推導的一切,重新開始,假設一個卡方分佈:
χ2=i=1k((zkh(a,x)2σi2)\chi^2 = \sum \limits_{i=1}^{k} (\frac{(z_k -h(a,x)^2}{\sigma _i^2})
zizkh(a,x)xh(),σi(vk)z_i 測量值(相當於z_k),h(a, x) 表示參數爲x的模型h(相當於觀測方程模型),在\sigma _i是和測量值有關的誤差(相當於v_k)
通過改寫形式:
χ2=i=1k(1σiσi(zkh(ai,x)2)\chi^2 = \sum \limits_{i=1}^{k} (\frac{1}{\sigma _i\sigma _i}(z_k -h(a_i,x)^2)
將標量形式轉化爲向量形式:(注此處的RR與前邊的RR沒有直接聯繫,但是含義相似)
χk2=[zkh(a,xk)]R1[zkh(ai,x]T\chi_k^2 = [z_k -h(a,x_k)]R^{-1}[z_k -h(a_i,x]^T
上式只使用了k時刻的測量值,爲了能夠前邊所有的測量值,需要:
χk12=kκ(zkh(a,x)R1(zkh(a,x)Tχmin2+(xk1x^k1)R1(xk1x^k1)T\begin{array}{cc} \chi_{k-1}^2 = \sum \limits_{k}^{\kappa} (z_k -h(a,x)R^{-1}(z_k -h(a,x)^T \\ \approx \chi_{min}^2 + (x_{k-1} -\hat x_{k-1})R^{-1}(x_{k-1} -\hat x_{k-1})^T \end{array}
考慮前邊的所有數據:
χ2=χk2+χk12=[zkh(a,xk)]R1[zkh(ai,x)]T+χmin2+(xk1x^k1)R1(xk1x^k1)T\begin{array}{cc} \chi^2 = \chi_k^2 + \chi_{k-1}^2 =[z_k -h(a,x_k)]R^{-1}[z_k -h(a_i,x)]^T + \chi_{min}^2 + (x_{k-1} -\hat x_{k-1})R^{-1}(x_{k-1} -\hat x_{k-1})^T \end{array}
考慮
h(a,xk)=h(a,(x^k+Δx))wherexk=x^k+Δxh(a,x_k) = h(a,(\hat x_k + \Delta x)) where x_k = \hat x_k + \Delta x
使用泰勒展開:
h(a,(x^k+Δx))=h(x^)+Δxxh(x^)\Rightarrow h(a,(\hat x_k + \Delta x)) = h(\hat x) + \Delta x \nabla _x h(\hat x)
對卡方求導,並將hΔxkh和\Delta x_k的表達式是代入:
d(χ2)dx=2Pk11(xk1x^k1)2xh(a,xk)TR1[zkh(a,xk)]=2Pk11(xk1x^k1)2xh(a,xk)TR1[zkh(a,x^)+(xkx^k)xh(a,x^k)]\begin{array}{cc} \frac {d(\chi ^2)}{dx} = 2P_{k-1}^{'-1}(x_{k-1}-\hat x_{k-1}) - 2\nabla _xh(a,x_k)^TR^{-1}[z_k-h(a,x_k) ] \\ =2P_{k-1}^{'-1}(x_{k-1}-\hat x_{k-1}) - 2\nabla xh(a,x_k)^TR^{-1}[z_k-h(a,\hat x) + (x_k- \hat x_k) \nabla _x h(a,\hat x_k) ] \end{array}
假設估計模型的參數和實際模型的參數十分接近,那麼他們的梯度相等:
xh(a,xk)=xh(a,x^k)=H\nabla _x h(a,x_k) = \nabla _x h(a,\hat x_k) = H
代入求導後的等式,並令該導數等於零,求得極值點:
d(χ2)dx=0=2Pk11(xk1x^k1)2HTR1[zkh(a,x^)+(xkx^k)H]=2(Pk11HTR1H)(xkx^k)2HTR1[zkh(a,x^)]\begin{array}{cc} \frac {d(\chi ^2)}{dx} =0 = 2P_{k-1}^{'-1}(x_{k-1}-\hat x_{k-1}) - 2H^TR^{-1}[z_k-h(a,\hat x) + (x_k- \hat x_k) H ] \\ =2(P_{k-1}^{'-1} - H^TR^{-1}H)(x_k- \hat x_k) - 2H^TR^{-1}[z_k-h(a,\hat x)] \end{array}
求解方程:
(xkx^k)=x=(Pk11HTR1H)(xkx^k)1HTR1[zkh(a,x^)](x_k- \hat x_k) = \nabla x =(P_{k-1}^{'-1} - H^TR^{-1}H)(x_k- \hat x_k)^{-1}H^TR^{-1}[z_k-h(a,\hat x)]
令:Kk=(Pk11HTR1H)HTR1 K_k =(P_{k-1}^{'-1} - H^TR^{-1}H)H^TR^{-1}
所以:
xk=x^k+x=x^k+Kk[zkh(a,x^)]x_k = \hat x_k + \nabla x = \hat x_k + K_k[z_k-h(a,\hat x)]
已知,我們推出了一個線性問題可以表達爲y=ax+by = ax + b,那麼我們遇到一個問題,判斷爲線性問題,就可以直接假設其方程爲y=ax+by = ax + b,再求解其參數。同樣的道理,我們已經推導出卡方問題的形式可以表示爲xk=x^k+Kk[zkh(a,x^)]x_k = \hat x_k + K_k[z_k-h(a,\hat x)],那麼對於卡方問題的卡爾曼濾波形式,我們可以直接假設:
x^k=x^k+Kk(zkHx^k)\hat x_k =\hat x_k^{'} + K_k(z_k - H\hat x_k^{'})
再通過已知的其他條件來求解對應參數。
注意:這裏的KkK_k只是使用了卡方的形式,並不是卡方推導公式裏的KkK_k值,這裏KkK_k的值由2.3中的推導求出的。

3.卡爾曼濾波的基本計算過程

卡爾曼濾波的核心點就是狀態、協方差,一共分爲5步,反覆迭代進行。
1. 由上一步最優狀態估計當前狀態;
2. 由上一步最優協方差估計當前協方差;
3. 計算卡爾曼增益;
4. 由狀態測量值和狀態估計值,預測當前狀態最優值;
5. 由卡爾曼增益、估計協方差計算當前協方差最優值;

五步方程:

  • (1) X^kk1=Fk1X^k1+Gk1uk1\hat{X}_{k|k-1} = F_{k-1}\hat{X}_{k-1} + G_{k-1}u_{k-1}
  • (2) Pkk1=Fk1Pk1Fk1T+Gk1uk1P_{k|k-1} = F_{k-1}P_{k-1}F_{k-1}^T + G_{k-1}u_{k-1}
  • (3) Kk=Pkk1HkT(HkPkk1HkT+Rk)1K_k = P_{k|k-1}H_{k}^T(H_{k}P_{k|k-1}H_{k}^T+R_{k})^{-1}
  • (4) X^k=X^xk1+Kk(zkHkX^xk1)\hat{X}_{k} = \hat{X}_{x|k-1} + K_{k}(z_{k}-H_{k}\hat{X}_{x|k-1})
  • (5) Pk=(IKkHk)Pkk1P_{k} = (I-K_kH_k) P_{k|k-1}
初狀態
估計
預測
更新

4.卡爾曼濾波方法的實例

爲了更好地理解卡爾曼濾波,下面引入一個簡單的實例來進行說明,牛頓力學模型:

  • 假設:小球做自由落體運動,忽略阻力,
  • 目標:濾波器KF由初始位置的不確定性來估計小球的位置
  • 符號說明:
    符號 hh gg tt Δt\Delta t kk k1k-1
    說明 高度 重力加速度 時刻 微小時間長度 當前計數 上一個計數

根據基本的牛頓力學定律,經過Δt\Delta t時間後:
* 速度關係:h˙(t)=h˙(tΔt)gΔt\dot h(t) = \dot h(t - \Delta t)-g\Delta t
* 距離關係:h(t)=h(tΔt)+h˙(tΔt)Δt12g(Δt)2h(t)=h(t-\Delta t)+\dot h(t-\Delta t)\Delta t-\frac{1}{2}g(\Delta t)^2

以上是該問題的連續性表述,將該問題離散化(這個離散化的思路有點意思),假設t=kΔtt=k\Delta t,將上述公式重寫爲:
* 速度關係:h˙(kΔt)=h˙(kΔtΔt)gΔt\dot h(k\Delta t) = \dot h(k\Delta t - \Delta t)-g\Delta t
* 距離關係:h(kΔt)=h(kΔtΔt)+h˙(kΔtΔt)Δt12g(Δt)2h(k\Delta t)=h(k\Delta t-\Delta t)+\dot h(k\Delta t-\Delta t)\Delta t-\frac{1}{2}g(\Delta t)^2

變量形式的替換不一一說明,按照位置對應即可。
更改一下表述形式:
* 速度關係:h˙k=h˙k1gΔt\dot h_k = \dot h_{k-1}-g\Delta t
* 距離關係:hk=hk1+h˙k1Δt12g(Δt)2h_k=h_{k-1}+\dot h_{k-1}\Delta t-\frac{1}{2}g(\Delta t)^2

轉換成矩陣表示:
[hkh˙k]=[1Δt01][hkh˙k]+[12(Δt)2Δt]g\left[\begin{matrix}h_k \\\dot h_k \\\end{matrix} \right]= \left[\begin{matrix}1 & \Delta t \\0 &1 \\\end{matrix} \right]\left[\begin{matrix}h_k \\\dot h_k \\\end{matrix} \right] + \left[\begin{matrix} -\frac{1}{2}(\Delta t)^2 \\ -\Delta t \\\end{matrix} \right]g

將對應位置的變量換一種表達形式:
Xk=Fk1Xk1+Gk1uk1X_k = F_{k-1}X_{k_1} + G_{k-1}u_{k-1}(狀態方程)

此外,還需建立一個觀測方程: 觀測值爲輸出狀態值加上觀測噪聲
yk=[10]hk+vky_k = \left[\begin{matrix}1 & 0 \\\end{matrix}\right] h_k + v_k
寫成矩陣的形式:
yk=HkXk+vky_k = H_kX_k + v_k

這個時候,回到卡爾曼濾波問題,思考一下想要使用卡爾曼濾波需要哪些變量?


5.卡爾曼濾波方法的Python實現

圖1是估計值與真實值之間的差值變化情況,隨着時間推移,估計值越來越接近真實值,最終在真實值附近波動。圖2是測量值、真實值、估計值的一個情況對比。Python代碼部分將4中的實例執行了一次。
在這裏插入圖片描述在這裏插入圖片描述

#-*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

#定義步長和迭代次數
iterations = 1000
delta_t = 0.001
#生成時間序列
time = np.linspace(0,1,iterations)
time = np.mat(time)

#定義g值
g = 9.80665 
# 系統真值
z = [100-0.5*g*(delta_t*i)**2 for i in range(iterations)]
z_watch = np.mat(z)
# 創建一個方差爲1的高斯噪聲,精確到小數點後兩位
noise = np.round(np.random.normal(0, 1, iterations), 2)
noise_mat = np.mat(noise) 
# 將z的觀測值和噪聲相加
z_mat = z_watch + noise_mat
# 定義最優估計的輸出
y = []

# 定義x的初始狀態
x_mat = np.mat([[105,], [0,]])
# 定義初始狀態協方差矩陣
p_mat = np.mat([[10, 0], [0, 0.01]])
# 定義狀態轉移矩陣,因爲每秒鐘採樣1000次,所以delta_t = 0.001
f_mat = np.mat([[1, delta_t], [0, 1]])
# 定義輸入矩陣
g_mat = np.mat([[-0.5*delta_t**2],[-delta_t]])
# 定義狀態轉移協方差矩陣,這裏我們把協方差設置的很小,因爲覺得狀態轉移矩陣準確度高
q_mat = np.mat([[0.0, 0], [0, 0.0]])
# 定義觀測矩陣
h_mat = np.mat([1, 0])
# 定義觀測噪聲協方差
r_mat = np.mat([4])

#卡爾曼濾波器的5個公式
for i in range(iterations):
    x_predict = f_mat * x_mat + g_mat * g
    p_predict = f_mat * p_mat * f_mat.T + q_mat
    kalman = p_predict * h_mat.T / (h_mat * p_predict * h_mat.T + r_mat)
    x_mat = x_predict + kalman *(z_mat[0, i] - h_mat * x_predict)
    p_mat = (np.eye(2) - kalman * h_mat) * p_predict
    
    #將每步計算結果添加到序列中
    y.append(x_mat[0].tolist()[0][0])

#數據格式轉化
y = np.mat(y)
error = y - z_watch
y = y.A
error = error.A
time = time.A
z_mat = z_mat.A
z_watch = z_watch.A

#繪圖
plt.plot(time[0,:], z_mat[0,:],  label = 'Measured')  
plt.plot(time[0,:], z_watch[0,:],'g', label='True')  
plt.plot(time[0,:], y[0,:], 'r',label = 'Estimated')   
plt.xlabel('h(m)')
plt.ylabel('time(s)')
plt.legend(loc='lower right')

plt.figure(2)
plt.plot(time[0,:], error[0,:], label ='Errors')
plt.ylabel('error(m)')
plt.xlabel('time(s)')
plt.legend(loc='lower right')
plt.show()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章