检测数据和表达式值的更改
Stateflow® 图可以检测时间步之间数据和表达式的值的更改。您可以:
使用更改检测运算符来确定变量的值何时发生更改。
使用边沿检测运算符来确定表达式的值何时高于或低于阈值。
要在图设置变量值时生成隐式局部事件,请使用 change
运算符。有关详细信息,请参阅通过使用隐式事件控制图行为。
更改检测操作
要检测 Stateflow 数据中的更改,请使用下表列出的运算符。
运算符 | 语法 | 描述 | 示例 |
---|---|---|---|
hasChanged | tf = hasChanged(data_name) | 如果当前时间步开始时 data_name 的值不同于前一时间步开始时 data_name 的值,则返回 1 (true )。否则,运算符返回 0 (false )。 | 如果矩阵 [hasChanged(M)] |
如果矩阵 在使用 MATLAB® 作为动作语言的图中,请使用: [hasChanged(M(1,3))] 在使用 C 语言作为动作语言的图中,请使用: [hasChanged(M[0][2])] | |||
hasChangedFrom | tf = hasChangedFrom(data_name,value) | 如果 data_name 的值等于在上一时间步开始时指定的 value 并且不同于在当前时间步开始时的值,则返回 1 (true )。否则,运算符返回 0 (false )。 | 如果结构体 [hasChangedFrom(struct,structValue)] |
hasChangedTo | tf = hasChangedTo(data_name,value) | 如果 data_name 的值不等于在上一时间步开始时指定的 value 并且等于在当前时间步开始时的 value ,则返回 1 (true )。否则,运算符返回 0 (false )。 | 如果结构体字段 [hasChangedTo(struct.field,5)] |
注意
如果多个输入事件在同一时间步内发生,这些运算符可以检测输入事件之间数据值的更改。
包含更改检测的 Stateflow 图的示例
此模型显示运算符 hasChanged
、hasChangedFrom
和 hasChangedTo
如何检测输入信号中的特定更改。在此示例中,Ramp (Simulink) 模块向 Stateflow 图发送了一个离散的上升时间信号。
模型使用步长为 1 的定步长求解器。信号在每个时间步递增 1。图分析输入信号 u
是否发生了以下更改:
自上一时间步以来发生的任何更改
更改为值 3
从值 3 更改为其他值
为了检查信号,Stateflow 图会在转移动作中调用三个更改检测运算符。图将返回值输出为 y1
、y2
和 y3
。
在仿真过程中,Scope (Simulink) 模块显示图的输入和输出信号。
u
的值在每个时间步递增 1。y1
的值在时间t = 1
时从 0 变为 1。由于u
在随后的每个时间步都会继续变化,因而y1
的值将保持在 1。当时间
t = 4
时,u
的值从 0 变为 1,y2
的值从 3 变为 4。y2
的值在一个时间步后回到 0。当时间
t = 3
时,u
的值从 0 变为 1,y3
的值从 2 变为 3。y3
的值在一个时间步后回到 0。
更改检测的限制
Stateflow 图的类型决定了更改检测所支持数据的作用域:
MATLAB 中的独立 Stateflow 图:仅限局部
Simulink® 中使用 MATLAB 作为动作语言的图:仅限输入
Simulink 中使用 C 语言作为动作语言的图:输入、输出、局部或数据存储内存
参量 data_name
可以是:
标量变量。
矩阵或矩阵的元素。
如果
data_name
是矩阵,当运算符检测到data_name
的任何元素发生变化时,运算符将返回true
。使用数值或计算结果为常量整数的表达式对矩阵元素进行索引。请参阅Stateflow 中向量和矩阵的运算。
结构体或结构体中的字段。
如果
data_name
是结构体,当更改检测运算符检测到data_name
的任何字段发生变化时,运算符将返回true
。使用圆点表示法对结构体中的字段进行索引。请参阅对 Stateflow 结构体进行索引并赋值。
结构体字段或矩阵元素的任何有效组合。
参量 data_name
不能为非平凡表达式或自定义代码变量。
注意
MATLAB 中的独立图不支持对矩阵的元素或结构体中的字段进行更改检测。
对于 hasChangedFrom
和 hasChangedTo
运算符,参量 value
可以是解析所得的值与 data_name
可比的任意表达式。
如果
data_name
是标量,则value
必须解析为标量值。如果
data_name
是矩阵,则value
必须解析为与data_name
具有相同维度的矩阵值。在使用 C 语言作为动作语言的图中,
value
也可以解析为标量值。图通过标量扩展将data_name
与一个矩阵进行比较,该矩阵的每个元素都等于value
指定的值。请参阅为矩阵的所有元素赋值。如果
data_name
是结构体,则value
必须解析为一个字段设定与data_name
完全匹配的结构体值。
如果从使用更改检测运算符的图中生成代码,并且启用行优先数组布局,则代码生成会产生错误。在生成代码之前,请启用列优先数组布局。请参阅Select Array Layout for Matrices in Generated Code。
边沿检测运算符
要确定表达式的值何时高于或低于阈值,请使用下表中列出的运算符。
运算符 | 语法 | 描述 | 示例 |
---|---|---|---|
crossing | tf = crossing(expression) | 如果满足以下条件,则返回 1 (
否则,运算符返回 0 ( 此运算符模拟触发器类型设置为 | 如果输入数据 [crossing(signal-2.5)] 当表达式 |
falling | tf = falling(expression) | 如果满足以下条件,则返回 1 (
否则,运算符返回 0 ( 此运算符模拟触发器类型设置为 | 如果输入数据 [falling(signal-2.5)] 当表达式 |
rising | tf = rising(expression) | 如果满足以下条件,则返回 1 (
否则,运算符返回 0 ( 此运算符模拟触发器类型设置为 | 如果输入数据 [rising(signal-2.5)] 当表达式 |
注意
像 Trigger 模块一样,当 expression
参量在三个连续时间步内将值从正值到零再到负值或从负值到零再到正值时,这些运算符会检测到单一边沿事件。当表达式的值变为零时,出现边沿事件。
启用了边沿检测的图的示例
此模型显示运算符 crossing
、falling
和 rising
如何检测输入信号中的边沿。在此示例中,Pulse Generator (Simulink) 模块向图发送方波。
模型使用步长为 1 的定步长求解器。输入信号 u
的值每两个时间步在 0 和 5 之间交替变化。图分析输入信号 u
是否出现了以下边沿事件:
越过阈值 2.5 的下降沿或上升沿
升至阈值 2.5 之上的上升沿
降至阈值 2.5 以下的下降沿
为了检查信号,Stateflow 图会在一个转移动作中调用三个边沿检测运算符。图将返回值输出为 y1
、y2
和 y3
。
在仿真过程中,Scope (Simulink) 模块显示图的输入和输出信号。
u
的值每隔一个时间步在 0 和 5 之间交替变化。y1
的值在时间t = 1
、3
、5
和7
从 0 更改为 1,在这些时刻表达式u-2.5
的值更改符号。y1
的值在一个时间步后回到 0。y2
的值在时间t = 1
和5
从 0 变为 1,在这些时刻表达式u-2.5
的值从负值变为正值。y2
的值在一个时间步后回到 0。y3
的值在时间t = 3
和7
从 0 变为 1,在这些时刻表达式u-2.5
的值从正值变为负值。y3
的值在一个时间步后回到 0。
边沿检测的限制
仅 Simulink 模型中的 Stateflow 图支持边沿检测。
参量 expression
:
必须为标量值表达式
可以组合图输入数据、常量、不可调参数、连续时间局部数据和来自基于 Simulink 状态的状态数据
可以包括标量变量、矩阵元素、结构体中的字段或结构体字段和矩阵元素的任何有效组合的加法、减法和乘法
使用数值或计算结果为常量整数的表达式对矩阵元素进行索引。
仅在转移条件下支持连续时间局部数据和来自基于 Simulink 的状态的状态数据的边沿检测。
在原子子图中,将您在边沿检测表达式中使用的所有输入数据映射到主图中的输入数据或不可调参数。将这些输入数据映射到输出数据、局部数据或可调参数会导致未定义的行为。
使用边沿检测运算符的 Stateflow 图不支持工况点。
更改检测和边沿检测的实现
图通过计算在时间步边界处的值来检测图数据和表达式中的更改。Stateflow 图会将上一执行步开始时的值与当前执行步开始时的值进行比较。
例如,当您使用 x
参量调用 hasChanged
运算符时,Stateflow 图会在局部变量中双缓冲 x
的值。
局部缓冲: | 描述 |
---|---|
x_prev | 上一时间步开始时数据 |
x_start | 当前时间步开始时数据 |
为了检测更改,图会在它被某一事件触发之后且在开始执行之前对数据值进行双缓冲。如果 xprev
和 xstart
的值匹配,更改检测运算符将返回 false
以指示无更改;否则返回 true
以指示有更改。下图将这些任务放到 Stateflow 图生命周期的上下文中。
边沿检测运算符的行为类似,不同之处在于它们将在上一个时间步开始时的表达式值 (xprev
) 与其当前值 (x
) 进行比较。这一实现上的差异允许连续时间图在子时间步内检测局部数据的边沿。
局部数据中的瞬时值更改
更改检测运算符会尝试仅在时间边界时对局部图变量进行求值,从而滤除这些变量中的临时更改。图仅在执行步结束时计算一次指定的局部变量。更改检测运算符的返回值将保持不变,即使局部变量的值在给定时间步内有波动也是如此。例如,假设在当前时间步中,局部变量 temp
的值自上一个时间步以来发生了变化,但随后又回到原始值。运算符 hasChanged(temp)
会在下一时间步返回 false
,表示没有发生任何更改。
边沿检测运算符则不同,它可以在子时间步内检测连续时间局部数据中的边沿。例如,假设 p
是具有负导数的连续时间局部变量。然后,当 p
将符号从正变为负时,运算符 falling(p)
在子时间步内返回 true
。
检测输入事件或超时间步迭代之间的值更改
当同一时间步内发生多个输入事件时,或当您启用超时间步语义时,图每次执行时都会更新 xprev
和 xstart
缓冲区。图检测输入事件和超时间步迭代之间值的更改,即使在给定时间步内发生了多次更改也一样。有关详细信息,请参阅Use Events to Execute Charts和Super Step Semantics。
另请参阅
change
| crossing
| falling
| hasChanged
| hasChangedFrom
| hasChangedTo
| rising