今更聞けない Stateflow 入門
本日は、久々に Simulink の達人 Simulink の中の人から Stateflow に関する記事です。
こんにちは。toshi | Simulink の中の人 です。今回は Stateflow を紹介したいと思います。すでに使ってくださっている方も多いかと思いますが、Simulinkとの違いがよく分からず、使えていない人もいるのではないでしょうか。
今回は初心者のために、Stateflow の何が良いのか、どうやって使うのかについて解説したいと思います。
目次
ソフトウェアの複雑さ
いきなりですが、皆さんはソフトウェアの複雑さについて意識したことはありますでしょうか。自分でコードを書いている時はほとんど感じていないと思います。しかし例えば、他の人が書いたコードを読んだ時、「どういう処理をしているのか分からない」と思ったことはないでしょうか。
こういったことはよくあります。なぜよくあるのかというと、「ソフトウェアは本質的に複雑である」からです。自分で書いたコードは、自分の頭の中で組み立てたシステムをコードにしているため、問題ないのですが、他の人が書いたコードは、自分の知らないシステムを表現しています。複雑なコード(ソフトウェア)からそのシステムを読み解くことが、一般的に難しいのです。
「Out of the Tar Pit」という、2006年に書かれた有名な論文があります。この論文では「ソフトウェアを複雑にする要素」について解説されています。その要素は、以下の4個です。
- 状態
- 制御構文
- プログラムのサイズ
- プログラミング言語がパワフルすぎる
一番上の「状態」とは、例えば洗濯機の「洗い」「すすぎ」「脱水」等の動作モードなどを意味しています。制御構文とは、if文などの処理の分岐を意味しています。プログラムのサイズというのはイメージ通り、コード記述の量のことです。一番下のパワフルすぎるというのは、プログラミング言語が何でもできてしまう(自由度が高すぎる)ということを意味しています。
実は、今回紹介する Stateflow は、この「状態」による複雑さを解消するツールなのです。そのことを順番に説明していきたいと思います。
Simulink による状態表現
実は Simulink は、このような複雑さを解消するツールでもあります。Simulink は時間的変化をシミュレーションする環境です。コードベースの環境では、「時間的変化の設定」をコードで書かなければなりませんが、Simulink であればコンフィギュレーションパラメーターで設定するだけです。
そして、Simulink はブロックを使ったデータフロー図表現ができます。それにより、処理の流れや依存関係をグラフィカルに分かりやすくすることができ、可読性が向上します。
以下の図では、ある計算を MATLAB 言語で記述したものと Simulink で記述したものを比較しています。
MATLAB や他の言語でも同じですが、基本は全てテキスト表現であるため、定数と変数は全て文字列で表現されています。一方で、Simulink では定数はパラメーター、変数は信号という形で、明確に異なる表現になります。これにより、余計な中間変数が削減され、複雑さ(理解しにくさ)を解消できます。
では次に、ここに「状態」が加わるとどうでしょうか。以下のモデルをご覧ください。
こちらのモデルでは、「二つの状態を持ち、入力信号が-0.5より小さければ状態1、入力信号が0.5より大きければ状態2に遷移する」という状態遷移を表現しています。ぱっと見て、これが状態遷移を計算しているモデルであることは分からないのではないでしょうか。
もちろん、直接数値が入っている所を意味の分かるパラメーターにしたり、サブシステムを使って階層化したりすることでもう少し可読性を良くすることができます。しかし、そういう所ではなく、本質的にデータフロー図表現がそもそも状態遷移を分かりやすく表現できていない、という点に着目していただきたいです。
ちなみに、MATLAB で同じものを表現すると、以下のようになります。
コードに慣れている方は、こちらの方が分かりやすいと感じるかもしれませんね。しかし、どちらにしろ、ぱっと見てこれが状態遷移を計算しているコードかは分からないと思います。
Stateflow による状態表現
ここで、Stateflow による状態表現を見てみましょう。上記のモデルやコードと同じものを Stateflow でモデリングすると、以下のようになります。
Simulink のブロックや MATLAB のコードと比較して、遥かに分かりやすいですね。
Stateflow は、一般的な状態遷移図そのままの表現でモデルを作ることができます。角が丸い四角形が一つの状態を表しています。状態には一意な名前を付けなければならないので、ここでは「State_1」「State_2」としています。状態同士は矢印で繋ぎます。その矢印一つに対して、「遷移条件」を設定できます(ここでは、[in_sig < -0.5] や [in_sig > 0.5] です)。遷移条件を満たした時、状態がその方向へ遷移します。
冒頭のソフトウェアの複雑さの話に戻りますが、Stateflow を使っても「状態を含むソフトウェアの動作が複雑」という事実は変わりません。しかし、Stateflow の表現力とそのデバッグ機能を使えば、その構造の可読性が大幅に向上し、不具合調査が非常に簡単になります。
Stateflowのモデリングノウハウ
Stateflow を触ったことがない人は、まずは「Stateflow入門」を受講することをおすすめします。実際に操作しながら使い方を学ぶことができ、MATLAB ライセンスを持たない人でもWebブラウザー上で実施できます。
このセクションでは、Stateflow 入門を終えた方に向けて、現場で Stateflow を使う時に知っておくとよいノウハウをいくつかお伝えしたいと思います。
ローカルデータと状態の可視化
Stateflow でモデリングをしていくと、Stateflow 内に変数(ローカルデータ)を作成することがあります。また、モデルを実行した時、各時刻の状態がどのように変化したのかを波形で確認したい時があります。
これらのローカルデータや状態を可視化したい時は、シミュレーションデータインスペクターにログ設定をするのがおすすめです。
ローカルデータをログするには、シンボルペインからローカルデータを選択状態にして、プロパティインスペクターの「▼ログ」から「信号データのログ」にチェックを入れます。
状態を可視化したい時は、「シミュレーション」タブの「準備」から「アクティブステートのログ記録」をクリックして選択状態にします。
これにより、モデルを実行すると以下のようにシミュレーションデータインスペクターで可視化することができます。
構文の強調表示
Stateflow でたくさんの処理を記述すると、文字の数が増え可読性が低下していきます。この時、データの種類ごとに色分けする設定を施すと可読性が向上します。
「モデル化」タブの「環境」「Stateflow の基本設定」「構文の強調表示」をクリックします。
「構文の強調設定」というウィンドウが表示されるので、「データ構文の強調を有効にする」にチェックを入れて「OK」をクリックします。
これにより、例えば以下のようにハイライトされます。かなり読みやすくなったかと思います。
状態の中に細かい処理を書かない
上記の状態では7行の処理が記述されていますが、この中で「get_random_periphery_position」と「get_initial_direction」は関数になっています。この二つの関数は、別の関数スクリプトで記述していて、それを Stateflow で呼び出す形にしています。
これを行わないと、状態の中に大量にコマンドを記述することになり、可読性が低下します。Stateflow で「コードを書く」必要がある場合は、別ブロック、別ファイルに処理を分けることが推奨されます。
処理を別に分ける方法としては、上記のように別の関数スクリプトで記述してそれを呼び出す方法、Simulink関数で記述する方法、グラフィカル関数で記述する方法、といろいろあります。場面に応じて使い分けるとよいと思います。
おすすめのモデリングスタイル
JMAAB制御モデリングガイドラインに、Stateflow の推奨モデリングスタイルか書かれています。こちらのページで下の方にスクロールすると、「制御モデリングガイドライン Ver6(日本語版)」(2023年3月時点)とありますので、そこからPDFファイルをダウンロードしてください。
全部のルールを守らなければならないわけではありませんが、参考になるルールも多いです。例えば4.2節の「Stateflow ダイアグラム」に記載されている「遷移線の引き方」など、可読性が良くなる書き方は是非真似してみてください。
まとめ
Stateflow を使うと、状態遷移機能を分かりやすく記述できます。皆様の開発で是非活用していただければと思います😄
- Category:
- Stateflow,
- 機能と使い方
Comments
To leave a comment, please click here to sign in to your MathWorks Account or create a new one.