手把手教用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,运行看工作空间有没有就知道有没有执行。

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