浅谈Simulink/StateFlow建模
在汽车、工业控制、航空航天等行业,系统与软件开发中,基于模型的设计(Model based Design,简称MBD)逐步在替代传统的手工代码开发方式,在MBD领域,Matlab/Simulink作为通用化的建模与代码生成工具及其相关配套的工具链经过多年的积累,已经在国内外以上行业中被应用到产品的开发中。
在笔者所处的行业,由于对象的强非线性、多变量耦合性、时变特性以及被控对象和控制器的复杂性,在算法、容错处理以及控制逻辑多方面都有着较高和较复杂的要求,而且以上几方面常常是耦合在一起。基于以上考虑,不论是对被控对象还是控制器,建模是一件非常必要的事情。而Simulink是无疑是首选!
Simulink是从学生时代就接触的一种通用化建模工具,这一工具同样也陪伴着走上工作岗位。工作的前两年,因岗位关系,精力更多的投入到了控制算法的设计与验证上,相关算法最终也可以用MBD方式生成代码,同时也积累了一定的实际应用经验,当前负责的业务经过积累,有了相对的突破。但,随着接触更多更复杂的项目,总感觉有点缺憾,毕竟,个人对其他容错处理及控制业务逻辑的关注却相对较少,一定程度上造成了自己视野偏窄,岗位更多的定位在仿真验证上,这种外部限制也让自己“鞭长莫及”,有些对自我提高有帮助的工作因不是自己负责,无法做到全身性的学习与工作结合,对整个控制对象的控制过程的理解自然会有所欠缺。好在后来上层对当前工作职责的界限也有了重新的认知,有幸能在新项目中全面贯彻应用层都进行建模的要求,而且,代码的需求则直接源自更上层的需求以及模型,中远期必然是走MBD的方式。
一旦负责了整个应用层的建模,则必须将以上提到的容错处理、算法以及逻辑上进行通盘考虑。其实,这时候作为建模人员,最重要的就是根据需求结合实现进行架构设计,这里的架构设计,从我当前的认知来说,就是基于对工作场景的识别来进行功能的解耦与划分,场景又可以分为大场景与小场景,大场景通常采用状态机(StateFlow)来定义,小场景则既可以参考大场景来进行独立设计成模块也可以和功能模块进行耦合,视具体情况和个人经验而定,功能解耦则主要体现在不同功能最终需要用同一具体控制机构(被控对象与控制器之间还存在执行机构)来实现,这时候既要划分不同的功能,又要有最终具体控制机构的综合,在功能模块中实现功能,在具体控制机构模块中实现综合,这里的综合更多的体现在优先级的判定与最终输出量的抉择上,以上的经验也是经过很多项目的实践和妥协得来的,未必说得上通用最优,但可以说是针对复杂对象进行控制建模的较好的方法,是一种不错的架构设计实践。
经过几个月项目“锤炼”,多番需求的迭代与评审,多轮建模设计,在某个瞬间突然就开窍了,感觉一下子提高了需求的把控能力,无论是大方向还是具体细节,任何一个需求的更改,都能在脑子里快速进行需求的分解并建立初步的Simulink模型,即将需求具体化,而所谓的建模,其实就是编码实现,因为模块化的建模即对应相应的函数代码。
值得注意的是,Simulink模型通常都是基于数据流的,任何输入必须对应相应的输出,无论输出是中间量还是最终量都有其对应的物理含义,即便这种含义是人为赋予的;这与C代码在常规上还是区别的,在C语言中,某个全局变量可能随时会根据不同的状态进行变化,这样容易导致某个变量在多个功能中赋值,这种到处赋值的危害是显而易见的,除非实现约定好其中的某几个,否则无约束必将导致混乱。在Simulink建模中同时被提及的还有StateFlow这一功能,StateFlow可以建立状态机也可以进行流程设计,甚至可以调用Simulink模块,调用非常灵活,但灵活带来的也是复杂性,事实上StateFlow更接近于手工代码,为了实现某个相对复杂的逻辑采用StateFlow来实现,既有状态又有代码,这种形式实际上就是把C代码进行一种函数封装,但显然不具备通用性,与Simulink混用,用的不好很容易打断数据流,让人产生混乱,因此,从个人角度,一般不推荐大量使用StateFlow。建议在以下几种场景下使用:
1、对于大量使用的基准模块,若用StateFlow实现更简单;
2、对于大的场景定义,推荐使用,同时不推荐把具体功能放在状态机里边实现;
3、对于综合模块,推荐使用。
对于状态中常用的功能,则通过产生标识(进入与推出条件完备)与输出,由Simulink实现,来给综合模块进行抉择。
限于工作性质,只能啰啰嗦嗦这么多,估计也就自己听懂了,毕竟以上经验之谈有行业的局限性,未必适合其他的,权当是前阵子工作的一个小结吧。