ステートマシン自動生成ツール

公式アカウントをフォロー+スターを付けて、楽しいコンテンツをお見逃しなく

0ea0dad360f93c47581f5e4d02d85f4c.gif

素材ソース | インターネット

実際のソフトウェア システム用のステート マシンを作成することは、特にステート マシン自体が比較的複雑な場合、簡単な作業ではありません。同様の経験をした多くのプログラマは、多くの時間を費やす必要があるため、それを「非創造的な」プロセスとよく表現します。プログラム自体の動作ロジックではなく、ステート マシン内のさまざまな状態を管理する方法に時間とエネルギーが費やされます。

一般的なソフトウェア設計パターンとして、さまざまなソフトウェア システムのステート マシン間には多かれ少なかれ共通性があるはずです。そのため、人々は有限ステート マシンのフレームワーク コードを自動的に生成するいくつかのツールを開発しようと試み始めました。次に、Linux では、は非常に良い選択です──FSME (Finite State Machine Editor)。

可視化されたFSME

fd092d92a975c75d16dc0ae66ecfa915.jpeg

FSME は、Qt ベースの有限ステート マシン ツールで、ユーザーがプログラムに必要なステート マシンをグラフィカルにモデル化できるほか、C++ または Python で実装されたステート マシン フレームワーク コードを自動的に生成することもできます。

下図の城門のステート マシンを例に、FSME を使用してプログラムに必要なステート マシン コードを自動生成する方法を紹介します。

ゲートを制御するステートマシン

94912b8d47b86a8d580153325a670bd6.jpeg

1 ステートマシンのモデリング

まず fsme コマンドを実行してステート マシン エディタを起動し、ツールバーの [新規] ボタンをクリックして新しいステート マシンを作成します。FSME でステート マシンを構築するために使用される 5 つの基本要素は、イベント (Event)、入力 (Input)、出力 (Output)、状態 (State)、および遷移 (Transition) です。これらは左側のツリー リストにあります。インターフェースの側面 そのうちの 4 つ。

  • 状態モデリング

FSME インターフェイスの左側にあるツリー リストで [州] 項目を選択し、キーボードの Insert キーを押して新しい州を挿入し、下部の [名前] テキスト ボックスに州の名前を入力します。右に移動し、右上にステートの名前を入力します。 の描画領域でステートを配置する位置をクリックすると、新しいステートが作成されます。同様に、次の図に示すように、ステート マシンに必要なすべての状態を追加できます。

状態モデリング

b0e3eef123144fdd59fcbbc95d63fe28.jpeg

  • イベントモデリング

FSME インターフェイスの左側にあるツリー リストで [イベント] 項目を選択し、キーボードの Insert キーを押して新しいイベントを追加し、下部の [名前] テキスト ボックスにイベントの名前を入力します。右クリックして「適用」ボタンをクリックすると、新しいイベントが作成されます。同様に、次の図に示すように、ステート マシンに必要なすべてのイベントを追加できます。

f107f8c78a4bcb732359bd546b33fff3.jpeg

  • 変換モデリング

状態遷移はモデリング プロセス全体の最も重要な部分であり、有限状態マシン内の 1 つの状態が別の状態にどのように切り替わるかを定義するために使用されます。たとえば、城門の制御に使用されるステート マシンが Opened 状態にある場合、この時点で Close イベントが発生すると、ステート マシンの現在の状態は Closed 状態に切り替わります。このような完全なプロセスは、ステート マシン モデルを closeDoor A 変換として記述します。

FSME でこのような変換を追加するには、まずインターフェイスの左側にあるツリー リストの [状態] の下にある [開いた] 項目を選択し、キーボードの Insert キーを押して新しい変換を追加する必要があります。 「名前」テキストボックスにトランジション名「closeDoor」を入力します。「条件」テキストボックスに「Close」と入力して、トランジションをトリガーする条件がCloseイベントの生成であることを示し、「Closed」を選択します。図に示すように、[ターゲット] ドロップダウン ボックスの項目を選択して、遷移が発生した後、ステート マシンがクローズ状態に切り替わることを示し、最後に [適用] ボタンをクリックして、新しい状態遷移関係を定義します。下に。ステート マシンに必要なすべての遷移は、同じ方法で追加できます。

変換モデリング

094521d2e489b1cf5a0d33a1129b3c71.jpeg

2 ステートマシンフレームの生成

FSME を使用すると、視覚的なステート マシン モデリングを実行できるだけでなく、さらに重要なことに、取得したモデルに基づいて C++ または Python で実装されたステート マシン フレームワークを自動的に生成することもできます。まず、FSME インターフェイスの左側にあるツリー リストで [Root] 項目を選択し、次に右下隅の [Name] テキスト ボックスにステート マシンの名前「DoorFSM」を入力して、状態「Opened」を選択します。 「初期状態」ドロップダウンリストから「」を選択 ステートマシンの初期化状態として、図 6 に示します。

初期プロパティを設定する

a50ba2da1258d62a272803f3751ed13b.jpeg

ステート マシン モデルを door.fsm ファイルとして保存した後、次のコマンドを使用してステート マシン定義を含むヘッダー ファイルを生成します。

[xiaowp@linuxgam code]$ fsmc door.fsm -d -o DoorFSM.h

さらに、ステート マシンの実装を含むフレームワーク コードを生成することもできます。

[xiaowp@linuxgam code]$ fsmc door.fsm -d -impl DoorFSM.h -o DoorFSM.cpp

生成されたステート マシンを検証したい場合は、テスト用のコードを手動で記述するだけです。

/*
 * TestFSM.cpp
 * 测试生成的状态机框架
 */

#include "DoorFSM.h"

int main()
{
  DoorFSM door;
  door.A(DoorFSM::Close);
  door.A(DoorFSM::Lock);
  door.A(DoorFSM::Unlock);
  door.A(DoorFSM::Open);
}

有限ステート マシンはイベントによって駆動されます。FSME によって生成されたステート マシン フレームワーク コードでは、メソッド A() を使用して、対応するイベントをステート マシンに送信し、ステート マシンの通常の動作に必要な「パワー」を提供できます。 。ステート マシンは内部のイベント キューを維持する責任を負い、到着したすべてのイベントはイベント キューに入れられて待機し、到着順に順番に処理されるようにします。各受信イベントを処理するとき、ステート マシンは、現在の状態に応じて、その状態に対応する遷移条件が満たされているかどうかを確認し、満たされている場合は、対応する状態遷移プロセスを起動します。

生成されたステート マシンのスケルトンとテスト コードは、次のコマンドを使用して実行可能ファイルにコンパイルできます。

[xiaowp@linuxgam code]$ g++ DoorFSM.cpp TestFSM.cpp -o fsm

fsmc コマンドでステート マシン コードを生成するときに -d オプションが使用されたため、生成されたステート マシン フレームには、ステート マシン内の各状態遷移のアクティブ化イベント、遷移前の状態、経験した状態などの特定のデバッグ情報が含まれます。遷移、遷移状態などは次のようになります。

[xiaowp@linuxgam code]$ ./fsm
DoorFSM:event:'Close'
DoorFSM:state:'Opened'
DoorFSM:transition:'closeDoor'
DoorFSM:new state:'Closed'
DoorFSM:event:'Lock'
DoorFSM:state:'Closed'
DoorFSM:transition:'lockDoor'
DoorFSM:new state:'Locked'
DoorFSM:event:'Unlock'
DoorFSM:state:'Locked'
DoorFSM:transition:'unlockDoor'
DoorFSM:new state:'Unlocked'
DoorFSM:event:'Open'
DoorFSM:state:'Unlocked'
DoorFSM:transition:'openDoor'
DoorFSM:new state:'Opened'

3 カスタム ステート マシン

現在のステート マシンは、外部からのさまざまなイベントに応答し、現在の状態を適切に調整することができています。つまり、ステート マシン エンジンの機能が実現されており、次は状態を調整することになります。アプリケーションの特定のニーズに応じてマシンをカスタマイズし、ソフトウェア システム自体に関連する処理ロジックをステート マシンに追加するようにカスタマイズします。FSME では、特定のアプリケーションに関連する操作は出力と呼ばれます。これらは実際には、ユーザーが特定の実装を行う必要があるいくつかの仮想関数です。自動生成されたステート マシン エンジンは、特定の状態に入るときまたは出るときにそれらを呼び出す役割を果たします。

市の門を制御するステート マシンを例として取り上げ、各ステートに入るときにいくつかの処理ロジックを追加したいとします。まず、FSME インターフェイスの左側にあるツリー リストで [出力] 項目を選択し、キーボードの Insert キーを押して新しい出力を追加し、右下の [名前] テキスト ボックスに対応する名前を入力します。をクリックして「適用」ボタンをクリックすると、図に示すように、新しい出力が作成されます。ステート マシンに必要なすべての出力は、同じ方法で追加できます。

出力を追加

ce0f8fa7286cc4b2ba29ec9263ed974f.jpeg

すべての出力が定義されると、ステート マシンの各状態に対応する出力をバインドすることができます。まず、FSME インターフェイスの左側にある「状態」項目で対応する状態を選択し、次に右下隅の「使用可能」リスト ボックスから状態に対応する出力を選択し、「<」ボタンをクリックして、図に示すように、それを「In」リストに追加します。同様に、ステート マシンのすべての状態に対応する出力を設定できます。同じ状態に複数の出力を持つことができます。状態に入るときに In リストの出力が呼び出され、Out リストの出力がそれになりますはこの状態を終了するときに呼び出され、出力呼び出しの順序は In または Out リスト内の順序と一致します。

写真は状態設定出力を示しています

11dfae2bfd2d0af6e3da5c339c51179f.jpeg

ステート マシン モデルの変更により、ステート マシンのフレームワーク コードを再度生成する必要がありますが、今回は -d パラメーターを追加する必要はありません。

[xiaowp@linuxgam code]$ fsmc door.fsm -o DoorFSM.h
[xiaowp@linuxgam code]$ fsmc door.fsm -d -impl DoorFSM.h -o DoorFSM.cpp

enterOpend、enterClosed、enterLocked、および enterUnlocked の 4 つの出力を新しいステート マシン モデルに追加したため、生成されたクラス DoorFSM には次の純粋仮想関数が含まれるようになります。

virtual void enterOpened() = 0;
virtual void enterLocked() = 0;
virtual void enterUnlocked() = 0;
virtual void enterClosed() = 0;

明らかに、この時点で生成されたステート マシン フレームワークは直接コンパイルできなくなり、DoorFSM クラスからサブクラスを派生し、これらの純粋な仮想関数の特定の実装を提供する必要があります。

/*
 * DoorFSMLogic.h
 * 状态机控制逻辑的头文件
 */
#include "DoorFSM.h"

class DoorFSMLogic : public DoorFSM
{
 
 protected:
  virtual void enterOpened();
  virtual void enterLocked();
  virtual void enterUnlocked();
  virtual void enterClosed();
};

上で述べたように、これらの関数は実際にはアプリケーション システムの処理ロジックを表しており、例として、いくつかのプロンプト情報を出力するだけです。

/*
 * DoorFSMLogic.cpp
 * 状态机控制逻辑的实现文件
 */
#include "DoorFSMLogic.h"
#include <iostream>

void DoorFSMLogic::enterOpened()
{
    std::cout << "Enter Opened state." << std::endl;
}

void DoorFSMLogic::enterClosed()
{
    std::cout << "Enter Closed state." << std::endl;
}

void DoorFSMLogic::enterLocked()
{
    std::cout << "Enter Locked state." << std::endl;
}

void DoorFSMLogic::enterUnlocked()
{
    std::cout << "Enter Unlocked state." << std::endl;
}

同様に、生成されたステート マシンを検証するには、テスト コードを手動で記述する必要があります。

/*
 * TestFSM.cpp
 * 测试状态机逻辑
 */
#include "DoorFSMLogic.h"

int main()
{
  DoorFSMLogic door;
  door.A(DoorFSM::Close);
  door.A(DoorFSM::Lock);
  door.A(DoorFSM::Unlock);
  door.A(DoorFSM::Open);
}

生成されたステート マシンのスケルトンとテスト コードは、次のコマンドを使用して実行可能ファイルにコンパイルできます。

[xiaowp@linuxgam code]$ g++ DoorFSM.cpp DoorFSMLogic.cpp TestLogic.cpp -o logic

実行結果は次のとおりです。

[xiaowp@linuxgam code]$ ./logic
Enter Closed state.
Enter Locked state.
Enter Unlocked state.
Enter Opened state.

この記事にはコードのダウンロードが含まれます。 http://www.uml.org.cn/umlcode/code.zip

免責事項:この記事の内容はインターネットから得たものであり、著作権は元の著者に属します。著作権上の問題が含まれる場合は、削除するよう私に連絡してください。

------------ 終了 ------------

79e5d600640655b39cc97205c1c1228b.gif

●コラム「組み込みツール

●コラム「組込み開発」

●コラム「Keilチュートリアル」

●埋め込み列に選択されたチュートリアル

公式アカウントに注意し、ルールに従って技術交流グループに参加するには「 Jiagroup 」と返信し、さらに多くのコンテンツを表示するには「 1024」と返信します。

6d729b2999c7283dff860c844a744406.jpeg

e354460fded1ffd8880bc55436782879.png

さらに共有を確認するには、元のテキストを読む」をクリックしてください。

おすすめ

転載: blog.csdn.net/ybhuangfugui/article/details/132033245