MATLAB/Simulinkでルートレベルの入力ポートへMATLABのスクリプトから入力を与える話

はじめに

若干マニアックな話ですが、MATLABスクリプトでSimulinkモデルの入力信号を生成して、シミュレーション結果を得たい場合があります。あまり良くある使い方ではないのかあまりわかりやすい例がなく、苦労したので書いてみます。この例はMATLAB R2020bで動作確認しています。

Simulinkモデルの読み込み

まず始めに、シミュレーションに使うSimulinkモデルを読み込みます。今回はARCH-COMPのベンチマークの中の、オートマチックトランスミッションコントローラーのモデル (以下 ATモデル) を使います。

mdl = 'Autotrans_shift';
load_system(mdl);

入力信号の定義

次にATモデルへ与える入力信号を定義します。ATモデルの入力はスロットルとブレーキの二次元信号です。

今回作る信号は制御点が3つで、サンプル間の時間は10.0秒で等間隔の信号とします。

numberOfSamples = 3;
signalStep = 10.0;
timeVector = (0:(numberOfSamples-1)) * signalStep;

入力値は以下の様に、最初はブレーキが最大で次にスロットルが最大の信号とします。

throttleValues = [0, 100, 100];
brakeValues = [325, 0, 0];

これらの値を元にtimeseriesオブジェクトを定義します。

throttleInput = timeseries(throttleValues, timeVector);
brakeInput = timeseries(brakeValues, timeVector);

上記のtimeseriesを組み合わせてSimulink.SimulationData.DataSetを作ります。

ds = Simulink.SimulationData.Dataset;
ds = ds.addElement(throttleInput, 'throttle');
ds = ds.addElement(brakeInput, 'brake');

Simulinkに定義した信号をExternalInputとして与えます。

set_param(mdl, 'LoadExternalInput', 'on');
set_param(mdl, 'ExternalInput', 'ds');

シミュレーションの実行

信号を定義したので、シミュレーションを実行します。

実行時間を30秒と設定します。

in = Simulink.SimulationInput(mdl);
in = in.setModelParameter('StopTime', '30.0');

実行結果の保存方法について設定を行い、シミュレーションを実行します。

in = in.setModelParameter('SaveOutput', 'on');
in = in.setModelParameter('OutputSaveName', 'yout');
in = in.setModelParameter('SaveTime', 'on');
simOut = sim(in);

実行結果のプロットは以下の様に行います。

plot(simOut.tout, simOut.yout(:, 1));

結果

シミュレーションの結果をプロットすると以下の様になります。

入力信号をちょっと変えて、最初からアクセルをかける様にすると次の様になります。出力信号が変化したのがわかると思います。

例の全体像

最後に今回の例の全体像は以下の様になります。

%% AT modelを読み込む
mdl = 'Autotrans_shift';
load_system(mdl);

%% 入力信号を定義する
numberOfSamples = 3;
signalStep = 10.0;
timeVector = (0:(numberOfSamples-1)) * signalStep;
throttleValues = [0, 100, 100];
brakeValues = [325, 0, 0];
throttleInput = timeseries(throttleValues, timeVector);
brakeInput = timeseries(brakeValues, timeVector);
ds = Simulink.SimulationData.Dataset;
ds = ds.addElement(throttleInput, 'throttle');
ds = ds.addElement(brakeInput, 'brake');
set_param(mdl, 'LoadExternalInput', 'on');
set_param(mdl, 'ExternalInput', 'ds');

%% シミュレーションを実行する
in = Simulink.SimulationInput(mdl);
in = in.setModelParameter('StopTime', '30.0');
in = in.setModelParameter('SaveOutput', 'on');
in = in.setModelParameter('OutputSaveName', 'yout');
in = in.setModelParameter('SaveTime', 'on');
simOut = sim(in);
plot(simOut.tout, simOut.yout(:, 1));