LoginSignup
9
3

More than 5 years have passed since last update.

MATLABで簡単システム同定(簡易)

Last updated at Posted at 2018-10-23

データ取得

まずは適切な入力を作成して入出力のデータを得る。

Chirp信号作成

簡単に作れて,かつそこそこの同定をするならChirp信号を用いる。
simulinkのブロックはなんか挙動が思ったように行かなかったので,Mfunctionで作成。

Linearな信号で良ければ1行で作成可能。
下記wikipediaの記事を参照。
https://ja.wikipedia.org/wiki/%E3%83%81%E3%83%A3%E3%83%BC%E3%83%97%E4%BF%A1%E5%8F%B7

  • u: clockから得た時間
  • f0: 最小の周波数
  • f1: 最大の周波数
  • Tchirp: 一度のsweep時間
  • phi0: 初期位相(0でよさそう)

sin(phi0+2*pi*(f0*rem(u,Tchirp)+(f1-f0)/2/Tchirp*rem(u,Tchirp)^2))

こんなかんじ。rem関数を使って周期的な動作を可能にしているのがミソ。

解析

そんでもって得たデータをin,outとする。

以下のがその一例。
(https://qiita-image-store.s3.amazonaws.com/0/188863/1243447c-53d8-b6a2-4eee-6a1d2d42dfa3.png)

周波数応答の同定

freqは当然周波数だが,winsizeは得られたデータをどのサイズで窓関数に打ち込むかを与える。
感覚的にはTchirp*freqで良さそうだが,間違ってたら指摘してください。


[PXX,FREQ] = tfestimate(in,out,winsize,[],[],freq);
Txx = frd(PXX,FREQ*2*pi,1/freq);

2行目でFREQに2*piをかけているのはHzからradに変換する必要があるため。どこかパラメータ設定すればこんなことしなくて済んだ気もする。

ボード線図を引いて見ればキレイに表示されていることと思う。


Bode(Txx)

また,Coherenceを取得するのもコマンド一つで済む。

[COHER,cFREQ] = mscohere(in,out,winsize,[],[],freq);
semilogx(cFREQ,COHER);

coherenceが小さいほどあんまり信用できないデータということになる。

お手軽フィッティング&システム同定

invfreqsという関数を用いることで簡単にフィッティングができる。学生はmatlabに課金すべき。

コマンドの使い方は以下の通りで先程tfestimateで生成したPXXとFREQを用いる。(必要に応じてradに変換すること!)

[num den] = invfreqs(PXX,FREQ*2*pi,nd,dd,weight,iter)
  • 3,4番目のnd,ddは分子と分母の字数で1次/2次なら,1,2と綴る。![octave-online-line-30.png]
  • weightは重み関数である。Coherenceから作成するとスムース。
  • iterはイテレーション回数。大体10回やっておけばまぁまぁ近い値になる。

重み関数作り方例

周波数帯がminf~maxfの間の情報のみかつ,Coherenceが0.95以上の周波数応答を用いてfittingするとする。
こんなかんじに書ける。簡単でしょう。

weight = zeros(size(COHER));
weight(COHER>0.95) = 1;
weight(cFREQ >= fmax)= 0;
weight(cFREQ <= fmin)= 0;

Sample Code(バグあり)

今matlabが消えたPCでやってるので後でちゃんと内容を確認する。あとで。

%% simulation set
close all
freq = 1000; %1000hz

%% 0. Define system
% system (ground truth) 
sys = tf([0.6],[0.02,10]);
figure;bode(sys);

%% 1. read data and set in/out data example

% make chirp signals
time = 0:1/freq:10;
CHP=chirp(time,0.5,2,50);
out=lsim(sys,CHP,time);
in=CHP;

%%load('result.data');
%time = result(:,1);
%in = result(:,2);
%out = result(:,3);

figure(1); plot(time,in,time,out);
xlabel('time[s]')
ylabel('in[A]/out[rad/s]')
legend('In','Out')
grid on;

%% 2. Get bode plot with tfestimate
windowsize = 2000;% this is not nessesary
[PXX,FREQ] = tfestimate(in,out,windowsize,[],[],freq);
Txx = frd(PXX,FREQ,1/freq);

figure(2); 
%opt = bodeoptions('cstprefs');
%opt.PhaseWrapping = 'on';
%opt.PhaseWrappingBranch = -180;
%bode(Txx,opt);
bode(Txx);
title('Freq responce')

%% 3. Get coherence mscoherence
[COHER,cFREQ] = mscohere(in,out,windowsize,[],[],freq);

figure(3); semilogx(cFREQ,COHER);
title('coherent')
xlabel('Freq [Hz]')
%% 4. fitting1
% Chirp Sweep Range
fmax = 50;
fmin = 0.5;

% choose weight from coherence
weight = zeros(size(COHER));
weight(COHER>0.95) = 1;
% use only 0.5--50 Hz
weight(cFREQ >= fmax)= 0;
weight(cFREQ <= fmin)= 0;

% estimate transfer function !
[num den]=invfreqs(PXX,2*pi*FREQ,0,1,weight,10);

% figure;bode(tf(num,den));
fitsys = tf(num,den);

figure(4);bode(sys,fitsys);
legend('ground truth','Estimated')
xlim([fmin fmax])

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3