matlabの使い方についてまとめる 参考書 ・MATLAB/Simulinkによるわかりやすい制御工学 ・https://www.mathworks.com/help/physmod/smlink/ref/-inventor-constraint-simmechanics-joint-correspondence.html ・https://jp.mathworks.com/help/physmod/sm/cad-import.html ・https://jp.mathworks.com/help/physmod/sm/ug/joint-actuation.html
PA + A'P = -Q のPを求める
A = 線形システムの行列A
Q = eye(Aのサイズと同じ)
P = lyap(A',Q)
eig(P)
状態空間表現からA,Cを使用する
Vo = obsv(A,C)
rank(Vc) %このランクがVoの列と同じなら可観測
det(Vc) %この値が0でなければ可観測(1入力の場合)
obsv(A,C)
: k可観測行列を求める A,Cは状態空間表現から双対システムの特徴を利用し A+B*K用のアルゴリズムをA=A',B=C'に置き換えることで利用する
状態空間表現からA,Cを使用する
L = -acker(A',C',q)'
上記の作業でオブザーバーゲインを求めることができる
注意
A+B*K 置き換えで A'+C'L' なのでこれで求められるものはL'なので最後に転置することでLがわかる
可制御を求める方法
状態空間表現からA、Bを使用する
A = 任意の行列
B = 任意の行列
Vc = ctrb(A,B)
rank(Vc) %この結果がVcの行サイズと同じなら可制御
[n,m] = size(Vc) % n:行サイズ, m:列サイズ
rank(Vc) == n %結果が1なら可制御,0なら不可制御
det(Vc) %この値が0でなければ可制御(1入力の場合)
ctrb(A,B)
: 可制御行列を求める A,Bは状態空間表現のA行列、B行列rank(行列)
: 行列のランクを求められる => 行フルランクなら可制御(行列の行数とランクが同じ場合)%行列の定義-----------------------
A = [-3 1;2 -2];
B = [2;0];
%変数(シンボリック)の定義---------
syms lambda k1 k2 p1 p2
----------------------------------
%ゲイン行列Kと併合システムのAcl行列の定義----
K = [k1, k2];
Acl = A + B*K;
%--------------------------------------------
%特性多項式(|λI-Acl|を求める[k1,k2]を利用したパターン)
eq1 = det(lambda*eye(2) - Acl); %行列式
eq1 = collect(eq1,lambda) %lambdaのべき乗で係数をまとめる
coe1 = coeffs(eq1,lambda) %lambdaの係数をすべて返す(次元の低いものから返される)
%--------------------------------------------
%多項式((λ-p1)(λ-p2))のパターン
eq2 = (lambda - p1)*(lambda - p2);
eq2 = collect(eq2,lambda)
coe2 = coeffs(eq2,lambda)
%--------------------------------------------
%方程式を指定したシンボリックに対して解く------------------
[k1,k2] = solve([coe1(1)-coe2(1),coe1(2)-coe2(2)],[k1,k2])
%----------------------------------------------------------
%k1,k2の関数内のp1とp2に指定の極を与えてそれに当てはまるk1,k2を求める---
K = subs([k1,k2],{p1,p2},{-8+4j,-8-4j})
%-----------------------------------------------------------------------
%Aclの固有値を求める----
eig(A+B*K)
%-----------------------
collect(方程式,シンボリック)
: 指定したシンボリックに関してべき乗で方程式内の係数をまとめる(今回の場合lambdaを指定しているのでlambdaのべき乗の式になる) >lambda^2 +(係数)*lambda のような形になる(デフォルトのシンボリックはx)coeffs(方程式,シンボリック)
: 指定した方程式のシンボリックの係数を次元の低いものから配列にして返す(通常みる多項式の後ろからということ)solve(数式,シンボリック)
: 数式について指定したシンボリックで解を求める(数式とシンボリック)を複数やる場合は対応するもの同士を同じ配列の場所に入れることで複数の解を求めることができるeig(行列)
: 行列の固有値を求める%ステップ1---------------------------
coe = poly(A) %特性多項式det(λI-A)の係数(高次から低次の順で返される)
a1 = coe(2); a0 = coe(3);
%------------------------------------
%ステップ2---------------------------
Mc = [a1 1;1 0] %正則行列Mcの計算
Vc = ctrb(A,B) %可制御行列の計算
%ステップ3---------------------------
Tc = inv(Vc*Mc) %可制御標準形への変換行列
%ステップ4---------------------------
p1 = -8+4j; p2=-8-4j;
Delta = conv([1 -p1],[1 -p2]) %多項式の計算(因数分解されたものの展開)
d1 = Delta(2); d0 =Delta(3);
%------------------------------------
%ステップ5---------------------------
Kc = [a0-d0 a1-d1]
K = Kc*Tc
%A+B*Kの固有値を
eig(A + B*K)
%-----------------------------------
poly(行列)
: 引数に行列を与えた場合、特性多項式(|λI-A|)の係数を返す=>λ2+係数*λのような形(λの先頭の係数から返されるため今回の場合先頭のλ2の1から順に返される) 順番は高次から低次となっているinv(行列)
: 行列の逆行列を求めるconv(配列, 配列)
: 畳み込みおよび多項式の乗算をする(多項式の分配法則的なこと) 配列には計算をする多項式の係数が入った配列を与えるA = [-3 1;2 -2];
B = [2;0];
p = [-8+4j;-8-4j];
K = - acker(A,B,p)
eig(A+B*K)
acker(A,B,p)
: 1入力システムのみ対応 A,B行列と指定したい極pを配列で渡すA = [0 1 0 0; -1 -1 1 1; 0 0 0 1;2 2 -2 -2];
B = [0 0 ;1/2 0; 0 0; 0 1];
p(1) = -2; p(2) = -2;
p(3) = -4; p(4) = -4;
K = -place(A,B,p)
eig(A+B*K)
place(A,B,p)
: 多入システムに対応 基本的にackerと同じ基本的にacker
とplace
で極配置できるという認識でOK
行列などで複数の係数行列を求めるときに便利
%(sI-A)^-1 の係数行列を求めるのを目標とする
A = [0 1; -10 -11]; %ここは任意でOK
syms s %ラプラス演算子sを定義
p = eig(A); %Aの固有値を求める
p1 = p(2)
p2 = p(1)
I = eye(2) %2×2の単位行列を作成
Q = inv(s*I - A) % (s*I -A)の逆行列を求める
%ヘビサイド
eq1 = simplify((s-p1)*Q); %(s-p1)Q(s)を簡略化=>分母分子の共通因子を約分
eq2 = simplify((s-p2)*Q); %上記と同じ
K1 = subs(eq1, s, p1) %eq1のsにp1を代入する
K2 = subs(eq2, s, p2)
注意 上記の作業でK1などの値が分数で表示された場合
double(K1)
とすることで小数表示にできる
eig(行列)
: 行列の固有値を求めるeye(数値)
: 数値×数値の単位行列を作成するinv(行列)
: 逆行列を求めるsimplify(数式)
: 約分をするsubs(シンボリック式, 代入させる変数, 代入する値)
: シンボリック式の変数に値をいれて計算するdet(行列)
: 行列式を求めるfactor(数式,シンボリック)
: 因数分解をする => シンボリックのところには対応する変数を入れる(デフォルトはx)expm(行列)
: 行列の部分には基本的にA*t
だがtにシンボリックを使用することもできる
注意
シンボリックを使用してsubsで計算した場合複素数表記になってしまう問題がある
A = 行列
syms s
exp_At = ilaplace(inv(s*eye(2)-A)) %ラプラス変換で求める方法を利用する
注意
この方法を利用してもsubsの計算がされない問題があるので注意する
パターンとして零入力応答,零状態応答,任意の時間応答を求める方法
initial(状態空間表現,初期値,時間配列)
: 零入力応答のグラフをplotする 状態空間表現はssで作成したも、初期値は縦行列(状態変数),tは配列を0:0.01:5
のような感じで作成したものy=initial(上記と同じ)
: yに時間応答の値を代入するstep(状態空間表現,時間配列)
: 単位ステップ応答のグラフをplotする => initialと同じでyに代入も可能impulse(状態空間表現,時間配列)
: インパルス応答のグラフをするをplot => yに代入可能lsim(状態空間表現,入力値,時間配列,初期値)
: 入力値は時間配列と同じサイズの配列にする必要があるため別で入力値の配列を作成するeig
を利用して固有値を求め,実部がすべて負なら漸近安定zpk
を利用して極零点をだし、極がすべて負ならBIBO安定ss(A,B,C,D)
: ss関数に各行列を与えることで状態空間表現を作成できる[A,B,C,D] = ssdata(状態空間表現)
: ssdata関数を使用することで係数行列を取り出すことができるtf(状態空間表現)
zpk(状態空間表現)
: こちらは零極ゲインの形になっているものに変換する
上記の操作後は古典制御でのtfやzpkの使いかたでOKss(伝達関数表現)
: この変換で得られるものは可制御標準形ではない[numP,denP] = tfdata(伝達関数表現)
[A, B, C, D] = tf2ss(numP,denP)
ss_P = ss(A,B,C,D) %tf2ssで作成した行列から状態空間表現を作成する
%ここまでだと可制御標準形と状態空間表現の要素の順番が逆になっている
T = [0 0 1; 0 1 0; 1 0 0]
ss_Pb = ss2ss(ss_P,T) %状態空間表現の変換
%ここで伝達関数表現から可制御標準形を求めることができた
使用した関数
tfdata()
: 伝達関数から分子要素分母要素を取り出すtf2ss()
: 伝達関数表現(の分子分母要素)から状態空間表現の各行列を求めるss2ss()
: 状態空間表現を変換する 第二引数には変換行列を与えるss(状態空間表現,'min')
: 通常の状態空間表現から最小実現の状態空間表現を求めるss_P = ss(A,B,C,D) %通常と同じように行列から状態空間表現を作成する
ss_P = ss(ss_P,'min') %最小実現の状態空間表現を得る
時間配列と、値のデータ配列から時間付き構造体を作成する
timeseries(値データ配列,時間配列)
: これで時間付き構造体になったものが返される上記で作成したデータを.mat
形式で保存する場合
save('保存するファイル名.mat','保存する時間付き構造体')
: 左のような関数を実行することで保存することができるsave('保存するファイル名.mat','変数1','変数2',...,'変数n')
bode(伝達関数)
: でボード線図を作成できる
bode(伝達関数,周波数範囲)
: 周波数範囲は w = logspace(-2,2,100)
のように
指定する. 今回の場合 -2 ~ 2 なので 10^-2 ~ 10^2 の範囲となる[Gg,Gp] = bode(伝達関数,周波数範囲)
: Ggの方にゲイン特性,Gpの方に位相特性が入る
その後の表示方法はfigure(1); semilogx(周波数範囲,20*log*10(Gg(:,:))); %ここでゲイン特性(dB表示)をグラフ1に描画
figure(2); semilogx(周波数範囲,Gp(:,:)); %ここで位相特性をグラフ2に描画
[Gg,Gp] = bode(伝達関数の分子要素,伝達関数の分母要素,周波数範囲)
: 以上のコマンドでもGg,Gpを求めることが可能lsimでsin波を指定すればOK
定常値はbodeを使用して公式の式にその値を使用することで求められる
sysP = tf(numP,denP); %伝達関数の作成
w = 2; %入力周波数の設定
t = 0:0.01:20; %時間の設定
[Gg,Gp] = bode(sysP,w);
Gp_rad = Gp*pi/180 %位相差の単位を[deg]から[rad]へ
%入力に対する出力y(t)の定常値yapp(t)の作成----
yapp = Gg * sin(w*t + Gp_rad);
%---------------------------------------------
plot(t,yapp) %定常値のグラフを表示
u = sin(w*t);
lsim(sys,u,t) %lsimを利用した任意の入力に対する時間応答のグラフを出力
ポイント
同じグラフに表示させたい場合
hold on
を使用することでこの後に出てくるグラフ出力は同じグラフに描画される
hold off
を使用することでhold on
の機能を切ることもできる
[Mp,i] = max(ゲイン特性)
: ゲイン特性にはbodeで求めたものを使用する
Mpには共振ピークの値,iにはbodeで使用した周波数配列のインデントの番号が入る
sysP = tf(numP,denP)
w = logspace(-1,1,10000) %周波数wの指定
[Gg,Gp] = bode(sysP,w)
[Mp, i] = max(Gg) %Mp:共振ピーク i:周波数配列のインデントが入る
wp=w(i); %wp : 共振周波数
nyquist(伝達関数)
: これでナイキスト軌跡のグラフが表示される
結合させる伝達関数を
sysP1 = tf([1],[1 3 2])
sysP2 = tf([1],[10, 1])
とする
sysP1 * sysP2
sysP1 + sysP2
または、 sysP1 - sysP2
feedback(sysP1, sysP2)
=> 分子がsysP1 分母が1+sysP1*sysP2となるコントローラーを
sysC = 2
制御系の伝達関数を
sysP = tf([5],[1 2 2])
とする
feedback(sysP*sysC, 1)
feedback(sysP, sysC)
1 - Gyr(s)
または feedback(1,sysP*sysC)
- Gyd
laplace(f,var,transVar) : ラプラス変換をする
f -> シンボリック式、シンボリック関数、あるいはシンボリック式な関数のベクトルor行列
var -> 独立変数を表すシンボリック変数(default:t) 時間変数のこと
transVar -> 変換変数を表すシンボリック変数またはシンボリック式(default:s)ラプラス演算子
ilaplace(F, var, transVar) : 逆ラプラス変換をする
F -> 上記のラプラス変換のfと同じ
var -> ラプラス演算子を表すシンボリックのこと(default:s)
transVar -> 時間変数(default:t)
伝達関数のために行列の要素ごとの配列を作成し、tfで伝達関数を作成したが、その伝達関数をそのままlaplaceに代入することはできないので注意が必要
対処法
分子要素をnumY , 分母要素をdenY とする
ex1)逆ラプラス変換をtfに対してらくにする
new_numY = 0;
syms s;
for i = 1:length(numY)
new_numY = new_numY + numY(i)*s^(length(numY)-1);
end
%上記の作業でnew_numYにシンボリック関数として伝達関数の分子要素が保存された
%同じ作業をdenYにも行いnew_denYを作成
ilaplace(new_numY/new_denY)
ex2)逆ラプラス変換の結果から値を代入し、グラフを作成したい
逆ラプラス変換の結果をsysPとする
T = 0:0.01:10; %時間の値
data_sysP = subs(sysP, t, T);
%上記の作業でsysP内の時間変数tを実数Tで置き換える
plot(T,data_sysP)
%これでグラフ表示完了
ex3)ex2とは違う方法で逆ラプラス変換の結果からのグラフ作成
func_sysP = symfun(sysP, [t])
%上記の作業で逆ラプラス変換の結果がtを引数にする関数にできる
data_sysP = func_sysP(T);
plot(T,data_sysP)
%これでグラフ表示完了
residue(分子係数,分母係数) : 部分分数分解の結果を分子要素と分母要素で返してくれる
ex)
numY = [4 5]; denY = [1 3 2];
[k p] = residue(numY, denY)
k -> 分子の要素k
p -> 分母要素p (なので実際の式は(s-p)となる)
重解の累乗が小さい方(1乗->2乗->...)から返される
分母要素のpは同じ値が返ってくる
ex) k_12/(s-p_1) + k_11/(s-p_1)
の場合に上記の例のように [k p] = residue()
した場合
k = [k_11, k_12]
p = [p_1, p_1]
といった形で値が返ってくる
impulse() : インパルス応答を得ることができる 引数には基本的にtfやzpkで作成した伝達関数
t = 0:0.01:10
などで作成し、その範囲のインパルス応答を得るstep() : ステップ応答を得ることができる. 使用方法は上記のimpulse()
と同じ
lsim() : 任意の入力に対しての応答を得ることができる
lsim(sys1, 'y:', sys2,'g--',u,t,x0)
ex1)
numP = [4,8];
denP = [1,2,-15,0];
sysP = tf(numP,denP)
>>>
sysP =
4 s + 8
------------------
s^3 + 2 s^2 - 15 s
ex2)
s = tf('s');
sysP2 = (4*s + 8)/(s^3 + 2*s^2 - 15*s)
>>>
sysP2 =
4 s + 8
------------------
s^3 + 2 s^2 - 15 s
逆に伝達関数が与えらており、その分子要素、分母要素が知りたいとき
%伝達関数をsysPとする
[numP, denP] = tfdata(sysP, 'v') %分子、分母の順で返される
ex1)
z = [-2]; %零点
p = [-5 0 3]; %極
K = 4; % ゲイン
sysP3 = zpk(z,p,K)
>>>
sysP3 =
4 (s+2)
-------------
s (s+5) (s-3)
上記の二つを利用してtfで作成した伝達関数をzpkの中に入れることで極、零点表現した伝達関数に変換できる