【倒立振子part20】連続系から離散系への変換について
これまで連続系での状態空間モデルを作成し最適制御を用いてフィードバックゲインを求めて安定化できることを確認した。
今回からは実際にマイコンで動かすために連続系から離散系への変換を行っていく。
手探りで進めていくので、誤った解釈があるかもしれないのでなるべく丁寧に理解していく。
ゼロ次ホールド
マイコンを使用する際に測定値は一定のサンプリングレートで取り組むことができる。
実際に振子の角度やモータの角速度などは連続的に変化しているが、マイコンはサンプリングレート毎でしか測定できないため「次のサンプリングレートまでは前の値がそのまま引き継がれる」という考えゼロ次ホールドと呼ばれる。
離散化した状態方程式
連続系での状態方程式の解は計算式は省略するが下記の様に求められる。
ここでサンプリングレートをTとすると、ある時刻tの次のステップ時刻t+Tの状態方程式の解は次式で表せる。
ただし入力は離散化されてゼロ次ホールドされているとする。そのためk番目の入力という意味を込めてとする。
以上よりある時刻tにおける状態に対して次ステップ時間T進んだt+Tにおける状態をとすると下式で表すことができる。
これが離散化した状態方程式となる。状態方程式の形にすると
離散化システムの最適制御
離散化された状態方程式のフィードバック制御でも連続系と同様でとして状態方程式の状態を安定化させることができる。
この時の状態フィードバックゲインであるは下記で求めることができる。
●評価関数は行列と定数をを用いて
●この時、評価関数の値を最小にするための状態フィードバック系は下記で表せる。
●上式の行列は下記の「離散時間リカッチ代数方程式」を満たす正定値対称行列である。
シュミレーション
離散化については上記でまとめたので実際のシステムでの離散化での初期応答のシュミレーションを行う。
上記の計算についてもscilabのコマンドを使用することで自動で計算できるため省略できる。
シュミレーションとしては、初期状態による応答、重み行列を変えたときの応答値の挙動についてもまとめる。
初期状態を変更してシュミレーション
サンプル周期と]とする。
初期状態]の3パターンで分けてシュミレーションする。
この時の重み行列は
とする。
初期状態として5degとともかく10degも傾くことはないので初期応答としては問題ないと判断する。
連続システムに対して離散システムは応答性が悪くなっていることが分かった。
重み行列を変更してシュミレーション
次に初期状態を]として、重みを変更してシュミレーションを行う。
【q1の重みを1000として固定してRの重みを変更】
Rを小さくすることで速応答性が上がるため入力が高くなるためR=500ぐらいが限界かなと感じる。
scilabのプログラム
scilabのプログラムは下記の様にした。ただし状態空間モデルと連続系については前回と同様なので省略する。
dt=0.005; //サンプル周期[s] pole_sys_d=dscr(pole_sys,dt); //連続状態の線形システムpole_sysをdtで離散化 Ad=pole_sys_d(2); Bd=pole_sys_d(3); Cd=pole_sys_d(4); V_d=cont_mat(pole_sys_d); //可制御行列 disp("可制御行列のランク") disp(rank(V_d)); //可制御行列のランク確認 //最適制御の重み設計 q1=100; //振子角度の重み q2=0.1; //ホイール角度の重み q3=0.1; //振子角速度の重み q4=0.1; //ホイール角速度の重み Q=[q1,0,0,0;0,q2,0,0;0,0,q3,0;0,0,0,q4]; //直立状態を維持したいのでθ1とθ1'にかかる値を大きくする(ゲインを大きくする),逆にモータの回転については重要度は小さくする R=1000; //R値を大きくするとモータを激しく動かさない、R値を小さくするとモータを素早く動かして安定するシステム Qd=Q*dt; Rd=R*dt; //離散化した最適制御 Pd=ricc(Ad,Bd*inv(Rd)*Bd',Qd,'disc'); //リカッチ方程式の解,contは連続、discは離散 Kd=inv(Rd+Bd'*Pd*Bd)*Bd'*Pd*Ad; //最適レギュレータ ramda_d=abs(spec(Ad-Bd*Kd)); //レギュレータ極(固有値)→離散系では絶対値が1より小さいときに漸近安定する pole_sys_d_fb=syslin(dt,Ad-Bd*Kd,Bd,Cd); //サンプル周期dtでの線形システムの定義 disp("離散リカッチ代数方程式の解 ") disp(Xd) disp("離散フィードバックゲイン ") disp(Kd) disp("離散フィードバックの固有値 ") disp(ramda_d) //状態シュミレーション d0=-0.017*5; //初期状態値 x0=[d0;0;0;0]; //単位はrad、1deg=0.017rad t=0:0.01:2.5; sys_d_x=flts(zeros(t),pole_sys_d_fb,x0); //状態xの応答 Vm=-Kd*sys_d_x; //システム入力u=モータ電圧Vはu=-Kx Im=(Vm-kt*sys_d_x(4,:))/R; //モータの印可電流 subplot(3,1,1); plot(t,sys_d_x(1,:),'r'); xtitle('t-θ','時間[t]','本体傾き[rad]') xgrid() legend(['連続系';'離散系'],4); subplot(3,1,2); plot(t,sys_d_x(2,:),'r'); xtitle('t-ω','時間[t]','本体傾き[rad/s]') xgrid() legend(['連続系';'離散系'],4); subplot(3,1,3); plot(t,Vm,'r'); xtitle('t-V','時間[t]','印可電圧[V]') xgrid() //システムの状態の1列目はθ1,2列目はθ1',3列目はθ2,4列目はθ2' legend(['連続系';'離散系'],4);
次回
連続システム⇒離散システムについて理解ができシュミレーションできた。
次は実際にマイコンに書き込むためのプログラムの作成と実行を行う。