0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

分享一款狀態(tài)機自動生成工具

strongerHuang ? 來源:strongerHuang ? 2023-07-31 10:24 ? 次閱讀

為實用的軟件系統(tǒng)編寫狀態(tài)機并不是一件十分輕松的事情,特別是當狀態(tài)機本身比較復雜的時候尤其如此,許多有過類似經(jīng)歷的程序員往往將其形容為"毫無創(chuàng)意"的過程,因為他們需要將大量的時間與精力傾注在如何管理好狀態(tài)機中的各種狀態(tài)上,而不是程序本身的運行邏輯。

作為一種通用的軟件設計模式,各種軟件系統(tǒng)的狀態(tài)機之間肯定會或多或少地存在著一些共性,因此人們開始嘗試開發(fā)一些工具來自動生成有限狀態(tài)機的框架代碼,而在Linux下就有一個挺不錯的選擇──FSME(Finite State Machine Editor)。

可視化的FSME

FSME是一個基于Qt的有限狀態(tài)機工具,它能夠讓用戶通過圖形化的方式來對程序中所需要的狀態(tài)機進行建模,并且還能夠自動生成用C++或者Python實現(xiàn)的狀態(tài)機框架代碼。

下面就以下圖中城門的狀態(tài)機為例,來介紹如何利用FSME來自動生成程序中所需要的狀態(tài)機代碼。

控制城門的狀態(tài)機

1狀態(tài)機建模

首先運行fsme命令來啟動狀態(tài)機編輯器,然后單擊工具欄上的"New"按鈕來創(chuàng)建一個新的狀態(tài)機。FSME中用于構建狀態(tài)機的基本元素一共有五種:事件(Event)、輸入(Input)、輸出(Output)、狀態(tài)(State)和轉換(Transition),在界面左邊的樹形列表中可以找到其中的四種。

  • 狀態(tài)建模

在FSME界面左邊的樹形列表中選擇"States"項,然后按下鍵盤上的Insert鍵來插入一個新的狀態(tài),接著在右下方的"Name"文本框中輸入狀態(tài)的名稱,再在右上方的繪圖區(qū)域單擊該狀態(tài)所要放置的位置,一個新的狀態(tài)就創(chuàng)建好了。用同樣的辦法可以添加狀態(tài)機所需要的所有狀態(tài),如下圖所示。

狀態(tài)建模

  • 事件建模

在FSME界面左邊的樹形列表中選擇"Events"項,然后按下鍵盤上的Insert鍵來添加一個新的事件,接著在右下方的"Name"文本框中輸入事件的名稱,再單擊"Apply"按鈕,一個新的事件就創(chuàng)建好了。用同樣的辦法可以添加狀態(tài)機所需要的所有事件,如下圖所示。

  • 轉換建模

狀態(tài)轉換是整個建模過程中最重要的一個部分,它用來定義有限狀態(tài)機中的一個狀態(tài)是如何切換到另一個狀態(tài)的。例如,當用來控制城門的狀態(tài)機處于Opened狀態(tài)時,如果此時有Close事件產(chǎn)生,那么狀態(tài)機的當前狀態(tài)將切換到Closed狀態(tài),這樣一個完整的過程在狀態(tài)機模型中可以用closeDoor這樣一個轉換來進行描述。

要在FSME中添加這樣一個轉換,首先需要在界面左邊的樹形列表中選擇"States"下的"Opened"項,然后按下鍵盤上的Insert鍵來添加一個新的轉換,接著在右下角的"Name"文本框中輸入轉換的名字"closeDoor",在"Condition"文本框中輸入"Close"表明觸發(fā)該轉換的條件是事件Close的產(chǎn)生,在"Target"下拉框中選擇"Closed"項表明該轉換發(fā)生后狀態(tài)機將被切換到Closed狀態(tài),最后再單擊"Apply"按鈕,一個新的狀態(tài)轉換關系就定義好了,如下圖所示。用同樣的辦法可以添加狀態(tài)機所需要的所有轉換。

轉換建模

2 生成狀態(tài)機框架

使用FSME不僅能夠進行可視化的狀態(tài)機建模,更重要的是它還可以根據(jù)得到的模型自動生成用C++或者Python實現(xiàn)的狀態(tài)機框架。首先在FSME界面左邊的樹形列表中選擇"Root"項,然后在右下角的"Name"文本框中輸入狀態(tài)機的名字"DoorFSM",再從"Initial State"下拉列表中選擇狀態(tài)"Opened"作為狀態(tài)機的初始化狀態(tài),如圖6所示。

設置初始屬性


在將狀態(tài)機模型保存為door.fsm文件之后,使用下面的命令可以生成包含有狀態(tài)機定義的頭文件:


		
			[xiaowp@linuxgam code]$ fsmc door.fsm -d -o DoorFSM.h
進一步還可以生成包含有狀態(tài)機實現(xiàn)的框架代碼:

		
			[xiaowp@linuxgam code]$ fsmc door.fsm -d -impl DoorFSM.h -o DoorFSM.cpp
如果想對生成的狀態(tài)機進行驗證,只需要再手工編寫一段用于測試的代碼就可以了:

		

/* * TestFSM.cpp * 測試生成的狀態(tài)機框架 */ #include "DoorFSM.h" int main() { DoorFSM door; door.A(DoorFSM::Close); door.A(DoorFSM::Lock); door.A(DoorFSM::Unlock); door.A(DoorFSM::Open); }


有限狀態(tài)機是由事件來進行驅動的,在FSME生成的狀態(tài)機框架代碼中,方法A()可以被用來向狀態(tài)機發(fā)送相應的事件,從而提供狀態(tài)機正常運轉所需要的"動力"。狀態(tài)機負責在其內部維護一個事件隊列,所有到達的事件都會先被放到事件隊列中進行等候,從而能夠保證它們將按照到達的先后順序被依次處理。在處理每一個到達的事件時,狀態(tài)機都會根據(jù)自己當前所處的狀態(tài),檢查與該狀態(tài)對應的轉換條件是否已經(jīng)被滿足,如果滿足的話則激活相應的狀態(tài)轉換過程。


使用下面的命令能夠將生成的狀態(tài)機框架和測試代碼編譯成一個可執(zhí)行文件:

		

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

由于之前在用fsmc命令生成狀態(tài)機代碼時使用了-d選項,生成的狀態(tài)機框架中會包含一定的調試信息,包括狀態(tài)機中每次狀態(tài)轉換時的激活事件、轉換前的狀態(tài)、所經(jīng)歷的轉換、轉換后的狀態(tài)等,如下所示:

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


3定制狀態(tài)機

目前得到的狀態(tài)機已經(jīng)能夠響應來自外部的各種事件,并適當?shù)卣{整自己當前所處的狀態(tài),也就是說已經(jīng)實現(xiàn)了狀態(tài)機引擎的功能,接下來要做的就是根據(jù)應用的具體需求來進行定制,為狀態(tài)機加入與軟件系統(tǒng)本身相關的那些處理邏輯。在FSME中,與具體應用相關的操作稱為輸出(Output),它們實際上就是一些需要用戶給出具體實現(xiàn)的虛函數(shù),自動生成的狀態(tài)機引擎負責在進入或者退出某個狀態(tài)時調用它們。

仍然以控制城門的那個狀態(tài)機為例,假設我們希望在進入每個狀態(tài)時都添加一部分處理邏輯。首在FSME界面左邊的樹形列表選擇"Outputs"項,然后按下鍵盤上的Insert鍵來添加一個新的輸出,接著在右下方的"Name"文本框中輸入相應的名稱,再單擊"Apply"按鈕,一個新的輸出就創(chuàng)建好了,如圖所示。用同樣的辦法可以添加狀態(tài)機所需要的所有輸出。

添加輸出

當所有的輸出都定義好之后,接下來就可以為狀態(tài)機中的每個狀態(tài)綁定相應的輸出。首先在FSME界面左側的"States"項中選擇相應的狀態(tài),然后從右下角的"Available"列表框中選擇與該狀態(tài)對應的輸出,再單擊"<"按鈕將其添加到"In"列表中,如圖所示。用同樣的辦法可以為狀態(tài)機中的所有狀態(tài)設置相應的輸出,同一個狀態(tài)可以對應有多個輸出,其中In列表中的輸出會在進入該狀態(tài)時被調用,而Out列表中的輸出則會在退出該狀態(tài)時被調用,輸出調用的順序是與其在In或者Out列表中的順序相一致的。

圖為狀態(tài)設置輸出

由于對狀態(tài)機模型進行了修改,我們需要再次生成狀態(tài)機的框架代碼,不過這次不需要加上-d參數(shù)


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

我們在新的狀態(tài)機模型中添加了enterOpend、enterClosed、enterLocked和enterUnlocked四個輸出,因此生成的類DoorFSM中會包含如下幾個純虛函數(shù):

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

顯然,此時生成的狀態(tài)機框架不能夠再被直接編譯了,我們必須從類DoorFSM派生出一個子類,并提供對這幾個純虛函數(shù)的具體實現(xiàn):

			
				/* * DoorFSMLogic.h * 狀態(tài)機控制邏輯的頭文件 */ #include "DoorFSM.h" class DoorFSMLogic : public DoorFSM { protected: virtual void enterOpened(); virtual void enterLocked(); virtual void enterUnlocked(); virtual void enterClosed(); };

正如前面所提到過的,這幾個函數(shù)實際上代表的正是應用系統(tǒng)的處理邏輯,作為例子我們只是簡單地輸出一些提示信息:


			
				/* * DoorFSMLogic.cpp * 狀態(tài)機控制邏輯的實現(xiàn)文件 */ #include "DoorFSMLogic.h" #include  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; }

同樣,為了對生成的狀態(tài)機進行驗證,我們還需要手工編寫一段測試代碼:

			
				/* * TestFSM.cpp * 測試狀態(tài)機邏輯 */ #include "DoorFSMLogic.h" int main() { DoorFSMLogic door; door.A(DoorFSM::Close); door.A(DoorFSM::Lock); door.A(DoorFSM::Unlock); door.A(DoorFSM::Open); }

使用下面的命令能夠將生成的狀態(tài)機框架和測試代碼編譯成一個可執(zhí)行文件:

			
				[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.
				
審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11304

    瀏覽量

    209523
  • 狀態(tài)機
    +關注

    關注

    2

    文章

    492

    瀏覽量

    27541
  • 軟件系統(tǒng)

    關注

    0

    文章

    63

    瀏覽量

    9505

原文標題:一款狀態(tài)機自動生成工具

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    如何設計自動駕駛系統(tǒng)的狀態(tài)機

    狀態(tài)機模塊在自動駕駛系統(tǒng)中扮演著關鍵的角色,它負責管理和控制各個功能的狀態(tài)轉換和行為執(zhí)行。今天我們來聊聊如何設計自動駕駛系統(tǒng)的狀態(tài)機 。
    發(fā)表于 09-19 15:07 ?2644次閱讀
    如何設計<b class='flag-5'>自動</b>駕駛系統(tǒng)的<b class='flag-5'>狀態(tài)機</b>

    如何利用Linux下的工具自動生成實用的狀態(tài)機框架?

    (Finite State Machine),是種應用非常廣泛的軟件設計模式(Design Pattern)。本文介紹如何構建基于狀態(tài)機的軟件系統(tǒng),以及如何利用Linux下的工具
    的頭像 發(fā)表于 11-25 14:15 ?1368次閱讀
    如何利用Linux下的<b class='flag-5'>工具</b>來<b class='flag-5'>自動</b><b class='flag-5'>生成</b>實用的<b class='flag-5'>狀態(tài)機</b>框架?

    SaberRD狀態(tài)機建模工具介紹()什么是狀態(tài)機建模

    狀態(tài)機建模是使用狀態(tài)圖和方程式的手段,創(chuàng)建基于混合信號的有限狀態(tài)機模型的種建模工具
    的頭像 發(fā)表于 12-05 09:51 ?1727次閱讀
    SaberRD<b class='flag-5'>狀態(tài)機</b>建模<b class='flag-5'>工具</b>介紹(<b class='flag-5'>一</b>)什么是<b class='flag-5'>狀態(tài)機</b>建模

    推薦一款:【靈生】單片代碼自動生成器(自動編程工具)

    推薦一款:【靈生】單片代碼自動生成器(自動編程工具)以往編寫單片
    發(fā)表于 12-21 16:53

    狀態(tài)機代碼生成工具

    狀態(tài)機代碼生成工具狀態(tài)機代碼生成工具狀態(tài)機代碼
    發(fā)表于 11-19 15:12 ?9次下載

    狀態(tài)機原理及用法

    狀態(tài)機原理及用法狀態(tài)機原理及用法狀態(tài)機原理及用法
    發(fā)表于 03-15 15:25 ?0次下載

    使用ModelSim自動生成狀態(tài)機FSM的狀態(tài)轉換圖

    HDL代碼設計中重要的內容之就是設計程序的狀態(tài)機FSM,狀態(tài)轉換控制著整個程序的流程,為了理解程序,我們經(jīng)常需要把狀態(tài)機狀態(tài)轉換圖畫出來
    發(fā)表于 02-10 15:39 ?1.5w次閱讀
    使用ModelSim<b class='flag-5'>自動</b><b class='flag-5'>生成</b><b class='flag-5'>狀態(tài)機</b>FSM的<b class='flag-5'>狀態(tài)</b>轉換圖

    簡述使用QII狀態(tài)機向導如何創(chuàng)建狀態(tài)機

    如何使用QII狀態(tài)機向導創(chuàng)建狀態(tài)機
    的頭像 發(fā)表于 06-20 00:11 ?4228次閱讀
    簡述使用QII<b class='flag-5'>狀態(tài)機</b>向導如何創(chuàng)建<b class='flag-5'>一</b>個<b class='flag-5'>狀態(tài)機</b>

    FPGA:狀態(tài)機簡述

    本文目錄 前言 狀態(tài)機簡介 狀態(tài)機分類 Mealy 型狀態(tài)機 Moore 型狀態(tài)機 狀態(tài)機描述
    的頭像 發(fā)表于 11-05 17:58 ?7404次閱讀
    FPGA:<b class='flag-5'>狀態(tài)機</b>簡述

    有限狀態(tài)機設計是HDL Designer Series的關鍵應用

    有限狀態(tài)機的設計是HDL Designer Series?工具的關鍵應用。 盡可能地對于設計人員編寫導致狀態(tài)機性能不佳的VHDL,可以使用HDL Designer用于生成VHDL的Se
    發(fā)表于 04-08 10:05 ?6次下載

    如何構建基于狀態(tài)機的軟件系統(tǒng)

    模式(Design Pattern)。本文介紹如何構建基于狀態(tài)機的軟件系統(tǒng),以及如何利用Linux下的工具自動生成實用的狀態(tài)機框架。
    的頭像 發(fā)表于 09-14 10:55 ?1549次閱讀

    狀態(tài)機自動生成工具FSME

    狀態(tài)機中的各種狀態(tài)上,而不是程序本身的運行邏輯。 作為種通用的軟件設計模式,各種軟件系統(tǒng)的狀態(tài)機之間肯定會或多或少地存在著些共性,因此
    的頭像 發(fā)表于 09-13 16:45 ?1475次閱讀
    <b class='flag-5'>狀態(tài)機</b><b class='flag-5'>自動</b><b class='flag-5'>生成</b><b class='flag-5'>工具</b>FSME

    自動生成程序狀態(tài)機代碼狀態(tài)機建模方法

    首先運行fsme命令來啟動狀態(tài)機編輯器,然后單擊工具欄上的“New”按鈕來創(chuàng)建個新的狀態(tài)機。FSME中用于構建狀態(tài)機的基本元素
    的頭像 發(fā)表于 09-13 16:50 ?1147次閱讀
    <b class='flag-5'>自動</b><b class='flag-5'>生成</b>程序<b class='flag-5'>狀態(tài)機</b>代碼<b class='flag-5'>狀態(tài)機</b>建模方法

    如何生成狀態(tài)機框架

    生成狀態(tài)機框架 使用FSME不僅能夠進行可視化的狀態(tài)機建模,更重要的是它還可以根據(jù)得到的模型自動生成用C++或者Python實現(xiàn)的
    的頭像 發(fā)表于 09-13 16:54 ?991次閱讀
    如何<b class='flag-5'>生成</b><b class='flag-5'>狀態(tài)機</b>框架

    什么是狀態(tài)機狀態(tài)機的種類與實現(xiàn)

    狀態(tài)機,又稱有限狀態(tài)機(Finite State Machine,F(xiàn)SM)或米利狀態(tài)機(Mealy Machine),是種描述系統(tǒng)狀態(tài)變化
    的頭像 發(fā)表于 10-19 10:27 ?9576次閱讀