Main Content

检测数据和表达式值的更改

Stateflow® 图可以检测时间步之间数据和表达式的值的更改。您可以:

  • 使用更改检测运算符来确定变量的值何时发生更改。

  • 使用边沿检测运算符来确定表达式的值何时高于或低于阈值。

要在图设置变量值时生成隐式局部事件,请使用 change 运算符。有关详细信息,请参阅Control Chart Behavior by Using Implicit Events

更改检测操作

要检测 Stateflow 数据中的更改,请使用下表列出的运算符。

运算符语法描述示例
hasChangedtf = hasChanged(data_name)如果当前时间步开始时 data_name 的值不同于前一时间步开始时 data_name 的值,则返回 1 (true)。否则,运算符返回 0 (false)。

如果矩阵 M 中的任一元素自上一时间步或输入事件以来已更改值,则发生转出状态的转移。

[hasChanged(M)]

如果矩阵 M 的第 1 行和第 3 列中的元素自上一时间步或输入事件以来已更改值,则发生转出状态的转移。

在使用 MATLAB® 作为动作语言的图中,请使用:

[hasChanged(M(1,3))]

在使用 C 语言作为动作语言的图中,请使用:

[hasChanged(M[0][2])]
hasChangedFromtf = hasChangedFrom(data_name,value)如果 data_name 的值等于在上一时间步开始时指定的 value 并且不同于在当前时间步开始时的值,则返回 1 (true)。否则,运算符返回 0 (false)。

如果结构体 struct 的上一个值等于 structValue 并且 struct 的任一字段自上一时间步或输入事件以来已更改值,则发生转出状态的转移。

[hasChangedFrom(struct,structValue)]
hasChangedTotf = hasChangedTo(data_name,value)如果 data_name 的值不等于在上一时间步开始时指定的 value 并且等于在当前时间步开始时的 value,则返回 1 (true)。否则,运算符返回 0 (false)。

如果结构体字段 struct.field 自上一时间步或输入事件以来已更改为值 5,则发生转出状态的转移。

[hasChangedTo(struct.field,5)]

注意

如果多个输入事件在同一时间步内发生,这些运算符可以检测输入事件之间数据值的更改。

包含更改检测的 Stateflow 图的示例

此模型显示运算符 hasChangedhasChangedFromhasChangedTo 如何检测输入信号中的特定更改。在此示例中,Ramp (Simulink) 模块向 Stateflow 图发送了一个离散的上升时间信号。

模型使用步长为 1 的固定步长求解器。信号在每个时间步递增 1。图分析输入信号 u 是否发生了以下更改:

  • 自上一时间步以来发生的任何更改

  • 更改为值 3

  • 从值 3 更改为其他值

为了检查信号,Stateflow 图会在转移动作中调用三个更改检测运算符。图将返回值输出为 y1y2y3

在仿真过程中,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 中的独立图不支持对矩阵的元素或结构体中的字段进行更改检测。

对于 hasChangedFromhasChangedTo 运算符,参数 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

边沿检测运算符

要确定表达式的值何时高于或低于阈值,请使用下表中列出的运算符。

运算符语法描述示例
crossingtf = crossing(expression)

如果满足以下条件,则返回 1 (true):

  • expression 的前一个值为正值,其当前值为零或负值。

  • expression 的前一个值为零,其当前值为非零。

  • expression 的前一个值为负值,其当前值为零或正值。

否则,运算符返回 0 (false)。

此运算符模拟触发器类型设置为 eitherTrigger (Simulink) 模块的行为。

如果输入数据 signal 的值越过阈值 2.5,则发生转出状态的转移。

[crossing(signal-2.5)]

当表达式 signal-2.5 的值从正变为负、从负变为正、从零变为非零或从非零变为零时,检测到边沿事件。

fallingtf = falling(expression)

如果满足以下条件,则返回 1 (true):

  • expression 的前一个值为正值,其当前值为零或负值。

  • expression 的前一个值为零,其当前值为负值。

否则,运算符返回 0 (false)。

此运算符模拟触发器类型设置为 fallingTrigger (Simulink) 模块的行为。

如果输入数据 signal 的值下降到低于阈值 2.5,则发生转出状态的转移。

[falling(signal-2.5)]

当表达式 signal-2.5 的值从正值变为负值、从正值变为零或从零变为负值时,检测到下降沿。

risingtf = rising(expression)

如果满足以下条件,则返回 1 (true):

  • expression 的前一个值为负值,其当前值为零或正值。

  • expression 的前一个值为零,其当前值为正值。

否则,运算符返回 0 (false)。

此运算符模拟触发器类型设置为 risingTrigger (Simulink) 模块的行为。

如果输入数据 signal 的值上升到高于阈值 2.5,则发生转出状态的转移。

[rising(signal-2.5)]

当表达式 signal-2.5 的值从负值变为正值、从负值变为零或从零变为正值时,检测到上升沿。

注意

Trigger 模块一样,当 expression 参数在三个连续时间步内将值从正值到零再到负值或从负值到零再到正值时,这些运算符会检测到单一边沿事件。当表达式的值变为零时,出现边沿事件。

启用了边沿检测的图的示例

此模型显示运算符 crossingfallingrising 如何检测输入信号中的边沿。在此示例中,Pulse Generator (Simulink) 模块向图发送方波。

模型使用步长为 1 的固定步长求解器。输入信号 u 的值每两个时间步在 0 和 5 之间交替变化。图分析输入信号 u 是否出现了以下边沿事件:

  • 越过阈值 2.5 的下降沿或上升沿

  • 升至阈值 2.5 之上的上升沿

  • 降至阈值 2.5 以下的下降沿

为了检查信号,Stateflow 图会在一个转移动作中调用三个边沿检测运算符。图将返回值输出为 y1y2y3

在仿真过程中,Scope (Simulink) 模块显示图的输入和输出信号。

  • u 的值每隔一个时间步在 0 和 5 之间交替变化。

  • y1 的值在时间 t = 1357 从 0 更改为 1,在这些时刻表达式 u-2.5 的值更改符号。y1 的值在一个时间步后回到 0。

  • y2 的值在时间 t = 15 从 0 变为 1,在这些时刻表达式 u-2.5 的值从负值变为正值。y2 的值在一个时间步后回到 0。

  • y3 的值在时间 t = 37 从 0 变为 1,在这些时刻表达式 u-2.5 的值从正值变为负值。y3 的值在一个时间步后回到 0。

边沿检测的限制

仅 Simulink 模型中的 Stateflow 图支持边沿检测。

参数 expression

  • 必须为标量值表达式

  • 可以组合图输入数据、常量、不可调参数、连续时间局部数据和来自基于 Simulink 状态的状态数据

  • 可以包括标量变量、矩阵元素、结构体中的字段或结构体字段和矩阵元素的任何有效组合的加法、减法和乘法

使用数值或计算结果为常量整数的表达式对矩阵元素进行索引。

仅在转移条件下支持连续时间局部数据和来自基于 Simulink 的状态的状态数据的边沿检测。

在原子子图中,将您在边沿检测表达式中使用的所有输入数据映射到主图中的输入数据或不可调参数。将这些输入数据映射到输出数据、局部数据或可调参数会导致未定义的行为。

使用边沿检测运算符的 Stateflow 图不支持工况点。

更改检测和边沿检测的实现

图通过计算在时间步边界处的值来检测图数据和表达式中的更改。Stateflow 图会将上一执行步开始时的值与当前执行步开始时的值进行比较。

例如,当您使用 x 的参数调用 hasChanged 运算符时,Stateflow 图会在局部变量中双缓冲 x 的值。

局部缓冲:描述
x_prev

上一时间步开始时数据 x 的值

x_start

当前时间步开始时数据 x 的值

为了检测更改,图会在它被某一事件触发之后且在开始执行之前对数据值进行双缓冲。如果 xprevxstart 的值匹配,更改检测运算符将返回 false 以指示无更改;否则返回 true 以指示有更改。下图将这些任务放到 Stateflow 图生命周期的上下文中。

Flowchart detailing double-buffering of data values for change detection.

边沿检测运算符的行为类似,不同之处在于它们将在上一个时间步开始时的表达式值 (xprev) 与其当前值 (x) 进行比较。这一实现上的差异允许连续时间图在子时间步内检测局部数据的边沿。

局部数据中的瞬时值更改

更改检测运算符会尝试仅在时间边界时对局部图变量进行求值,从而滤除这些变量中的临时更改。图仅在执行步结束时计算一次指定的局部变量。更改检测运算符的返回值将保持不变,即使局部变量的值在给定时间步内有波动也是如此。例如,假设在当前时间步中,局部变量 temp 的值自上一个时间步以来发生了变化,但随后又回到原始值。运算符 hasChanged(temp) 会在下一时间步返回 false,表示没有发生任何更改。

边沿检测运算符则不同,它可以在子时间步内检测连续时间局部数据中的边沿。例如,假设 p 是具有负导数的连续时间局部变量。然后,当 p 将符号从正变为负时,运算符 falling(p) 在子时间步内返回 true

检测输入事件或超时间步迭代之间的值更改

当同一时间步内发生多个输入事件时,或当您启用超时间步语义时,图每次执行时都会更新 xprevxstart 缓冲区。图检测输入事件和超时间步迭代之间值的更改,即使在给定时间步内发生了多次更改也一样。有关详细信息,请参阅Use Events to Execute ChartsSuper Step Semantics

另请参阅

| | | | | |

相关主题