MATLABプログラミング Simulink基礎編(2)
前回にひきつづき、「パラメータを読み書きする」についてご説明します。
前回は、モデルやブロックのパラメータを読み書きする事が、Simulink向けMATLABプログラミングの基本ですよ、という事を確認しました。
その時に使うAPIとして、get_param, set_param をご紹介しましたが、そもそもパラメータ読み書きを行うにあたっては、大別して2種類の情報が必要です。
- どのブロック(モデル)に対して?
- どのパラメータを?
そこで今回は、これらをどのように指定するのかについて見ていく事にします。
どのブロック(モデル)を読み書きするか
前回、モデルのパラメータ「終了時間」を取得するにあたり、
>> get_param( ‘ex1_1′, ‘StopTime’ )
としました。
同様に、Constantブロックの「定数値」を取得するために、
>> get_param( ‘ex1_2/Constant’, ‘Value’ )
としました。
これらの第一引数 ‘ex1_1’ や、 ‘ex1_2/Constant’ は、いかにも「どのブロック(モデル)のパラメータを読み書きするか?」を指定しているっぽいですよね。確かにその通り!
確かにその通りではあるのですが、実はもうちょっとだけ奥が深かったりします。そこで今回は、そこのところを深く掘り下げ、よりキッチリと理解をしておきましょう。
モデルやブロックの指定方法(1)
モデルを指定する場合は、
‘モデル名’
と、モデル名を ‘ で囲って指定します。
ブロックを指定する場合は、
‘モデル名/ブロック名’
と、モデル名とブロック名を / でつなぎ、 ‘ で囲って指定します。
ここで出てきた / は、Windowsのディレクトリを区切る ¥ 記号と同じ意味を持ちます。
たとえば、「Constant」という名前のブロックが、「Subsystem」という名前のサブシステムに入っている場合、このConstantブロックを指定するには、
‘モデル名/Subsystem/Constant’
というようにします。Windowsのコマンドプロンプトで、ファイル名を指定するときと同じイメージですね。
演習3:サブシステム内のブロックのパラメータを読み込む
手順1
手順1:Simulinkモデルを作成し、ex1_3.mdl として保存する
結果1:ex1_3.mdl が生成されました
手順2
手順2:モデル ex1_3 上にConstantブロックを配置する
結果2:Constantブロックが配置されました
手順3
手順3:Constantブロックを左クリック(シングルクリック)し、Ctrl + G を2回押す
選択状態にしてから、 Ctrl+Gを2回
結果3:2階層のサブシステムが出来ました。「モデルブラウザーの切り替え」をクリックする事で、階層を確認できます
モデルブラウザーの切り替え
「Subsystem1」の中の「Subsystem」の中の「Constant」
手順4
手順4:MATLABコマンドウィンドウにて、get_paramコマンドを実行する
>> get_param( ‘ex1_3/Subsystem1/Subsystem/Constant’ , ‘Value’ )
結果4:Constantブロックのパラメータ「定数値」が取得できました
ふりかえり
モデル、ブロック、ともにWindowsのファイルと似たイメージで指定できる事を確認しました。ここでは get_param について確認しましたが、set_param でもまったくおなじです。
演習4:ちょっと変わった名前のブロックにアクセスする
手順1
手順1:Simulinkモデルを作成し、ex1_4.mdl として保存する
結果1:ex1_4.mdl が生成されました
手順2
手順2:モデル ex1_4 上にConstantブロックを配置する
結果2:Constantブロックが配置されました
手順3
手順3:先ほどのConstantブロックの名前部分をクリックし、ブロック名を変更します
名前変更中
ここでは芸能人風に、Cons☆tant としておきましょうか。
結果3:ブロック名が変更されました
手順4
手順4:MATLABコマンドウィンドウにて、get_paramコマンドを実行する
>> get_param( ‘ex1_4/Cons☆tant’ , ‘Value’ )
結果4:芸能人ブロック Cons☆tant の「定数値」パラメータが取得できました
手順5
手順5:先ほどのConstantブロックの名前部分をダブルクリックし、ブロック名を変更します
やっぱり☆はやりすぎですよね。ちょっと落ち着いて、Cons/tant としておきましょう。
結果5:改名が済みました
手順6
手順6:MATLABコマンドウィンドウにて、get_paramコマンドを実行する
>> get_param( ‘ex1_4/Cons/tant’ , ‘Value’ )
結果6:エラー発生!?
ふりかえり
手順6ではエラーが発生してしまいました。Cons☆tantはいいのに、Cons/tantはダメな理由・・・それは、/がサブシステム名の区切りに使われるからです。
今回の例でいくと、
ex1_4 にあるブロック Cons/tant なのか、
ex1_4のサブシステム Cons の中にあるブロック tant なのか、
区別がつきません。Simulinkは後者であると判断するため、コマンドは失敗してしまいます。
じゃあ、ブロック名に / が含まれていると、それに対して get_param, set_param は出来ないのでしょうか?
いいえ、そんな事はありません。実は、モデルやブロックを指定するには、もう1つ方法があります。
モデルやブロックの指定方法(2)
これまで、モデルやブロックへは名前でアクセスしてきました。
さて、これらのモデルやブロック、実は「ハンドル」という値を持っています。これは、double型の数値で、全モデル、ブロックでユニークなIDになっています。
みんなみんな、ハンドルをもっている
ハンドルというのはあくまでIDなので、ブロックに変な名前がついていても関係ありません。さっそく確かめてみましょう。
演習5:ハンドルを取得し、使用する
手順1
手順1:Simulinkモデルを作成し、ex1_5.mdl として保存する
結果1:ex1_5.mdl が生成されました
手順2
手順2:モデル ex1_5 上にConstantブロックを配置する
結果2:Constantブロックが配置されました
手順3
手順3:MATLABコマンドプロンプトにて、ハンドルを取得します
>> h = get_param( ‘ex1_5/Constant’, ‘Handle’ )
結果3:ハンドルが取得できました
手順4
手順4:MATLABコマンドプロンプトにて、Constantの「定数値」を取得します
>> get_param( h, ‘Value’ )
第1引数のところがポイントです
結果4:定数値が取得できました
手順5
手順5:先ほどのConstantブロックの名前部分をクリックし、ブロック名を変更します
先ほどと同じく、Cons/tant とします。
結果5:ブロック名が変更されました
手順6
手順6:MATLABコマンドプロンプトにて、Constantの「定数値」を取得します
>> get_param( h, ‘Value’ )
第1引数のところがポイントです。ブロック名が変わっても、ハンドルは変わりません。
結果6:ぶじ、定数値が取得できました
ふりかえり
ハンドルは、get_param コマンドにて、パラメータ名 ‘Handle’ を指定する事で取得できます。今回はブロックのハンドルを取得しましたが、モデルのハンドルでも問題なく取得できます。
例
>> hModel = get_param( ‘ex1_5’, ‘Handle’ )
ブロック名と違って、ハンドルであれば変な名前のついたブロックでも問題なくアクセスできます。
さて、今回はハンドルを取得したあとでブロック名を変えました。当然の疑問として、「ねぇ、最初からブロック名に / が含まれていた場合はどうなるの?」と思われるかも分かりません。
実は、ハンドルを取得するには get_param 以外にもう1つあるのです。そちらであれば、最初からブロック名に / が含まれていても大丈夫です。その方法については、次々回(か、もうちょっと後)にご説明します。
待斬内蔵!という方は、find_system をどうぞ。
(ちょっと調べてみたら、待斬内蔵って中部圏ローカルネタなんですね。。。)
名前 vs ハンドル
名前によるアクセスと、ハンドルによるアクセス。それぞれメリット・デメリットがあります。
名前によるアクセスのデメリット
今回確かめたように、名前に / が含まれていると get_param, set_paramに失敗してしまいます。
プログラミングをする事を考えるときに、「名前に / が含まれているか?」をいちいち気にしないといけないのは大いなるデメリットです。ハンドル方式であれば、そういった心配は一切無用でプログラムを組めるため、エラー軽減&コードのシンプル化に役立ちます。
ハンドルによるアクセスのデメリット
実は、ハンドルというのはMATLABを立ち上げなおすたびに変わってしまいます。そのため、ハンドルの値をファイルに保存しておいて、後から利用するという事が出来ません。
もう1つ。ハンドルというのは便宜上 double 型を取っていますが、数値そのものに意味はなくあくまでIDとして使用します。そのため、 sprintf コマンドでハンドルを一度文字列に変換して・・・という事をしようとすると精度の問題から失敗します。
sprintfを使いたくなるのは、あるプログラムから別のプログラムを自動生成しようとした時です。(めったにないと思われるかも分かりませんが、意外と使う機会があるのです。)
失敗するコード例:sprintfにハンドルを渡した時点でアウト
(ここで、hはConstantブロックのハンドルとします)
>> cmd = sprintf( ‘get_param( %f, ”Value”)’, h )
>> eval( cmd )
まとめ
今回も、「パラメータを読み書きする」とはどういう事か?について確認をしました。すなわち、
- モデルやブロックを指定するには、「名前」による方法と、「ハンドル」による方法がある
- 「名前」による方法は、イレギュラーな名前をもつブロックに弱い
- 「ハンドル」はMATLABを立ち上げなおすたびに変わってしまう
次回
ホントは「どのパラメータを?」まで一気に片づけるつもりをしていましたが、ちょっと長くなりすぎました。これは次回やります。
前稿コメントの続きです。
大変参考になります。
説明の仕方も上手ですね。うまい回避方法を提示しつつ、その際に生じる疑問にもきちんと答えてらっしゃる。
これまでsimulinkは使いづらいと思っていましたが、これで少し突破口が見えた気がします。
前の記事に引き続き、コメントありがとうございます。お褒めの言葉をいただきますと、元気が出ます。多少なりともお役に立てたのでしたら幸いです。