メインコンテンツ

S-Function Builder の API を使用した S-Function の作成

この例では、外部 C コードを統合してコンフィギュレーションの仕様から S-Function を生成するように、S-Function Builder ブロックをプログラムで構成する方法を示します。この例では、バネとダンパーにつながれた質量の位置と速度を C コードで計算します。マス-バネ-ダンパー系は一連の離散状態の微分方程式を使用して表されます。

モデルの設定

このセクションでは、モデル sfcnbuilderapi を作成して構成する方法を示します。この例を初めて実行するときは、new_system 関数を使用してモデルを作成します。

ただし、モデルが作業フォルダー内に既に存在する場合は、新しいモデルを作成する前に、コマンド ラインで clear mex を実行してから delete sfcnbuilderapi.slx mySFcn.mexw64 を使用します。また、前の MATLAB® セッションのモデルが開いている場合は閉じます。

mdl = "sfcnbuilderapi";
new_system(mdl);

S-Function Builder ブロックを追加します。

add_block('simulink/User-Defined Functions/S-Function Builder',[gcs,'/S-Function Builder']); 

ブロック ハンドル blk を取得します。このブロック ハンドルは S-Function Builder ブロックを構成するために使用します。

blk = getSimulinkBlockHandle('sfcnbuilderapi/S-Function Builder');

S-Function Builder ブロックの構成

S-Function Builder ブロックの構成では、S-Function を設定し、状態とパラメーターを追加して、S-Function Builder ブロックのビルド オプションを設定します。

S-Function の設定

S-Function の名前を mySFcn に設定します。

Simulink.SFunctionBuilder.setSFunctionName(blk,'mySFcn');

ブロックの設定を指定します。コードの配列レイアウトは列優先、サンプル モードは離散、サンプル時間は 0.1 秒です。

Simulink.SFunctionBuilder.setSettings(blk, ArrayLayout= "Column", SampleMode="Discrete", SampleTime= 0.1, DirectFeedthrough=true, CodeReuseSupport = false);
Simulink.SFunctionBuilder.setTargetLanguage(blk,'c');

S-Function Builder ブロックの状態とパラメーターの追加

状態と速度の 2 つの離散状態を追加します。

 Simulink.SFunctionBuilder.add(blk,'DiscreteState', InitialCondition="1"); %% Position
 Simulink.SFunctionBuilder.add(blk,'DiscreteState', InitialCondition="0"); %% Velocity

離散時間でのマス-バネ-ダンパー系の状態空間表現は次のとおりです。

x[k+1]=Ax[k] + Bu[k] 

y[k]=Cx[k]+D[k]

ここで、ベクトル x[k],u[k]y[k]kth の時間における状態、入力、出力のベクトルです。

この例では、質量は 3.6 kg、バネ定数は 400 N/m、減衰係数は 10 N-s/m です。このワークフローでは、システム行列 (A) と入力配列 (B) の値はc2d (System Identification Toolbox)関数を使用して取得されます。

パラメーター値を追加します。

Simulink.SFunctionBuilder.add(blk,'Parameter', Name = "A", DataType= "double", Value  ="[0.5369  0.07204; -8.004   0.3368]");
Simulink.SFunctionBuilder.add(blk,'Parameter', Name = "B", DataType= "double", Value  ="[0.001158; 0.02001]");
Simulink.SFunctionBuilder.add(blk,'Parameter', Name = "C", DataType= "double", Value  ="[1  0]");
Simulink.SFunctionBuilder.add(blk,'Parameter', Name = "D", DataType= "double", Value  ="0");

S-Function メソッドのコードの指定

出力コードを追加します。このコード セクションは S-Function の出力値を決定します。

OL = "y0[0]= C[0]*xD[0]+C[1]*xD[1]+D[0]*u0[0];";
Simulink.SFunctionBuilder.setUserCode(blk,"output",OL);

更新コードを追加します。このコードはシミュレーションの各タイム ステップにおける状態値を計算します。

U1 = "real_T tempX[2] = {0.0,0.0};" + newline + "tempX[0] = A[0]*xD[0]+ A[2]*xD[1]+ B[0]*u0[0];"+ newline + "tempX[1]= A[1]*xD[0]+ A[3]*xD[1]+ B[1]*u0[0];" + newline + "xD[0] = tempX[0];" + newline + "xD[1] = tempX[1];"; 
U1 = U1 + newline + "tempX[1]= A[1]*xD[0]+ A[3]*xD[1]+ B[1]*u0[0];" + newline + "xD[0] = tempX[0];" + newline + "xD[1] = tempX[1];";  
Simulink.SFunctionBuilder.setUserCode(blk,"update", U1);

S-Function Builder ブロックのビルド オプションの指定

この例では、ビルド ステップはログに記録されず、生成される MEX ファイルにデバッグ情報は含まれません。ただし、ShowCompileSteps の値を true に変更すると、ビルド ステップをログに記録できます。また、CreateDebuggableMEX の値を true に変更すると、生成される MEX ファイルにデバッグ情報を含めることができます。

Simulink.SFunctionBuilder.setBuildOptions (blk, "ShowCompileSteps",false,"CreateDebuggableMEX",false,"GenerateWrapperTLC",true);
Simulink.SFunctionBuilder.build(blk);
Generating 'mySFcn.c' ....Please wait
### Output folder is '/tmp/Bdoc25b_2988451_621513/tpc20de554/simulink_general-ex62441600' 
### 'mySFcn.c' created successfully
### 'mySFcn_wrapper.c' created successfully
### 'mySFcn.tlc' created successfully
Compiling 'mySFcn.c' ....Please wait
### S-function 'mySFcn.mexa64' created successfully

シミュレーション環境の構成

Source ブロックと Sink ブロックを追加します。

add_block('simulink/Sources/Step',[gcs,'/Input']); % Step block
add_block('simulink/Sinks/Scope',[gcs,'/Output']); % Scope block that displays the system response 
myScopeConfiguration = get_param('sfcnbuilderapi/Output','ScopeConfiguration');
myScopeConfiguration.OpenAtSimulationStart  = true;

S-Function Builder ブロックを基準にして入力ブロックと出力ブロックを配置します。

h = getSimulinkBlockHandle('sfcnbuilderapi/S-Function Builder');
pos = get_param(h,'Position');
pos = [pos(1)*2 pos(2)*2 pos(3)*2 pos(4)*2];
set_param('sfcnbuilderapi/S-Function Builder','Position',pos);

posStep = [pos(1)-200 pos(2) pos(3)-200 pos(4)]; %% Position of the Step block relative to the S-Function Builder block
set_param('sfcnbuilderapi/Input','Position',posStep);

posScope = [pos(1)+200 pos(2) pos(3)+200 pos(4)]; %% Position of the Scope block relative to the S-Function Builder block
set_param('sfcnbuilderapi/Output','Position',posScope);

S-Function Builder ブロックを Step ブロックに接続します。

srcIn = 'sfcnbuilderapi/Input';
dstIn = 'sfcnbuilderapi/S-Function Builder';
Simulink.connectBlocks(srcIn,dstIn);

S-Function Builder ブロックを Scope ブロックに接続します。

srcOut = 'sfcnbuilderapi/S-Function Builder';
dstOut = 'sfcnbuilderapi/Output';
Simulink.connectBlocks(srcOut,dstOut);

Model shows the S-Function builder block and the simulation environment.

開ループ モデルのシミュレーション

テスト環境を作成するには、入力端子 (u0) に Step ブロックを接続し、出力 (y0) を表示するために Scope ブロックを接続します。モデルをシミュレートし、システムに対する開ループのステップ応答を可視化します。

save_system ("sfcnbuilderapi")
outOL = sim("sfcnbuilderapi");

開ループ モデルから閉ループ モデルへの更新

コントローラーは、システムの整定時間を短縮する極を配置するためにplace (Control System Toolbox)関数を使用して設計されています。S-Function Builder ブロックのパラメーターを更新します。

Simulink.SFunctionBuilder.update(blk,"Parameter",Name="A",FieldToUpdate="Value",NewValue ="[0.8632  0.07103; -2.415 0.437]");
Simulink.SFunctionBuilder.update(blk,"Parameter",Name="B",FieldToUpdate="Value",NewValue ="[0.001117; 0.01973]");
Simulink.SFunctionBuilder.update(blk,"Parameter",Name="C",FieldToUpdate="Value",NewValue ="[1 0]");
Simulink.SFunctionBuilder.update(blk,"Parameter",Name="D",FieldToUpdate="Value",NewValue ="[0]");

閉ループ モデルのシミュレーション

sim コマンドを使用してモデルをシミュレートし、Scope ブロックを使用してステップ応答を可視化します。

outCL = sim("sfcnbuilderapi");
save_system("sfcnbuilderapi");

Step response to closed loop system.

close_system("sfcnbuilderapi",1);

参考

トピック