MATLABユーザーコミュニティー

MATLAB和Si万博1manbetxmulinkユーザーコミュニティー向け日本語ブログ

MATLAB函数ブロックを使いこなせ!

皆さんこんにちは。トレーニングエンジニアの遠藤と申します。
このブログでは”仿万博1manbetx真软件MATLABとをつなぐ”をコンセプトとして,主に技術的な内容について書いております。

今回フォーカスを当てていくのは,”万博1manbetx仿真软件MATLABとをつなぐ”機能の一つである“MATLAB函数ブロック”です。普段MATLABをメインで使用している方は,

  • MATLABで使っていたコードを仿真万博1manbetx软件でも使いたい!
  • ブロック線図で複雑な演算を作るのが苦手!

といった理由で,このMATLAB函数ブロックを使用する場面が多いのではないでしょうか。

この記事では,そんなMATLAB函数ブロックを使う上での主要なつまづきポイントとその解決策についてまとめていきたいと思います!

MATLAB函数ブロックとは

まず初めに,MATLAB函数ブロックについて簡単に説明します。MATLAB函数ブロックは、MATLABの関数を用いて動作を自分でカスタマイズすることができるブロックです。

MATLAB函数ブロックは,関数形式でブロックの動作を設定します。通常のブロックはダブルクリックするとブロックダイアログが開きますが,MATLAB函数ブロックの場合はMATLABの関数編集画面が開きます。

デフォルトでは入力をそのまま出力するような関数が設定されています。この関数を自分で編集していくことで,入力と出力の関係をカスタマイズできる,というわけです。

ちなみに,関数の入出力引数はブロックの入出力端子に対応してるので,関数の引数の数を変えると,ブロックの端子の数も変わります。複数の入出力が必要な場合は関数の引数を編集しましょう。

もっと詳しい使い方が知りたい方は,MATLAB函数ブロックのドキュメントもご確認ください。

MATLAB函数ブロックのつまづきポイント

MATLAB函数ブロックは,通常のMATLAB関数のようにブロックの動作を書くことができるため,特にメインでMATLABを使っている人は親しみやすいブロックかと思います。

しかし,MATLAB函数ブロックはあくまで仿真软件の機能の一万博1manbetxつですので,通常のMATLABの関数と使い勝手が異なる部分もあります。そのため,MATLABと同じような感覚でMATLAB函数ブロックを使っていると,思わぬところでエラーが発生してしまいます。

そこで,この記事ではMATLAB函数ブロックを使う際に特につまづきやすい4つポイントにフォーカスを当て,それぞれの解決策を解説していきます!

【つまづきポイント1】一部の関数が使えない!
【つまづきポイント2】過去の値が使えない!
【つまづきポイント3】ワークスペースの変数にアクセスできない!
【つまづきポイント4】配列サイズのエラーが出る!

【つまづきポイント1】一部の関数が使えない!

例えば,MATLAB函数ブロックで以下のような処理を書いたとしましょう。

函数y = myContrast (u)
我= imresize (u, [224224])
y = localcontrast(我);

imresize関数で画像データを224 x 224にリサイズしたあと,localcontrast関数で局所的にコントラストを強調するような処理です。一見問題なく動きそうですが,実際にモデルを実行すると……

関数的localcontrastはコード生成でサポートされていません。
関数“MATLAB函数”(# 36.51.67),行3列5:
“localcontrast (I)”

エラーが出てしまいました。これは,localcontrast関数がコード生成に対応していないことが原因です。

万博1manbetx仿真软件はシミュレーションを行う際にモデルから実行用のコードを生成します。そのため,MATLAB函数ブロック内でも,一部の関数を除いてコード生成に対応している関数しか使うことができません

しかし,場合によってはどうしてもコード生成対応外の関数をMATLAB函数ブロック内で使わなければならないこともあります。そういったときに使うのが,coder.extrinsicというコマンドです。

coder.extrinsicは、特定の関数をコード生成対象外にするコマンドです。これを使うことで、コード生成に対応していない関数でも MATLAB Functionブロック内で使用することができるようになります。

それでは,先ほどのコードで编码器。外在を使ってみましょう。

函数y = myContrast (u)
coder.extrinsic (“localcontrast”);
I = imresize (u, [224224]);
y = localcontrast(我);

coder.extrinsicでエラーの原因であった localcontrast 関数をコード生成対象外に指定しました。これでOK!……かと思いきや、

このコンテキストでは,関数の出力‘y’をmxArrayにはできません。既知のタイプをもつ出力変数を事前に初期化することを検討してください。

今度は別のエラーが出てしまいました。どうやら出力yが問題のようですが,何が原因なのでしょうか……?

実は,编码器。外在を使う際は,コード生成対象外に指定した関数から返ってくる値のデータ型やサイズを万博1manbetx仿真软件に明確に教えてあげる必要があるのです. cod。外在で指定された関数は仿真软件ではなくM万博1manbetxATLABで実行されるため,仿真软件はこの関数からどんな値が返ってくるか全く知りません。そのため,この状況でシミュレーションを行おうとしても,MATLAB函数ブロックから出力されるyがどんなデータ型でどれくらいのサイズなのかを判断できず,モデルの整合性が確認できないのです。

ではどうするかというと,エラーメッセージに書いてあるように,変数yを”初期化“してあげます。次のコードを見てください。

函数y = myContrast (u)
coder.extrinsic (“localcontrast”);
y = 0 (224“uint8”);
I = imresize (u, [224224]);
y = localcontrast(我);

2行目にyをuint8型の224 x 224のゼロ行列で初期化する処理を入れました。一見無駄な処理に見えるかもしれませんが,MATLAB函数ブロックにおいては非常に重要な処理になります。なぜなら,この行があることで,“loalcontrast関数から返ってくるyという変数は,uint8型の224 x 224の行列だ”ということを仿真软件が判断万博1manbetxできるようになるからです。実際,この初期化処理を入れることで,先ほどのエラーは発生しなくなります。

このように,编码器。外在を用いてコード生成対応外の関数を使う際は,変数の初期化を忘れないようにしましょう

小贴士:関数がコード生成に対応しているかどうかを調べるには吗?

既存のコードをMATLAB函数ブロックで使用する場合,使っている関数がコード生成に対応しているか確認する必要があります。

一番簡単なのは,とりあえず実行してみてエラーを見る,という方法です。一番手軽で原因もわかりやすいので,基本的にはこの方法で問題ないかと思います。ただし,規模の大きなモデルの場合は、実行ボタンを押してから MATLAB Function ブロックでエラーが出るまでに時間がかかってしまうため、実行する前に事前にコード生成対応しているか把握しておく方が効率的なこともあります。

こういった場合は,ドキュメントを使って確認する方法が有効です。

例えば,こちらのドキュメントに載っているコード生成対応関数リストを使うと,特定の関数がコード生成に対応しているか確認することができます。そのほかにも,それぞれの関数のドキュメントの下部に”C / c++コード生成対応”という表記があれば,その関数はコード生成に対応しています。

例:linspace関数のドキュメント。コード生成に対応していることがわかります。

また,一部の関数はコード生成のための制約が記載されていることもあります。

例:马克斯関数のドキュメント。入力引数の与え方に関する制約が記載されています。

特定の関数でコード生成関連のエラーが発生した場合は,何かの制約に引っかかってないかドキュメントで確認してみましょう。

注意点

coder.extrinsic使うと、一般的にモデルの実行速度は遅くなります。また,当たり前ですがcoder.extrinsicが含まれるモデルはコード生成することができません。そのため,実行速度がクリティカルに効いてくるモデルやコード生成を行う前提のモデルは,编码器。外在を使わず,コード生成対応の別の関数で代用する必要がありますので注意しましょう。

【つまづきポイント2】過去の値が使えない!

それでは次のつまづきポイントです。前のステップと今のステップの入力の平均を計算する処理をMATLAB函数ブロックで実装するにはどうすればいいでしょうか吗?

函数y = fcn (u)
y = (u_old + u) / 2;
u_old = u;

それっぽいコードを書いてみたものの,これではエラーとなります。通常のMATLAB関数と同様に,MATLAB函数ブロックの関数も実行ごとに変数がリセットされます。そのため,このままでは前のステップの入力を使うことができません。

このような場合に使用するのが,永続変数です。

永続変数は関数内で定義されていても実行後にリセットされず,値が残り続けます。これを使えば,過去の値を使って演算を行うことが可能です。先ほどのコードを,永続変数を使って書き換えてみます。

函数y = fcn (u)
持续的u_old
如果isempty (u_old
u_old= 0;
结束
y = (u_old+ u) / 2;
u_old= u;

まず,u_oldの前に持久と書き,u_old変数を永続変数に設定します(変数名が青緑色に変わります)。一度永続変数に設定してしまえば,以後u_old変数は関数の実行後も値がリセットされなくなりますので,前のステップの入力を保存しておき,次のステップで使う,といった芸当が可能になります。

しかし,ここで気を付けなければならないのは,永続変数には初回実行時に何も値が入っていないという点です。そのため,初回実行時のみ初期値を与えてあげる必要があります。そこで,さきほどのコードのように,一度isempty関数を用いて永続変数に値が入っているか確認し,入っていない場合は初期値を入れる,という処理を書く必要があります。この構文は永続変数を使う際に必ず書くものなので,セットで覚えておきましょう!

注意点

MATLAB函数ブロック内で使っている永続変数の値は,シミュレーションが終わってもメモリに保存されます。そのため,もう一度シミュレーションを行うと,前回の値が残ったまま実行されてしまいます。これを防ぐには,以下のようなコマンドをMATLABで実行し,永続変数をリセットします。

>>清晰的関数名%永続変数の名前ではないので注意!

何回もモデルを実行する際は,永続変数の値をクリアするのを忘れないようにしましょう。

【つまづきポイント3】ワークスペースの変数にアクセスできない!

MATLABでスクリプトを用いて計算を行う場合,あらかじめベースワークスペースに.matファイルなどに保存しておいたパラメータを読み込み,スクリプト内でそれを用いることが多々あります。しかし,通常のMATLAB関数と同様,MATLAB函数ブロックも直接ベースワークスペースの変数にアクセスすることはできません。

しかし,MATLAB函数ブロックのパラメータ——引数という機能を使用すると,ベースワークスペースの変数をMATLAB函数ブロック内でパラメータとして使用することができます。

パラメータ引数の使い方:

1.使用したいワークスペース上の変数と同じ名前の変数を,MATLAB函数ブロックの関数の入力引数に追加します(一時的にブロックの入力端子が増えます)。

2.エディタ上部の[データの編集]をクリックします。

3.先ほど追加した変数を選び,“スコープ”を”パラメータ”に設定します(ブロックの入力端子の数がもとに戻ります)

このようにしてパラメータ引数を設定することで,ベースワークスペースの変数をMATLAB函数ブロック内で使用することができます。ワークスペースの変数と同名の入力変数を設定しなければならない点に注意です。

注意点

よく勘違いされやすいのですが,シミュレーション中にベースワークスペースの変数を変更しても,MATLAB函数ブロック内のパラメータ引数の値は変わりません。なぜなら,万博1manbetx仿真软件はシミュレーション開始前にワークスペースの変数の値を確認し,それを固定値のパラメータとして使用するからです。また,その逆,すなわちMATLAB函数ブロック内からベースワークスペースの変数の値を変更することもできません。

どうしてもシミュレーション中にベースワークスペースの値を動的に参照したい,という場合は,evalinassligninなどの関数を编码器。外在と組み合わせて使いましょう(詳細は各関数のドキュメントをご確認ください)。

小贴士:使いたい変数が多すぎる場合!

パラメータ引数を使うとMATLAB函数ブロックからベースワークスペースの変数にアクセスすることができますが,必要な変数が多い場合,全ての変数に対してパラメータ引数を作成するのは大変です。

このような場合は,変数を1つの構造体にまとめてあげる方法が有効です。例えば,使いたい変数が”数据。垫”というファイルに保存されている場合は,

>> data = load(“data.mat”

とすることで.matファイル内の変数を数据という1つの構造体として読み込むことができますので,この数据変数をパラメータ引数に設定するだけですべての変数をMATLAB函数ブロック内で使用することができます。

ただし,MATLAB函数ブロック内では图オブジェクトなどの一部のデータ型の変数は使用できません。保存関数でワークスペースの変数をすべて.matファイルに保存した場合は構造体の中に対応していない変数が混入しやすいので注意しましょう。

【つまづきポイント4】配列サイズのエラーが出る!

以下のMATLAB函数ブロックの関数を見てみましょう。

函数y = fcn (u)
y = 0: u: 10 * u;

入力に応じてベクトルを作成して出力するようなコードです。一見問題なく動くように見えますが,モデルを実行するとエラーとなります。

“y”は可変サイズの行列と推定されますが,そのサイズは継承または固定として指定されています。“y”が調整不可なパラメーターで定義されていることを確認するか,(可変サイズ]チェックボックスを選択し,[サイズ]ボックスで上限を指定します。

今回エラーが発生してしまったのは,出力yのサイズを仿真软万博1manbetx件が判断できないからです。万博1manbetx仿真软件の信号のサイズは,基本的にシミュレーション前に決定されている必要があります。先ほどの関数を見ると,配列yの形が入力uの値に依存するようなコードになっていますね。このような場合,万博1manbetx仿真软件はシミュレーション前に出力のサイズを判断できないため,エラーになってしまうのです。

このエラーの解決方法は2種類あります。

方法1:配列サイズが判断できる形に変更する

実行したい演算によっては,表記を変更することで仿万博1manbetx真软件が配列サイズを推測できるようになります。例えば先ほどのコードは,一見uの値によって配列サイズが変化しそうに見えますが,実は配列サイズは必ず11になります。次のように書き換えるとそれが明確になりますね。

函数y = fcn (u)
y = (0:1:10) *

この形であれば,万博1manbetx仿真软件も出力信号のサイズが11だと判断することができるため,モデルはエラーなく実行されます。

このように,もし配列サイズが入力に依存しないはずなのに配列サイズに関するエラーが出てしまう場合は,より配列サイズが明確になるような形に変形できないか検討してみましょう

方法2:可変サイズに設定する

先ほど”万博1manbetx仿真软件では信号のサイズは基本的にシミュレーション前に決定されている”と書きましたが,例外もあります。それが可変サイズ信号です。可変サイズ信号はシミュレーション中にサイズが変更する信号です。

MATLAB函数ブロックの出力は,[データの編集]画面で”可変サイズ”にチェックを入れ,“サイズ”に上限サイズを設定することで,可変サイズ信号に設定することができます。

この設定を行うことで,MATLAB函数ブロックからの出力信号yは可変サイズ信号となり,シミュレーション中でサイズが変更できるようになります。

ただし,可変サイズ信号には多くの制約が存在します。例えば,可変サイズ信号のサンプル時間は離散である必要があります。制約はこちらのドキュメントにリスト化されていますが,多くのモデルに大きな影響を及ぼしますので,可変サイズ信号を用いるべきかどうかは慎重に検討必要があります

まとめ

今回はMATLAB函数ブロックを使う上で問題となる4つのつまづきポイントについてまとめました。“MATLAB函数ブロックのエラーが解決できなくて模型使うの諦めた…万博1manbetx…”という方は,この記事のつまづきポイントに引っかかってしまっているかもしれませんので,今一度モデルを見返してみてはいかがでしょか吗?

皆さんもうまくMATLAB函数ブロックを用いて,快適なモデリングライフをお送りください!

|

评论

要留下评论,请点击在这里以登录您的MathWorks帐户或创建一个新的帐户。