1. 概念讲解
1.1 为什么要观察消息
Simulink 用消息(Messages)在模型组件之间通信。当模型中存在一条或多条消息信号时,普通的信号观察只拿到载荷数据,却看不到消息在仿真中"何时到达、何时离开、是否被丢弃"这一类事件语义。为此,观察者在为消息信号创建 Observer 模型时,会自动生成与该消息关联的元数据(metadata),让你既能测试消息数据本身,也能验证消息属性。
1.2 消息总线元素
为消息信号创建观察者时,Observer 模型会自动包含一个 Observer Port 模块和一个 Bus Selector 模块。总线有两个元素:
OrigPayload:正在被观察的消息数据本身。
Metadata,内含四个元素:
sltestEventMetadata.Message.id:被观察消息的 ID,返回 int32;sltestEventMetadata.Message.order:该消息动作在仿真中的顺序,返回 int32;sltestEventMetadata.Message.eventType:事件类型,返回slTestEventType对象,合法取值为 MessageArrival、MessageDeparture、MessageDrop、Invalid;sltestEventMetadata.Message.time:消息发送、接收或丢弃时的仿真时间,返回 double。
1.3 为什么要观察条件子系统信号
条件子系统(Conditional Subsystem)由一个外部信号使能或触发。观察条件子系统的意义在于:检查该子系统是否只在控制信号激活它时才运行,并顺带检查子系统内部其他功能。可加观察者的模块类型包括:Enabled Subsystem、Triggered Subsystem、Enabled and Triggered Subsystem、If Action Subsystem、Switch Case Action Subsystem。
当你为条件子系统内的信号加观察者时,Simulink 会在主模型顶层加 Observer Reference 模块,并创建一个 Observer 模型——该模型里的 Observer Port 被放在一个非周期分区(aperiodic partition)中。这个分区控制条件数据的调度,分区内的测试逻辑也随之条件化运行。分区是创建观察者时自动生成的,你无需改动其调度设置;可以改分区名,但名字在模型内必须唯一。
2. 操作步骤 / 工作流
2.1 添加消息观察者
在含有输出消息模块的模型中,右键要观察的输出消息信号。注意:来自异步采样时间模块的消息,仅对自生采样时间的 SimEvents 模块支持。
选择 Observers > Observe selected signals > New Observer,为该消息信号创建 Observer 模型。主模型加入 Observer Reference 模块,新 Observer 模型内含一个 Observer Port 与一个 Bus Selector(两路输出 OrigPayload 与 Metadata)。
把总线输出接到 Test Assessment 模块或 Stateflow 图等验证模块,编写分析或验证消息数据/元数据的逻辑。
2.2 添加条件子系统观察者
在条件子系统内部,右键要观察的信号。
选择 Observers > Observe selected signals > New Observer;或者选中信号后悬停省略号打开操作条,点击 Observe in New Observer。Simulink 在主模型顶层加 Observer Reference 模块并新建 Observer 模型,其中有一个含 Observer Port 与 Terminator 的非周期分区。
用验证模块(如 Test Assessment 或 Verification Subsystem)替换 Terminator,接到 Observer Port 输出,编写分析/验证逻辑。
从主模型运行,不要从 Observer 模型运行。
3. 示例
3.1 消息观察:Overflow 模型
Overflow 模型中,Sine Wave2 模块每 0.1 秒发送一次数据,而 Receive2 模块每 0.5 秒才接收一次;Queue2 FIFO 最多缓存三条消息,因此会溢出、丢弃部分消息。该模型已通过选中消息信号、右键选 Observers > Observe selected signals > New Observer 建好观察者,Observer Reference 模块自动加入主模型。
% 打开 Overflow 示例模型(已含 Observer 模型) open_system('Overflow') % 双击主模型中的 Observer 块,或用命令打开其 Observer 模型 open_system('Overflow_Observer_1')% 打开 Overflow 示例模型(已含 Observer 模型) open_system('Overflow') % 双击主模型中的 Observer 块,或用命令打开其 Observer 模型 open_system('Overflow_Observer_1')
Observer 模型含 Send、Receive 两个 Observer Port,分别对应主模型中选中的两条信号;每个 Port 接一个 Bus Selector(两路输出)。总线输出再接到两个 Stateflow 图分析消息数据。其中接收侧图的逻辑用于验证:Queue 溢出丢消息后,消息数据与元数据未被破坏。具体判据包括:正弦数据在 0 到 1 的预期范围内;消息顺序号与仿真时间递增且每个 order 值唯一;消息事件类型合法。
3.2 条件子系统观察:ObserveCondSubsys 模型
该模型用正弦波控制信号作为 Enabled Subsystem 的输入,使能子系统仅在正弦输入为正时激活。
% 打开条件子系统观察示例 open_system('ObserveCondSubsys')按指南步骤:打开 Enabled Subsystem,选中 Integrator 模块输出信号,用操作条点击 Observe in New Observer。Simulink 在模型顶层加 Observer Reference 模块并打开新 Observer 模型,其内非周期分区含一个接 Terminator 的 Observer Port。随后双击打开 Aperiodic 分区,把 Terminator 换成 Test Assessment;打开 Test Assessment,删除 step_1_1 与 step_1_2,右键 step_1 清除 When decomposition 勾选,在 step_1 中加入verify(data >= 0);。从主模型点击 Run。
仿真结束后,在 MATLAB 命令行用如下命令查看评估结果:
run = Simulink.sdi.Run.getLatest; dataset = Simulink.sdi.exportRun(run.Id); assessmentSignalIndices = find(arrayfun(@(idx)... isequal(class(dataset{idx}),'sltest.Assessment'),... 1:dataset.numElements)); result = arrayfun(@(idx) dataset{idx}.Result,assessmentSignalIndices)verify语句给出通过结果,说明 Enabled Subsystem 及其关联观察者确实只在正弦输入为正时才激活。
4. 要点与注意事项
消息观察者自动生成的 Bus Selector 有 OrigPayload 与 Metadata 两路输出;事件类型是
slTestEventType对象,取值 MessageArrival / MessageDeparture / MessageDrop / Invalid,不要当普通字符串比较。异步采样时间消息的观察仅支持自生采样时间的 SimEvents 模块。
条件子系统观察的限制(指南 Limitations 节原文):一个非周期分区内只能有一个 Observer Port;非周期分区名在模型内必须唯一;不能编辑非周期分区中的调度触发器;不能在 Schedule Editor 中拖拽或重排条目,也不能用
simulink.schedule.OrderedSchedule重排;不能向 Observer 模型的非周期分区添加事件;Partition 子系统、Function-Call Subsystem 与 For Each Subsystem 模块不支持观察者。观察条件子系统时务必从主模型运行,而非从 Observer 模型运行。