Simulinkで分散を求める(副題：Simulink.Signalの使い方)

# はじめに
[分散](https://jp.mathworks.com/help/matlab/ref/var.html)・[共分散](https://jp.mathworks.com/help/matlab/ref/cov.html)など、統計の基本的な処理はMATLAB標準で供えられおり、すぐに使うことが出来ます。初学者にとって非常に優しいですね。

これに対しSimulinkは、制御のためのブロックは豊富ですが統計のためのブロックはあまり見当たりません。（[DSP System Toolbox](https://jp.mathworks.com/help/dsp/mathematics-and-statistics.html)にならあるかも？）

これは単純に、Simulinkで統計的処理を行うことが一般的でないことが原因と思いますがどうしてもやりたい！というケースもあるとは思います。著者のケースとして、Simulink連携を利用して統計的処理をarduinoに実装するときに悩みました。

本記事では分散をSimulinkにて求める方法を紹介します、完成イメージは下記になります。
共分散については省略しますがやることはほぼ同じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/964263d4-00c8-c05e-f275-05280950f27f.png)

下記、MATLABのバージョンは2018bを使用します。

# Todo1.信号属性を指定する(最最重ポイント)
Simulinkの機能の一つに[Simulink.Signalによる信号属性の指定](https://jp.mathworks.com/help/simulink/slref/signal.html)があります。信号属性の指定は、Simlinkでよくやる単純な制御系シミュレーションのような場合はあまり使う必要がありません。

じゃあいつ使うかというと、ハードウェア実装を意識したシミュレーション、あるいは自動コード生成を利用する場合に使います。

指定できる信号属性としては、型の指定や上下限値の設定、そして次元の設定が出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/a6b2fe5f-ea4d-9ab0-d8ba-e22200e3ac5f.png)

次元は[1 N]で要素Nのベクトルを、[M N]でM×Nの行列を指定できます。
今回は信号属性をベクトルに指定、ベクトルに複数データを格納することで分散の導出を可能にします。

## で、どうやって信号属性を指定するか

### ①信号に名前を付ける
名前を付けたい信号をダブルクリックして任意の名前を付けましょう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/3a6cde4f-5772-4658-55d2-ba3b83d1716e.png" width=500>

### ②信号をSimulink.Signalに関連付ける
正攻法として、該当する信号を右クリック→プロパティを選択→信号名を~　で可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/c7af22a1-7542-8ef4-ae4f-c995ecb586c5.png)

<b>が、個人的なオススメは違います。</b>モデルデータエディタを使うのです。
[モデルデータエディターを使用したデータプロパティの設定]
(https://jp.mathworks.com/help/simulink/ug/inspect-and-configure-design-attributes-of-model-data.html)　概ね2017以降からの追加機能のようです。

起動はSimulinkのメニュー画面より行います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/91968b73-7436-4032-446e-81169cfa376c.png" width=300>

これの「信号」タブで、モデル内の各信号の設定を見ることが出来ます。
Simulink.Signalへの関連付けは右端の「<b>Resolve</b>」にチェックを入れることで行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/fb39add8-7974-d088-e5a3-ccabf58cf261.png)
なおデータエディタでは選択した信号がハイライトされます。非常に分かり易くてよいですね！
この画面から信号名を付けることももちろん可能です。


またSimulink.Signalへの関連付けが有効な信号にはフォークのような印が付きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/d30f3844-3d7f-1b7a-4014-73b0f4b3d30b.png)

### ③Simulink.Signalを作成する
色々なやり方がありますが、今回はモデルエクスプローラ経由での方法を書きます。
起動はSimulinkのメニュー画面より行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/34f0a453-beb6-7cfc-52f9-9d8dbffb3d7e.png)

信号っぽいアイコンをクリックすることでSimulink.Signalを作成できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/67c2730b-34d5-b9a4-cb21-d23408160a22.png)

名前は先程付けた信号名と一致させる必要があります。作成する場所はベースワークスペースとモデルワークスペースのどちらでも構いません。自分が分かり易いところにしておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/03519e67-93a0-b72e-5fa6-d40783f236ce.png)

データエディタに戻り更新ボタンを押すか、シミュレーションを実行することでSimulink.Signalの設定内容が対象信号の属性に反映されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/7c023181-afe8-82a6-18ae-25e2851d16e1.png)

信号属性の設定は以上になります。なお②と③は逆でも構いません。
設定方法は一度やれば理解できるものではありますが、やったことがないとちょっとしんどいので丁寧に書きました。（著者は何もない状態から始めたので結構手間取った）

# Todo2.ベクトルにデータを格納する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/e40476c6-7e4a-a830-71f4-507870aa6e27.png)
Simulink.Signalを用いて、上図xoutを1×200のベクトルに設定しました。データの格納はTriggerd Subsystem内にて行います。

トリガの立ち上がりごとに、ベクトルの末尾に新しいデータを追加するものとします。イメージは下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/085b9260-3b26-69e5-0cea-412812293525.png)

実装はSelectorとVector Concatenateを使います。後者はMuxでもOKかと思いきやエラーが出ました、マッピングできないとのこと。信号属性がベクトルであるが故のエラーですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/33a7c54e-86c5-f36a-4b5e-7bebbb172c79.png)

Selectorの設定は下記です。上図のイメージ通りの処理となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/1d3e5218-41b4-0270-06f0-0d18c7c20ea2.png)

微妙に注意すべき点として、ベクトルに対して「<b>外部信号を遅延して入力をラッチ</b>」の設定を有効にする必要があります。input2のポートに<b>Lo</b>と書いてあるのはこの設定が有効なためです。
設定はinput2のポートのプロパティにて行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/e5a17380-9697-d21e-6c8e-b2a08b5f4d2a.png)

なおラッチの代わりにUnit delayを使用したところエラーとなりました。

# Todo3. MATLAB functionにて分散を求める

```matlab
function y = fcn(x)
y = var(x);
```
<b>以上！</b>　超簡単ですね。

# 動作確認
[Random Numberブロック](https://jp.mathworks.com/help/simulink/slref/randomnumber.html)を入力とし、分散を変化させてみます。

分散１
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/6ab94954-ff72-a3c4-73c8-a16bb59672ea.png)

分散２
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/90ddd977-b880-f3e4-9961-b74ebd54bc7d.png)

問題なさそうですね。

# おわりに
この記事の内容は「分かってしまえば何ともないが、分かるまでが大変」なもので、これはMATLABにはよくある事だと思います。

記事を読んですぐに試そうという方は多くはないかと思いますが、心に留めておいて頂き「いざ！」というときに役立てて頂ければ幸いです。