Matlab_Simulink:PIDゲイン最適化プログラム①(無料公開)

実現したいこと

  • Simulinkとmファイルを用いたPID制御シミュレータの構築
  • 上記プログラムのPIDゲインの最適化
  • fminsearchを使っての最適化

Matlabのバージョン

Matlab2021a
※ダウンロード形式として過去のバージョンも用意

必要なtoolbox

ダウンロードURL

【ダウンロードリンク】

PID_Control_fminsearch - Google ドライブ

※ご利用中のMatlabバージョンのフォルダをダウンロードしてください。
 例:2021aバージョンであれば,上記リンクの「2021a」を選択
※上記プログラムの利用で生じたトラブルは一切の責任を負いかねます

フォルダ構成

上記ダウンロードし展開。
(下記のようなフォルダ構成になっていることを確認)

実行方法

「Main_PID_fmin.m」を実行
※PCスペックに依って最適化計算に5分程度時間がかかります。

Simulinkファイル(PID_fmin.slx)

mファイルソースコード(Main_PID_fmin.m)

%% 初期化
clc         % コマンドウィンドウの初期化
clear       % ワークスペースの初期化
close all   % グラフを全部閉じる

%% 変数宣言
% ===== 制御対象 =====
K = 1;
A = 1;
B = 1;
C = 1;

% ===== 目標値 =====
r_val = 10; % ステップ状の目標値

% ===== Simulink関係 =====
N_File = 'PID_fmin.slx'; % simulinkファイル名
FinalTime = 30;     % シミュレーション終了時刻[s]
SamplingTime = 0.1; % サンプリング時間[s]

%% fminsearch
ini_x = [0.5 0.5, 0.5]; % PIDゲインの初期値
[x, fval] = fminsearch(@(x) func_fmin(x,N_File),ini_x);

%% Simulinkの実行
open(N_File);   % Simulinkを起動
sim(N_File);    % Simulinkの実行

%% グラフ化
% ===== Simulinkデータ格納 =====
t = ScopeData.time;                     % 時刻情報
y = ScopeData.signals(1).values(:, 1);  % 出力
r = ScopeData.signals(1).values(:, 2);  % 目標値
u = ScopeData.signals(2).values(:, 1);  % 入力

% ===== グラフ描画 =====
% ----- y -----
figure;
subplot(211);
plot(t,y);
hold on;
plot(t,r,'--');
grid on;
xlabel('$$ t {\rm [s]} $$', 'interpreter', 'latex');
ylabel('$$ y(t) $$', 'interpreter', 'latex');
legend('$$ y(t) $$', '$$ r(t) $$', 'interpreter', 'latex');
% ----- u -----
subplot(212);
plot(t,u);
hold on;
grid on;
xlabel('$ t {\rm [s]} $', 'interpreter', 'latex');
ylabel('$ u(t) $', 'interpreter', 'latex');

mファイルソースコード(func_fmin.m)

function f = func_fmin(x,N_File)

%% 変数宣言
Kp = x(1);
Ki = x(2);
Kd = x(3);

assignin('base','Kp',Kp);
assignin('base','Ki',Ki);
assignin('base','Kd',Kd);


%% Simulink実行
sim(N_File);

%% Scopeデータの取得
t = ScopeData.time;                     % 時刻情報
y = ScopeData.signals(1).values(:, 1);  % 出力
r = ScopeData.signals(1).values(:, 2);  % 目標値
u = ScopeData.signals(2).values(:, 1);  % 入力

%% 評価規範
f = sum((r-y).^2);

%% コマンドウィンドウ表示
fprintf('[Kp, Ki, Kd, fval] = %.3g, %.3g, %.3g, %.3g\n',Kp, Ki, Kd, f);

実行結果

まとめ・考察

今回の最適化評価関数 fは下記の通り。

【最小化する評価関数】
 f = \sum_{t=0}^{N} ( r(t)-y(t) )^2

したがって,入力 u(t)については全く考慮されていないため,目標値追従は実現するものの,過大な入力が印加されてしまい,現実的には利用できない。飽和(サチュレーション)を加えれば良いが,理論的ではなくなり個人的には美しくはないと感じる。入力 u(t)を上記評価規範に加えたPIDゲイン最適化については,また別の記事に執筆予定である。

併せて確認推奨の過去記事

forfree.hatenablog.jp

forfree.hatenablog.jp

forfree.hatenablog.jp