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

MATLAB & Simulink ユーザーコミュニティー向け日本語ブログ

自分だけの Simulink を作ろう!ツールストリップ自作機能の紹介!

皆さんこんにちは。トレーニングエンジニアの遠藤と申します。
このブログでは、「Simulink と MATLAB をつなぐ」をコンセプトとして、主に技術的な内容について書いております。

さて、2021年ももう残すところわずかとなりました。今年もコロナ禍の影響で様々なイベントがオンラインでの開催となり、MATLAB ユーザーの皆さんとも対面で会うことができず寂しい日々が続いていますが、このブログでは MathWorks 社員と MATLAB ユーザーの皆さん、あるいはユーザーの皆さん同士が繋がれるように、今後も様々な情報の発信を続けていきたいと思いますので、来年もどうぞよろしくお願いします!

 

と、挨拶はこれくらいにして、そろそろ本題に入りたいと思います。皆さん、もう MATLAB R2021b はインストールされましたでしょうか?実は、R2021b では、私が以前解説記事を書いた Simulink API と非常に相性の良い新機能が追加されました。その機能とはズバリ、「Simulink のツールストリップを自作できる機能」です!

 

ツールストリップとは、Simulink の上部に表示されている様々なショートカットアイコンのことです。

 

様々な機能が備わっているこのツールストリップですが、複数のタブに分かれて配置されているため、目的の機能がどのタブにあるのか探すのが大変、複数のタブを切り替えて操作を行うのが面倒、といった苦労もあります。「自分がよく使う機能だけ1つのタブにまとめられないかなぁ」と思ったことのある方もいらっしゃるのではないでしょうか?

また、Simulink API で便利機能を開発している人は、誰しもが「自分の作った機能をツールストリップに登録したい」と考えたことがあるかと思います。アイコンを押すだけで便利機能を実行できれば、わざわざ MATLAB に戻ってコマンドを実行する手間が省けます。

 

今回紹介するツールストリップ自作機能は、まさにこういった方々の夢をかなえるための機能です!

 

この画像のように、なんと既存機能や自作機能を自作したタブにまとめることができるんです!素晴らしい!

この記事では、既存機能を追加する方法と自作機能を追加する方法を順番に解説していきたいと思います。

こちらのドキュメントも合わせてご覧いただくと詳細がわかりやすいです。

 

0. ツールストリップ作成のための準備

ツールストリップの自作を行うためには、事前準備が必要です。とはいっても準備は超簡単、2つの関数を実行するだけです。

まず1つ目は slCreateToolstripComponent という関数です。この関数を実行することで、現在のフォルダ下に “resources” というフォルダが作成され、その下にベースとなるサブフォルダやファイルが自動で作成されます。実行するときは作成するコンポーネントの名前を引数として渡します。

>> slCreateToolstripComponent("test")

 

2つ目は slCreateToolstripTab という関数です。この関数を実行することで、json フォルダ下にタブを作成するためのファイルを自動で作成することができます。実行するときは、作成するタブのIDと先ほど作成したコンポーネントの名前、そしてタブの名前を指定します。

>> slCreateToolstripTab("testTab","test",Title="myTab")

 

 

“testTab.json” というファイルが作成されました。この json ファイルを編集していくことで、オリジナルのタブを作成できる、というわけです。ちなみに、この時点で既にタブ自体は作成されています。

 

これで事前準備は完了です。早速ツールストリップを作っていきましょう!

 

1. ツールストリップに既存機能をまとめたタブを作成する

まずは既存機能を1つのタブにまとめる方法を説明していきます。

1.1 タブの階層構造を設計する

初めに、タブの階層構造を作っていきます。先ほど自動で作成された json ファイルの中身を確認してみましょう。

testTab.json{
  "version": "R2021b",
  "entries": [
    {
      "type": "Tab",
      "id": "testTab",
      "title": "myTab"
    }
  ]
}

json ファイルでは、コンポーネントとプロパティを階層構造で定義します。今作成されているコンポーネントはタブだけなので、そのタブの type, id, title といったプロパティが定義してあるだけです。このタブコンポーネントの中に children というプロパティを新たに作り、その下に新たなコンポーネントを定義していくことでタブを作成していきます。

タブを作成する際の各コンポーネントの階層構造は以下の図の通りです。

  

 

Tab -> Section -> Column とタブを区切っていき、最後に実際の機能である Control を配置するイメージです。試しに json ファイルを編集して新しい Section と Column を作ってみましょう。

testTab.json{
  "version": "R2021b",
  "entries": [
    {
      "type": "Tab",
      "id": "testTab",
      "title": "myTab",
      "children": [
          {
              "type": "Section",
              "title": "Test",
              "children": [
                  {
                      "type": "Column"
                  }
              ]
          }
      ]
    }
  ]
}

“Test” というタイトルの Section に 1 つの Column を定義しました。ただし、json ファイルを編集しただけではツールストリップは更新されません。編集を適用するには、slReloadToolstripConfig 関数を実行します。

>> slReloadToolstripConfig

 

もし json ファイルに不備があった場合は、警告で教えてくれます。何か警告が出たら、括弧やカンマなどが抜けていないかチェックして修正しましょう。

 

MYTAB に新たに TEST という Section が追加されました!

 

1.2 機能を追加する

次に、この Section に既存機能を追加していきます。機能を追加するには、Column の children 下で Control コンポーネントの type と action を指定します。type は以下の4種類から選べます。

  • PushButton:クリックするとアクションが実行されます。
  • DropDownButton:クリックするとドロップダウンメニューが表示されます。
  • SplitButton:PushButton と DropDownButton がセットで作成されます。
  • EmptyControl:位置調整用のスペースが作成されます。

action は既存機能の動作にそれぞれ割り当てられたアクション名です。例えば Simulink の「開く」ボタンが押された時の動作は “openModelAction” という名前です。このアクションを使って、試しにクリックしたらモデルを開くウィンドウを表示するボタンを追加してみましょう。

testTab.json"type": "Column",
"children": [
    {
        "type": "PushButton",
        "action": "openModelAction"
     }
]

※コードが長くなってしまうので、Column の編集部分だけ抜き出しています。

slReloadToolstripConfig 関数を実行して適用してみると……

 

モデルを開くボタンが追加されました!openModelAction にはあらかじめモデルを開くための動作がすべて定義されているので、もうこのボタンを押せばモデルを開く機能を使うことができます。とっても簡単!

 

ただ、問題はアクション名です。追加したい機能に対応するアクション名はどうやって調べればよいのでしょうか?

 

ここで便利なのが、slToolstripDeveloperMode という関数です。この関数はツールストリップの機能のアイコンとアクションの名前を調べるための開発者モードをオンオフ切り替えることができる関数です。

>> slToolstripDeveloperMode("on")
Simulink ツールストリップの開発者モードが有効になりました。Simulink ツールストリップのウィジェット上で一時停止して Ctrl を押すと、MATLAB コマンド ウィンドウにそのウィジェットのアクションとアイコンの名前が表示されます。

 

実行後に表示されるのテキストにも書いてある通り、開発者モードをオンにすると、ツールストリップのアイコンの上にマウスを持っていき Ctrl キーを押すことで、コマンドウィンドウ上にその機能のアクションとアイコン名が表示されます。

試しにコンフィギュレーションパラメータの歯車マークの上で Ctrl キーを押してみると……

Action: openModelConfigParamAction
Icon: settings
-------------------

 

アクション名とアイコンが表示されました。これを使えば既存機能を簡単にタブに追加できます。

testTab.json"type": "Column",
"children": [
    {
        "type": "PushButton",
        "action": "openModelAction"
    },
    {
        "type": "PushButton",
        "action": "openModelConfigParamAction"
    }
]

 

コンフィギュレーションパラメータのボタンが追加できました!

このように、よく使う機能のアクション名を開発者モードで調べてタブに Control として追加しておけば、必要な機能だけをまとめた便利なタブを作成することができます!

 

2. 自作機能をタブに追加する

次に、自作した機能をタブに追加する方法について説明します。自作した機能を追加する場合は、その機能を新しいアクションとして定義しなければならないため、既存機能の場合に比べて複雑です。

2.1 アクションファイルを作成する

自作アクションを定義するためには、先ほど編集していた json ファイルとは別に “タブ名_actions.json” という名前のファイルを json フォルダ下に作成する必要があります。こちらのファイルは特に自動で作成する関数などはないので、先ほどの json ファイルをコピーして名前を変えるなどして手動で作成しましょう。

中身は version と entries だけ残して削除してしまって大丈夫です。

testTab_actions.json{
  "version": "R2021b",
  "entries": [
    {
    }
  ]
}

この entries の中にアクションを定義していき、先ほどの Control の Action でそれを指定する、という流れになります。この記事では、例として「モデル上のゲインを一括で変更するアクション」を作ってみたいと思います。

2.2 アクションを定義する

アクションを定義するときは、以下のように type や id などの必要なプロパティを指定します。

testTab_actions.json{
  "version": "R2021b",
  "entries": [
    {
      "type": "Action",
      "id": "setGains",
      "text": "Set Gains",
      "description": "Set all gain values",
      "command": "setAllGains",
      "commandType": "Script"
    }
  ]
}

type には必ず “Action” を指定します。その他については、id が Control で指定する際に使うアクションの名前、text がツールストリップ上に表示されるテキスト、description がマウスをかざしたときに表示される説明文、command が実行するスクリプト名で、最後の commandType は “Script” を指定します。

実行したいスクリプトは MATLAB から見える場所に置いておきます。今回は以下のようなスクリプトファイル “setAllGains.m” を用意しました。

setAllGains.mblocks = find_system(gcs,"BlockType","Gain");
values = get_param(blocks,"Gain");
gainValues = inputdlg(blocks,"Set gains",1,values);
if ~isempty(gainValues)
    for i = 1:length(blocks)
        set_param(blocks{i},"Gain",gainValues{i});
    end
end

まず find_system 関数で Gain ブロックを検索し, get_param 関数で値を取得, inputdlg 関数でユーザーが値を入力するためのダイアログウィンドウを作成し、set_param 関数で入力された値をブロックに設定する、というようなスクリプトになっています。各関数の使い方については Simulink API の記事やリンク先のドキュメントをご確認ください。

それではこのアクションを testTab.json ファイルの方で指定し、ツールストリップから呼び出せるようにしましょう。

testTab.json"type": "Column",
"children": [
    {
        "type": "PushButton",
        "action": "openModelAction"
    },
    {
        "type": "PushButton",
        "action": "openModelConfigParamAction"
    },
    {
        "type": "PushButton",
        "action": "setGains"
    }
]
 

スクリプト名ではなく、id で設定した “setGains” を指定しなければならないことに注意しましょう。それでは slReloadToolstripConfig 関数を実行して変更を適用し、試運転してみましょう。

setGains をクリックすると、モデル上の3つの Gain ブロックの値を設定するウィンドウが開きました。値を変更して OK をクリックすると……

Gain ブロックの値が入力した値に変更されました!

このように、Simulink API を使ってモデルを編集するスクリプトを用意しておけば、自作したタブからワンクリックでそれを実行できちゃうんです。これは便利!

3. その他の機能の紹介

ここまでで結構分量が多くなってしまったので、その他の機能についてはまとめて簡単に紹介します。詳しい使い方についてはこちらのドキュメントをご参照ください。

3.1 アイコンの指定

アクションを定義した ***_actions.json ファイルでは、アイコンを定義できます。開発者モードで確認したアイコン名、または自作したアイコンの画像(16 x 16, 24 x 24)をツールストリップに表示できます。

3.2 ドロップダウンメニューの定義

この記事では プッシュボタンの作り方を説明しましたが、ドロップダウンメニューの場合はもう少し複雑です。メニューをクリックしたときに表示される Pop-Up List を ***_popups.json ファイルで定義し、各項目をクリックしたときに実行されるアクションを指定する必要があります。

3.3 自作タブの無効化、削除

slCreateToolstripComponent 関数を実行すると、現在のフォルダが MATLAB のパスに追加され、次回起動以降もこのパスは追加されたままになります。そのため、MATLAB を再起動しても一度作成したタブは表示され続けます。

しかし、試しに作っただけのタブや一時的に必要だったタブなど、場合によっては自作したタブを表示させたくない、という場合もあるかと思います。その場合は、slPersistToolstripComponent という関数を使うことで、自作タブをパスに残したままにするかどうかを制御できます。なお、もし作成したファイルも含めて自作したタブを完全に削除したい場合は、slDestroyToolstripComponent 関数を使います。

4. デモモデルのご紹介

弊社エンジニアが作成した、Simulink のモデリング業務効率向上のためのカスタムタブの一例が File Exchange にて公開されています

2o個以上のカスタム機能例やプロジェクトにカスタムタブを反映させる方法などが綺麗にまとまっていますので、どんな機能が作れるか知りたい方や、開発の足掛かりとするための例題ファイルが欲しい方は、ぜひこちらをダウンロードしてみてください!

5. まとめ

今回は、R2021b で新たに追加された Simulink のツールストリップを自作する方法について解説しました。自作機能を開発していない方も、よく使う既存機能をまとめておくだけでも日々の操作が一気に楽になるかもしれません。

皆さんも自分専用の Simulink を作って、より効率的にモデル開発を行ってみませんか?

|
  • print

コメント

コメントを残すには、ここ をクリックして MathWorks アカウントにサインインするか新しい MathWorks アカウントを作成します。