システムとモデリング

modelica, Julia, Design Structure Matrix, SysML, 他モデリング全般について。

JuliaでPI制御を実装する

今回はプログラミング言語JuliaでPI制御を実装してみます。練習のため制御関係のパッケージは使用せず、一から実装してみました。 例題は下記書籍のものになります。

エンジニアのためのフィードバック制御入門

エンジニアのためのフィードバック制御入門

この本にはPythonのシミュレーションコードが付属されているため、それを参考にしながらJuliaに書き換えました。PythonコードではClassを多用していますがJuliaには該当するものがないため関数のみで使用しています。Pythonコードはgithubにもあげられています。

github.com

例題の内容

f:id:Otepipi:20190405005745p:plain

  1. 下流の処理工程へ部品を流すシステムを考える
  2. 下流工程のシステムは部品のバッファを持っている
  3. 下流工程のシステムは時間ごとにバッファ中の部品に対して必要な数を処理する。処理された部品はバッファから取り出される。
  4. 予備プールに部品を投入することができる。そこから部品が適宜バッファに移される。
  5. バッファから処理された部品数、および予備プールからバッファへ移される部品数はランダムに変動する
  6. 常にバッファの部品数を一定としたい。そのために予備プールの部品投入数を調整する。

バッファの部品数を参照し、その値が目標値に近づくように、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制御である程度追随できていることがわかります。

f:id:Otepipi:20190405010144p:plain

また比例ゲイン、積分ゲインの値を入れ替えたのが下のグラフになります。

f:id:Otepipi:20190405010633p:plain

今回はここまでにします。