今回はプログラミング言語JuliaでPI制御を実装してみます。練習のため制御関係のパッケージは使用せず、一から実装してみました。 例題は下記書籍のものになります。
- 作者: Philipp K. Janert,野原勉,星義克,米元謙介
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/07/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (5件) を見る
この本にはPythonのシミュレーションコードが付属されているため、それを参考にしながらJuliaに書き換えました。PythonコードではClassを多用していますがJuliaには該当するものがないため関数のみで使用しています。Pythonコードはgithubにもあげられています。
例題の内容
- 下流の処理工程へ部品を流すシステムを考える
- 下流工程のシステムは部品のバッファを持っている
- 下流工程のシステムは時間ごとにバッファ中の部品に対して必要な数を処理する。処理された部品はバッファから取り出される。
- 予備プールに部品を投入することができる。そこから部品が適宜バッファに移される。
- バッファから処理された部品数、および予備プールからバッファへ移される部品数はランダムに変動する
- 常にバッファの部品数を一定としたい。そのために予備プールの部品投入数を調整する。
バッファの部品数を参照し、その値が目標値に近づくように、PI制御で部品投入数を調整してやります。 今回、バッファーの部品数の目標値はあるステップごとに変動させてみます。
Juliaでの実装
Juliaで実装した場合以下のようになりました。 変数のスコープの関係でエラーが頻出して応急処置的に修正を繰り返したコードですので大変非効率的なものに仕上がっていると思います。
using Plots u = 0 #部品供給数初期値 wip = 0 #予備プールの部品数 que = 0 #バッファーの部品数 max_wip = 50 #予備プールへの最大投入数 max_flow = 10 #下流工程への処理速度の最大値 kp = 1.25 #比例ゲイン ki = 0.01 #積分ゲイン tm = 1000 #シミュレーション時間 ie = 0 #誤差積算値初期値 er = 0 #誤差初期 function work(u) #予備プールへの部品供給 u = max(0,u) u = min(u,max_wip) global wip = wip + u # 予備プールからバファーへの部品移動 r = rand( 0:wip) wip = wip - r global que = que + r # バッファーから下流工程への部品移動 r = rand( 0:max_flow) r = min(r,que) que = que - r return que end # PDコントローラー function PI(er) global ie = ie + er return kp * er + ki * ie end #目標値の変更 function setpoint(t) if t < 100 return 0 elseif t < 300 return 50 else return 10 end end #ループの実行 # 空の配列の作成 r_ = zeros(tm + 1) er_ = zeros(tm + 1) u_ = zeros(tm + 1) y_ = zeros(tm + 1) for t in 0:tm global er r = setpoint(t) u = PI(er) y = work(u) er = r - y r_[t+1] = r er_[t+1] = er u_[t+1] = u y_[t+1] = y end plot([0:tm],[y_,r_],title="kp=1.25 ki=0.01",label=["y","setpoint"])
これを実行すると以下のようなグラフなります。 目標値の変動に対してPI制御である程度追随できていることがわかります。
また比例ゲイン、積分ゲインの値を入れ替えたのが下のグラフになります。
今回はここまでにします。