MATLAB R2009b新機能(2)

前回の続きです。

R2009bで追加された機能のうち、「モデル実行中に、サイズが変化する信号線」について纏めてみます。

モデル実行中に、サイズが変化する信号線

概要

Simulinkモデルには、ブロックとブロックをつなぐための信号線があります。

この信号線は、見た目は1本の線です。

r2009b_sig_00

図1 信号線に、データが1つ

ところが、この中にデータがいくつか入っている場合があります。

r2009b_sig_01図2 信号線に、データが3つ

この信号線に、いったいいくつのデータが入っているのか?これは、モデル開始時までは確定しません。

言い換えれば、モデル開始時には確定していたのです。

この、「いったいいくつのデータが入っているのか?」を、信号線の次元、と呼ぶ事にしましょう。

R2009bでは、いったんモデル開始時に次元を確定しつつも、モデル実行中に次元が変化するようになりました。

さて・・・どうしてこんな機能が入ったのか良く分かりません。こういうのは大概、だれか大口顧客からの要望によって入れられるものです。誰が何のためにこの機能を使うのでしょうか・・・?

自動車の制御モデルで、こんなことする理由は無いと思います。ましてや、プラントモデルでこういう事をしたい、という理由は思いつきません。

私のせまい経験から思いつくのは、無線通信アルゴリズムくらいです。

無線通信というのは、電波がビビビっと飛んでくるやつです。そいつを掛け算したり足し算したり引き算したりすると、音楽になったり映像になったりします。

r2009b_sig_02図3 受信した電波からノイズを取り、それから復調する

ところが、無線というのは波ですから、発信元と受信先の「距離」が問題になります。放送塔からの距離によって、TV映りのいい地域とそうじゃない地域がありますよね?

んで、極力そういう影響を排除したいわけです。そこでどうするか?よくある方法が、アンテナを1つだけでなく、4つにする事です。4つもあれば、どれかは調子よく受信できるんじゃない?という話です。(本当はそんな単純じゃないですが、ここで詳しく書くと叱られそうです。今回の話題には関係ないので、まぁこんな感じと思って下さい。)

さて、飛んできた電波に対して、掛けたり足したり引いたりするんです。これを、1本のアンテナだけでやるか、4本のアンテナでやるか。これを動的に切り替えられると、こんな事が出来ます。

まず、開発するシステムには「1本のアンテナモード」と「4本のアンテナモード」があって、いつでも切り替えられるようにします。これをコード生成してDSPに焼いておくと、実地検証するときにスイッチ1つでモードが切り替えられて便利です。(最近はDSPを使わないで、Simulinkから直接HDLを生成する事もあります。)

そのためのアルゴリズムを開発するわけですが、1本あろうが4本あろうが、基本のアルゴリズムは一緒です。図3ではアンテナが1本だけですが、これのアンテナが4本あっても、「バンドパスフィルター」や「信号復調」のアルゴリズムは一緒です。

なのに、信号線の「次元」が違うというだけで、1つのブロックでは取り扱えません。従来のSimulinkでは、まったくおんなじ処理をするブロックを、1本のアンテナモード用と、4本のアンテナモード用それぞれ別々に配置しないといけません。

r2009b_sig_08図4 次元が違うだけで、中身はまったく同じブロックが並列に配置されている

しかし、R2009bの可変次元信号を使えば、1つのアルゴリズムブロックで、1本モード、4本モードどちらにも対応できます。実行中にモード切り替えスイッチをいじってもぜんぜん大丈夫!

ASK、PSK、QPSKなど復調方式が違う場合には、さすがにブロックを分ける必要があります(当然ですね)。しかし、アンテナ1本と4本の違いはSimulink側で吸収してくれる事になりました!やったね!

(あってるかどうか分かりません。あくまで個人的な予想です。)

使い方

こんなモデルを書いたとします。

r2009b_sig_03

図5 次元=1のブロックと、次元=3のブロックが
それぞれマニュアルスイッチに入力している

信号の次元に注目してください。上のConstantブロックは次元=1です。一方、下のConstantブロックは次元=3です。

では、Manual Switchの次元がいくつになるのかというと・・・3です。次元の大きいほうの入力に引きずられてしまっています。

このManual Switchを上に向けると、こうなります。

r2009b_sig_04図6 Manual Switchの出力は [ 1 1 1 ] になっている

1 1 1と、1が三つならんでいますね。もともとのConstantブロックは次元=1です。すなわち、1が1つだけです。しかし、下の次元=3のConstantブロックに引きずられて、次元=3にされてしまっています。

では、新しい可変次元信号を使ってみましょう。そのためには、Manual Switchのプロパティを変更する必要があります。

r2009b_sig_05図7 Manual Switchのプロパティ

図7で、「Allow different input sizes ( Results in variable-size output signal )」にチェックが入っている事を確認してください。これが、可変次元信号を有効にするための設定です。

これでモデルを実行すると、次のようになります。

r2009b_sig_06図8 次元=1の信号を採用

r2009b_sig_07図9 次元=3の信号を採用

図8と、図9のDisplayブロックの違いに注目してください。

図8では、数値が1つしか表示されていません。一方、図9では数値が3つ(=1 2 3)表示されています。

このように、動的に信号の次元が切り替えられる事ができるようになりました。

この可変次元信号の目印は、信号線の表示です。Manual Switchから出ている信号は、まるでLabViewの信号線みたいですよね?これが可変次元信号のサインです。

この可変次元信号を使用すれば、おなじアルゴリズムに対していろんな次元の信号を適用する事ができるようになります。

たとえば、Switchの入力ポート1には、アンテナを1本つなげます。そして入力ポート2には、アンテナを4本つなげます。すると、そこから先のアルゴリズムは全く同じものを使用できます。使う時に自由に切り替えられるのがうれしい所です。

S-Function

可変次元信号は、S-Functionでも利用できます。

mdlOutputs関数の中で使える関数に、

ssGetCurrentInputPortDimensions( , , );

というものが加わりました。これは、「現在の」信号次元を調べられるものです。

ですから、

  int i = 0;
  real_T *u = ssGetInputPortRealSignal( S, 0 );
  real_T *y = ssGetOutputPortRealSignal( S, 0 );
  int width = ssGetCurrentInputPortDimensions( S, 0, 0 );

  for( i = 0 ; i < width ; ++i )
  {
    *y++ = *u++;
  }

などとすることで、可変次元信号に対応できます。

TLCを書く時も同様で、 %<SLibGetCurrentInputPortDimensions(0, 0)> などとすると、入力ポートの「現在の」次元を取得できます。

まとめ

いろいろな次元の信号を、「Manual Switch」や「Switch」や「Multiport Switch」などを使って切り替える事により、ダイナミックに信号の次元が変化するようになりました。

この機能によって、これまでムダに複製していたブロックを1つに統合できる可能性があります。

ただし、自動車部品の制御モデルやプラントモデルに使い所があるか?というと、ちょっと微妙な気がします。