手把手教用matlab做無人駕駛(十五)--matlab/simulink stateflow學習教程

1.打開stateflow的五種方式方式:

(1)在maltab命令行裏面輸入:sf

(2)命令行輸入:sflib

(3)命令行輸入:sfnew  -matlab

(4)命令行輸入:sfnew -c  這是打開stateflow c語言編寫的

(5)直接在simulink library 中直接打開stateflow

如上圖,隨便哪一種方式都可以。

2.在matlab/simulink中建立stateflow後

雙擊進入stateflow中,在空白處右鍵點擊Properties進入進行相關設置,如Action Language是matlab語言可設置爲C語言,更新方法等。

3.現在介紹stateflow建模

看下面兩個模塊,這個是虛線,是個並行關係,怎麼設置呢?即在 空白處右鍵選擇Decompostion中Parallel就出現虛線(注意:這裏有1,2表示執行順序,1表示優先執行)。選擇Exclusive即爲互相排斥關係,爲實線,如下圖:

想改變並行執行順序怎麼做呢?只需要在上面案例中state1上選中Execution order選擇爲2,另一個就會變成1,如下圖:

動作類型(entry(en),during(du),exit(ex)

用於基於事件的時序邏輯的運算符

對於基於事件的時序邏輯,請使用下表所述的運算符。

運算符 語法 說明

after

after(n, E)

E 是 after 運算符的基礎事件;n 可以是:

  • 正整數

  • 計算結果爲正整數值的表達式

如果基礎事件 E 自關聯狀態激活後至少已發生 n 次,則返回 true。否則,運算符返回 false

在不包含輸入事件的 Stateflow 圖中,如果圖自關聯狀態激活後已喚醒 n 次或更多次,after(n, tick) 或 after(n, wakeup) 會返回 true。

每次關聯狀態重新激活時,E 的計數器重置爲 0。

before

before(n, E)

E 是 before 運算符的基礎事件;n 可以是:

  • 正整數。

  • 計算結果爲正整數值的表達式。

如果基礎事件 E 自關聯狀態激活後發生次數少於 n 次,則返回 true。否則,運算符返回 false

在不包含輸入事件的 Stateflow 圖中,如果 Stateflow 圖自關聯狀態激活後喚醒次數少於 n 次,則 before(n, tick) 或 before(n, wakeup) 會返回 true。

每次關聯狀態重新激活時,E 的計數器重置爲 0。

at

at(n, E)

E 是 at 運算符的基礎事件;n 可以是:

  • 正整數。

  • 計算結果爲正整數值的表達式。

僅當基礎事件 E 自關聯狀態激活後發生第 n 次時,才返回 true。否則,運算符返回 false

在不包含輸入事件的 Stateflow 圖中,如果 Stateflow 圖自關聯狀態激活後已喚醒第 n 次,at(n, tick) 或 at(n, wakeup) 將返回 true。

每次關聯狀態重新激活時,E 的計數器重置爲 0。

every

every(n, E)

E 是 every 運算符的基礎事件;n 可以是:

  • 正整數。

  • 計算結果爲正整數值的表達式。

當基礎事件 E 自關聯狀態激活後每發生 n 次時,返回 true。否則,運算符返回 false

在不包含輸入事件的 Stateflow 圖中,當圖自關聯狀態激活後喚醒 n 的整數倍次數時,every(n, tick) 或 every(n, wakeup) 會返回 true。

每次關聯狀態重新激活時,E 的計數器重置爲 0。因此,此運算符只適用於狀態動作,而不適用於轉移。

temporalCount

temporalCount(E)

E 是 temporalCount 運算符的基礎事件。

自關聯狀態激活後,基礎事件 E 每發生一次,值遞增 1,並返回正整數。否則,運算符返回 0 值。

每次關聯狀態重新激活時,E 的計數器重置爲 0。

基於事件的時序邏輯示例

以下示例說明了基於事件的時序邏輯在狀態動作和轉移中的使用。

運算符 用法 示例 說明

after

狀態動作

(on after)

on after(5, CLK): status('on');

從狀態激活後開始 5 個時鐘週期,每個 CLK 週期會出現一條狀態消息。

after

轉移

ROTATE[after(10, CLK)]

僅在廣播 ROTATE 事件且狀態激活 10 個 CLK 週期以後,纔會發生轉出關聯狀態的轉移。

before

狀態動作

(on before)

on before(MAX, CLK): temp++;

temp 變量在每個 CLK 週期遞增一次,直到狀態達到 MAX 限制。

before

轉移

ROTATE[before(10, CLK)]

僅在廣播 ROTATE 事件且在狀態激活後的 10 個 CLK 個週期之內,纔會發生轉出關聯狀態的轉移。

at

狀態動作

(on at)

on at(10, CLK): status('on');

狀態消息會在狀態激活後的正好 10 個 CLK 週期時出現。

at

轉移

ROTATE[at(10, CLK)]

僅在廣播 ROTATE 事件且正好在狀態激活後的 10 個 CLK 週期時,纔會發生轉出關聯狀態的轉移。

every

狀態動作

(on every)

on every(5, CLK): status('on');

狀態激活後,每 5 個 CLK 週期會出現一條狀態消息。

temporalCount

狀態動作

(during)

du: y = mm[temporalCount(tick)];

此動作會對狀態激活後的時鐘時間進行計數並返回整數值。然後,該動作會爲變量 y 賦予 mm 數組的值,該數組的索引是 temporalCount 運算符返回的值。

基於事件的時序邏輯的表示法

可以使用以下兩種表示法之一來表示基於事件的時序邏輯。

事件表示法

使用事件表示法定義僅依賴基礎事件的狀態動作或轉移條件。

事件表示法採用以下語法:

tlo(n, E)[C]

其中

  • tlo 是一個布爾時序邏輯運算符(afterbeforeat 或 every

  • n 是運算符的出現次數

  • E 是運算符的基礎事件

  • C 是一個可選條件表達式

條件表示法

使用條件表示法定義依賴基礎事件和非基礎事件的轉移條件。

條件表示法遵循以下語法:

E1[tlo(n, E2) && C]

其中

  • E1 是任意非基礎事件

  • tlo 是一個布爾時序邏輯運算符(afterbeforeat 或 every

  • n 是運算符的出現次數

  • E2 是運算符的基礎事件

  • C 是一個可選條件表達式

事件表示法和條件表示法示例

表示法 用法 示例 說明

事件

狀態動作

(on after)

on after(5, CLK): temp = WARM;

temp 變量自狀態激活後的 5 個 CLK 週期後變爲 WARM

事件

轉移

after(10, CLK)[temp == COLD]

狀態激活 10 個 CLK 週期之後,如果 temp 變量爲 COLD,則會發生轉出關聯狀態的轉移。

條件

轉移

ON[after(5, CLK) && temp == COLD]

僅在廣播 ON 事件且在狀態激活 5 個 CLK 週期以後並且 temp 變量爲 COLD 時,纔會發生轉出關聯狀態的轉移。

注意

在狀態動作中必須使用事件表示法,因爲狀態動作的語法不支持使用條件表示法。

用於絕對時間時序邏輯的運算符

對於絕對時間時序邏輯,請使用下表中所述的運算符。

運算符 語法 說明

after

after(n, sec)

after(n, msec)

after(n, usec)

n 是任意正數或表達式。secmsec 和 usec 是表示自關聯狀態激活後已用仿真時間的關鍵字。

如果自關聯狀態激活後,已用仿真時間達到指定的 n 秒 (sec)、毫秒 (msec) 或微秒 (usec),則返回 true。否則,運算符返回 false

每次關聯狀態重新激活時,secmsec 和 usec 的計數器重置爲 0。

before

before(n, sec)

before(n, msec)

before(n, usec)

n 是任意正數或表達式。secmsec 和 usec 是表示自關聯狀態激活後已用仿真時間的關鍵字。

如果自關聯狀態激活後,已用仿真時間未到指定的 n 秒 (sec)、毫秒 (msec) 或微秒 (usec),則返回 true。否則,運算符返回 false

每次關聯狀態重新激活時,secmsec 和 usec 的計數器重置爲 0。

temporalCount

temporalCount(sec)

temporalCount(msec)

temporalCount(usec)

secmsec 和 usec 是表示自關聯狀態激活後已用仿真時間的關鍵字。

計算並返回自關聯狀態激活後已用的仿真時間,以指定的秒數 (sec)、毫秒數 (msec) 或微秒數 (usec) 表示。

每次關聯狀態重新激活時,secmsec 和 usec 的計數器重置爲 0。

elapsed

elapsed(sec)

等效於 temporalCount(sec)。返回自關聯狀態激活後已用的仿真時間,以秒 (sec) 表示。

每次關聯狀態重新激活時,sec 的計數器重置爲 0。

duration

duration(C)

在條件表達式 C 變爲 true 後返回秒數。如果條件表達式變爲 false,則 duration 運算符會重置。如果 duration 運算符用於狀態中,則當進入包含該運算符的狀態時,該運算符會重置。如果 duration 運算符用在轉移中,則當進入該轉移的來源狀態後,該運算符重置。

 

絕對時間時序邏輯示例

 

下面的示例說明了絕對時間時序邏輯在狀態動作和轉移中的運用。

運算符 用法 示例 說明

after

狀態動作

(on after)

on after(12.3, sec): temp = LOW;

自狀態激活並執行 12.3 秒的仿真後,temp 變量變爲 LOW

after

轉移

after(8, msec)

自狀態激活並執行 8 毫秒的仿真後,會發生轉出關聯狀態的轉移。

after

轉移

after(5, usec)

自狀態激活並執行 5 微秒的仿真後,會發生轉出關聯狀態的轉移。

before

轉移

[temp > 75 && before(12.34, sec)]

如果變量 temp 超過 75,並且自狀態激活後所經過的時間不到 12.34 秒,則會發生轉出關聯狀態的轉移。

temporalCount

狀態動作

(exit)

ex: y = temporalCount(sec);

此動作對狀態激活和反激活之間所經過的仿真時間進行計數並返回秒數。

4.怎樣定義stateflow輸入輸出接口?這裏給出三種方法

(1)通過窗口chart/Add Input & output,如下圖:

 

(2)第二種方法通過工具欄中的Model Explorer

(3)直接點擊編譯,會報錯彈出窗口,在彈出的窗口裏面選擇輸入,輸出,再次編譯就不會報錯。這裏不給出圖片,自己試一下即可知道。(這裏別忘了加默認的初始狀態)

 

4.講了這麼多,教大家一個實例

其實這個x==1條件可以看作家裏總開關有電,switch_on表示控制燈的開關爲開,light=1 表示燈亮。燈的變量設置如下:light爲輸出,switch_off爲輸入端口2,爲下降沿,switch_on輸入端口1,上升沿,x爲輸入,端口爲1,event是爲默認轉移條件設置的,設置爲輸入3,設置爲Either。是爲了剛初始化時,狀態爲默認的off。

 

整體完成如上:當初始開始時,爲off狀態,爲當x=1,觸發從0到1,燈亮,輸出爲1,1到0燈滅,輸出爲0。

程序的下載地址:https://download.csdn.net/download/caokaifa/11437934

5.連接節點的應用

這個相當於if ..elseif ..else...這個沒什麼難的,直接搭建即可

6.stateflow回調函數調用

首先,隨便搭建一個stateflow模塊或用我上面搭建的stateflow例子都可以:我就搭建了一個如下圖

然後右擊stateflow模塊,點擊Properties如下圖:

 

 

 

然後出現如下圖:

然後點擊Callbacks,然後點擊ClipboardFcn,添加disp("ClipboardFcn")

 

這樣,點擊OK,保存就好了,現在看調用函數的效果。回到工程,右擊點擊剪切stateflow模塊,如下圖:

這時,matlab輸入命令窗口出現開始設置的disp顯示內容。

其他的調用函數按照上面操作即可。

注意:這裏可能有的回調函數沒有顯示你的內容,可能是因爲函數對disp有點bug,你可以隨便定義i=9,運行看工作空間有沒有就知道有沒有執行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章