Matlab_Simulink:PIDゲイン最適化プログラム②_入力考慮(無料公開)

実現したいこと

  • Simulinkとmファイルを用いたPID制御シミュレータの構築
  • 上記プログラムのPIDゲインの最適化
  • fminsearchを使っての最適化
  • 過大な入力が印加されないような最適化

Matlabのバージョン

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

必要なtoolbox

ダウンロードURL

【ダウンロードリンク】

PID_Control_fmin_Input - Google ドライブ 

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

フォルダ構成

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

実行方法

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

Simulinkファイル(PID_fmin.slx)

mファイルソースコード(Main_PID_fmin_input.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]
% ===== 推定システムゲイン =====
K_hat = K; % fminsearchで偏差と入力の値のオーダーを一致させることに利用

%% fminsearch
ini_x = [0.5 0.5, 0.5]; % PIDゲインの初期値
[x, fval] = fminsearch(@(x) func_fmin_input(x,N_File,K_hat),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_input.m)

function f = func_fmin(x,N_File,K_hat)

%% 変数宣言
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); % 入力

 

%% 評価規範
% 入力の整定値u(end), K_hatを導入することで,偏差(r-y)と同じオーダーにする
 f = sum( ( r-y ).^2 ) + ( K_hat.*(u(end)-u)).^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 + \hat{K}(u_{final}-u(t))^2 )

このとき, \hat{K}は推定システムゲイン, u_{final}は入力の整定値である。偏差 (r-y)と入力のオーダーを揃えるために \hat{K}, u_{final}を導入している。

もし, \hat{K}を真値 Kの10分の1と見積もった場合( \hat{K}=0.1K)は下記のグラフが取得され,入力の変動が大きくなることを確認できる。

次回の記事では入力飽和がある場合について執筆予定である。

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

forfree.hatenablog.jp

forfree.hatenablog.jp

forfree.hatenablog.jp