在 Simulink 中面对一个动辄上千个模块、信号线密集到几乎无法滚动查找的模型时,很多工程师心里都会冒出同一个念头:如果这套逻辑能像写函数一样,定义一次、引用多次、修改一处全局生效,该有多省心。
R2020a 之前,这个问题在 Simulink 里并没有特别优雅的解法。普通 Subsystem 只能复制粘贴,改一次要手动同步 N 处;Model Reference 则要求把被复用的部分抽成一个完整的顶层模型,要配置接口、仿真模式、求解器边界,对于只是想复用一个“子系统级别的小模块”来说,成本明显偏高。R2020a 推出的 Subsystem Reference 模块,正好补上了这个空白:子系统内容被保存为独立的 .slx 文件,主模型里只放一个引用块去指向它,同一份定义可以被多个模型、多个实例同时引用。
这篇文章会从 Simulink 常用模块库的定位出发,讲清楚四个问题:Subsystem Reference 到底是什么、它和普通 Subsystem、Model Reference 的区别在哪里;如何实操创建并复用一个最小示例;在工程建模中会遇到哪些坑;以及项目选型时应该怎么判断。读完以后,你应该能判断自己的模型是否适合用这个模块,并且能够直接上手跑通一个完整流程。
1. 这篇文章真正要解决的问题
很多团队在推进 Simulink 模型化开发时,通常都会经历三个阶段。第一阶段,模型很小,所有逻辑直接画在一张图里,简单直接。第二阶段,模型变大,开始用 Subsystem 做层级分组,把功能模块化。第三阶段,模型很大,多个工程师同时在一个模型文件上开发,反复出现合并冲突、修改遗漏、副本同步问题。
大部分团队长期停留在第二阶段和第三阶段之间。最常见的做法是“复制一个子系统副本”,把同一个算法模块从别的模型里直接复制粘贴过来。这个做法短期有效,但会留下三个隐患。
第一,修改不同步。算法参数、中间变量、模型配置在任何一个副本上被独立修改后,其他副本不会自动更新。仿真结果对不上时,很难判断到底是哪一份副本没有被同步到。
第二,文件膨胀。一个模型文件里塞进几十个内容几乎相同的子系统,模型保存速度、编译速度都会下降。用 Git 对比模型变更时,差异粒度非常粗,很难定位到某个具体子系统的改动。
第三,协作冲突。两个人同时打开同一个模型文件做修改,合并时会产生大量冲突。即便用版本控制工具处理二进制模型文件,也只能做到“模型级”的对比,无法精确到子系统内部。
Model Reference 是一个可用的解法,但成本偏高。模型引用要求把被引用的系统提升为“完整模型”,需要显式声明接口、仿真模式、代码生成构型等。我只是想复用一个输入输出不过两三个、内部逻辑也不算复杂的算法单元,用 Model Reference 有点杀鸡用牛刀。
Subsystem Reference 正好落在中间层。它把子系统内容作为独立文件抽出来,但保留了子系统本身的轻量化属性。你不需要配置完整的模型引用接口,不需要考虑独立仿真模式,双击引用块就能进入一个类似模型编辑器的页面,修改后保存,所有引用该定义的地方自动生效。
这篇文章的目标读者,比较适合以下三类:
- 已经能用 Simulink 搭建完整仿真模型,但正在寻找更科学的模型组织方式的工程师;
- 正在做汽车电子、机器人、电力电子方向,模型规模已经膨胀到需要模块复用的开发者;
- 负责 Simulink 模型评审、模型库建设、团队建模规范制定的人员。
如果你是刚接触 Simulink 的初学者,这篇文章可以收藏作为进阶路线的参考。先跑通文章里的最小示例,等模型规模上来后再对照使用,收获会更大。
2. Simulink 常用模块库与 Subsystem Reference 的定位
要理解 Subsystem Reference,需要先把它放回 Simulink 常用模块库的全景中看。
在 Simulink 的 Library Browser 里,模块按功能被分成若干大类。日常建模中用到最多的几类如下:
- Sources(信号源):包含 Constant、Step、Sine Wave、Ramp、Clock、Signal Builder 等,负责产生仿真输入信号。
- Sinks(输出与显示):包含 Scope、Display、To Workspace、To File 等,用于查看和导出仿真结果。
- Math Operations(数学运算):包含 Gain、Sum、Product、Divide、Math Function、Abs 等,用于构建控制律、滤波器和数值运算。
- Signal Routing(信号路由):包含 Mux、Demux、Bus Creator、Bus Selector、Selector、Switch 等,负责信号的合并、拆分和选择。
- Logic and Bit Operations(逻辑与位运算):包含 Logical Operator、Relational Operator、Bitwise Operator 等,用于布尔逻辑和状态判断。
- Continuous 与 Discrete(连续与离散系统):包含 Integrator、Transfer Fcn、Zero-Pole、Unit Delay、Discrete Transfer Fcn 等,支撑连续域和离散域的建模。
- Ports & Subsystems(端口与子系统):这是 Simulink 模型结构化的核心,Subsystem、Atomic Subsystem、Subsystem Reference、Model Reference 都放在这个分类下。
Ports & Subsystems 这一类,解决的是模型组织问题:当逻辑太多、一张画布放不下时,如何把它组织成可读、可复用、可并行开发的单元。这个分类下的模块分工很明确。
普通 Subsystem 是最基础的层级封装,所有内容保存在父模型中,双击即可进入编辑,适合局部整理。Atomic Subsystem 在普通子系统基础上增加了“原子执行”属性,强调内部逻辑在仿真调度中作为一个整体执行。Enabled Subsystem 带使能端口,受外部门控信号控制是否执行。Triggered Subsystem 带触发端口,在触发边沿到来时执行。Model Reference 引用一个完整模型文件,适合大型分布式开发。R2020a 加入的 Subsystem Reference,引用一个独立的子系统文件,定位介于“内部子系统封装”和“顶层模型引用”之间。
从模块库的组织逻辑来看,Subsystem Reference 最接近“把普通 Subsystem 独立成文件”。它仍然是一个子系统模块,不需要配置独立的仿真周期、求解器或代码生成目标,只是内容不再内嵌在父模型中,而是存放在单独文件里。理解这一点,后面操作时就不会产生歧义。
需要强调的地方是:Subsystem Reference 不是一个新增的算法计算模块,而是一个“容器类模块”。它和 Model Reference 类似,内容由外部文件决定。真正决定运算逻辑的,是那个被引用的 .slx 文件里的内部模块结构。
3. Subsystem Reference 核心概念与原理
Subsystem Reference 的核心概念可以拆成三层来看。
第一层是定义