关于基于模型的设计(MBD)⼀些概念和理解
本⽂转载于中国⾼级⼯程师董淑成的帖⼦内容。 之前有⽹友引发了⼀些讨论,为了⽅便⼤家进⼀步讨论,专门开贴,讨论基于模型的设计。题⽬有点⼤,以我的个⼈经历,我只能说说基于模型的嵌⼊式软件设计,我先抛砖引⽟吧。 先胡乱问⼏个⼤问题:
什么叫基于模型的设计?
为什么要基于模型的设计?
基于模型的设计过程中,需要做什么事情?
再问⼏个⼩问题:
模型验证是否必要?
模型验证有哪些⼯作可以做?
模型验证是否⼀定需要被控对象模型?
代码⽣成效率如何?
底层驱动是否要建模?
Embedded Coder(以前的RTW Embedded Coder)⽀持哪些芯⽚?
MIL、SIL、PIL、HIL的⽬的和实现⽅式?
如何定点化?
如何做代码集成?
也希望版上的⽹友提出各⾃的问题及见解,我们⼀起讨论。
什么叫基于模型的设计?
这是⼀个很⼤的话题,因为本⼈能⼒所限,仅讨论使⽤Simulink模型开发嵌⼊式软件的设计过程。也就是说,我只能聊基于模型的嵌⼊式软件设计。
我的理解是,通过对算法建模进⾏软件设计的过程,都可以叫基于模型的设计。
当然,如果仅限于算法建模,把Simulink/Stateflow当做Visio使⽤,⽽不去进⾏其他环节的⼯作,这样的基于模型设计是不完整的,可能对你的开发效率不会有很⼤的提升。
如果想通过基于模型的设计提升软件开发团队的开发效率,提⾼软件品质,我觉得⾄少有如下⼏点可以考虑:算法模型的验证
⽂档⾃动化
代码和模型的等效性验证
传统的开发过程中,我们有⼀个环节,需求捕获,也即,从系统需求分解出软件需求。
在基于模型的设计过程中,我们同样可以通过分析系统需求,获得软件需求。当然,根据系统需求的详细程度,我们可以考虑是否要写专门的软件需求。
在基于模型的软件设计中,我们主要关⼼的是系统的功能需求,或者说可以通过软件实现的功能需求。如果这部分需求在系统需求⽂档⾥已经有⾮常清楚的定义,那么我们可以以系统需求⽂档作为依据建⽴模型。
当然,如果系统需求不是⾜够清楚,那我们有必要编写专门的软件需求⽂档。如果不考虑Simulink/Stateflow的应⽤上的问题,也就是说,如果我们都是熟练的Simulink/Stateflow⽤户,那么建模过程的主要⼯作是需求分析,通俗点讲,需求弄清楚了,建模也就是⾮常简单的事情了。当然,建模的时候,要考虑未来的验证、实现以及后期维护的问题。
我个⼈的体会,这个阶段,不要着急建模,⼀定要先弄清需求,另外,建模的时候,模型架构⾮常重要。
有了模型之后,接下来要做什么事情?代码⽣成?
这是很多⽐较初级的⽤户容易犯的错误,犯这个错误的⽤户,很⼤程度上是因为没有弄清楚为什么要做基于模型的设计?
为什么要做基于模型的设计?我相信很多⽤户没有仔细考虑这个问题,很多⽤户做基于模型的设计的理由是:国外的公司都这么做,同⾏其他公司都这么做......
弄清为什么要基于模型的设计,也就是要弄清楚基于模型的设计到底可以给我们带来哪些好处?
很多⼈会⾮常⾃然的想到,代码⽣成,代码⽣成可以提⾼软件开发效率。没错,代码⽣成是⼀个很⼤的好处,但,代码⽣成不是唯⼀的,也不是最⼤的好处。
代码⽣成最⼤的好处是,算法的早期验证,之前NASA有研究表明,开发初期引⼊的bug,如果到了晚期才发现出来,那么修复这⼀的bug,会产⽣⾮常⼤的费⽤。所以,我们期望能够尽早的发现开发过程中引⼊的bug。
如何尽早的发现设计上的错误?传统的开发模式⾥,我们使⽤review的⽅式去发现错误,在质量体系ISO9001⾥⾯有定义,任何⼀份设计,都必须要评审。评审的⽬的,也就是为了发现这个阶段的错误,以防错误被带到后续的开发过程中。
⽽评审的效率,却是⾮常低下的。我想凡是参加评审的⽹友都会有体会。⽐如,我在做完⼀份设计之后,我会邀请我的同事来评审我的⼯作,⽽参加评审的这些同事,往往不能有⾜够的时间了解我的这份⼯作,⽽只能在评审会上听我介绍我做的⼯作,这样的评审,可能会发现⼀些⾮常明显的问题,除此之外的,很难发现问题。
评审作为⼀种⾮常传统的验证⽅式,并不能及时发现设计过程中引⼊的各种错误。⽽仿真,从效率上讲,要远⾼于评审,仿真更容易发现设计中的问题。
仿真是可以运⾏的,如果我们设定⼀些输⼊,运⾏模型之后,我们会得到相应的输出,我们很容易观测到此时的输出是否是我们期望的输出。
另外还有好处,仿真的结果是确定的,给定输⼊,就会得到确定的输出,当然,期望输出也是确定的。⽽不像评审,同样的⽂字,对于不同⼈,可能理解成不同的含义。
⽂档⾃动化
代码⽣成和早期验证之外,基于模型的设计,还可以给我们带来其他好处,⽐如⽂档⾃动化。
我们经常听到这样的说法:
我们终于把软件发布出去了,现在可以有时间补⽂档了...
下个⽉要audit了,所有同事都在补⽂档....
这⾥我要问:为什么要补⽂档?
补⽂档,我们可以从中得到两个⽅⾯的信息:
1.⽂档很重要,不能没有,⾄少从质量体系上要求我们必须有⽂档
2.⼯程师都不愿意写⽂档,是啊,如果愿意写⽂档的话,在开发过程中⾃然会把各类⽂档写起来的。
好,⼯程师不愿意写,开发过程中⼜不能少,如果计算机可以帮我们写,岂不是很美好的事情。基于模型的设计,可以帮助我们实现⽂档⾃动化,⾄少有相当⼤的⼀部分⽂档可以让计算机替我们写。
图形化设计
其实,基于模型的设计,还有⼀个天然的优势:图形化设计。
对于⼯程师来讲,图形化的东西,本⾝就⽐⽂字更容易理解,否则我们在软件开发过程中也不会去画流程图和状态机了。
所以总结⼀下,基于模型的设计可以从以下⽅⾯给我们提供便利:
1. 图形化设计
2. 早期验证
3. 代码⽣成
4. ⽂档⾃动化
前⾯我⼤概论述了为什么要做基于模型的设计,或者说基于模型的设计可以给我们带来哪些好处。这些好处,最终会⼤⼤提⾼开发效率,并且改善软件品质。 下⾯,我在说说基于模型的设计(MBD)⾥有哪些事情要做?
刘博⼠说的没错,基于模型的设计,⾃然模型最重要,如何建模,毫⽆疑问是最为重要的环节。 在软件产品开发中,建模活动⾥,耗时最多的,就应该是需求分析了,需求分析不仅包括如何正确理解软件需求,⽽且要考虑如何通过模型实现,真正的画模型的时间,相⽐之下并不多,如果Simulink/Stateflow⽤
的熟的话,真正打开MATLAB画模型的时间占建模阶段总时间的1/3都不到。 建模之后,接下来就是模型验证,验证,英⽂单词Verification,英⽂⾥⾯还有另外⼀个词Validation--确认,很多⼈不清楚这两个词之间的区别,通俗点讲:Verification是考察你是否正确的做了⼀件事,⽽Validation,则是考察你是否做出了正确的东西。⼀个强调的是过程,⼀个在乎的是结果。 闲话少说,咱们继续回到模型验证上来,通常模型验证包含如下活动:建模标准的检查、评审、单元测试、快速原型。(如果说的不完善,欢迎⼤家补充) 建模标准的检查,可以通过模型检查⼯具⾃动完成,建模标准检查的意义,和传统开发模式⾥C编码标准的意义⼀致,这⾥不展开了。 有关评审和单元测试,再专门开贴说吧。
模型验证之后,接下来就可以做代码⽣成了,有关代码⽣成,也专门讨论吧。
代码⽣成之后,需要做代码验证,基于模型的开发过程⾥⾯,SIL、PIL都是常⽤的代码验证⽅式。
在代码做完SIL或者PIL测试之后,要考虑软件集成了,即应⽤层软件,也就是通过Simulink模型⽣成的软件,和底层驱动软件之间的集成。
软件集成之后,后⾯的事情,基本上和传统的开发模式差不多了,当然,相对于传统的开发模式,你可以多⼀个HIL环节出来,不过话⼜说回来,即便是传统的开发模式,也⼀样可以有HIL这个环节的。
有关HIL的实现及⽬的,以后再说。再说说模型验证的必要性。 我在进⼊MathWorks之后,接触过很多
客户,不少客户在最初引⼊基于模型设计的时候,根本不在意模型验证⼯作,他们经常在模型编译通过之后就拿去⽣成代码,有了代码之后将代码下载到各种快速原型设备上去测试算法,Simulink的仿真功能基本上成了摆设。并且在这个阶段,不管我如何苦⼝婆⼼的给他们介绍模型验证的重要性,在他们那边,却总有各种各样的借⼝去省略模型验证环节,“项⽬时间太紧,模型来不及测”,“我们知道规范的开发流程,但是现在⼈⼿不够”。 当然,这类⽤户经常在这样折腾了⼀段时间之后,还是要回到模型测试上来,他们最终会发现,在HIL设备上测试算法,实在太难,当然,也有坚持的,坚持的结果就是他们所谓的基于模型的设计,开发效率⽐传统的开发模式⾼不了多少。 其实,这个问题我们可以这么去看,模型阶段的测试,我们是可以分模块进⾏的,⽽HIL上测试,基本上是集成之后的软件。⽐如,⼀个软件有10个模块,在HIL设备上,你很难分离出每个模块的bug,⽽如果是按模块做单元测试,则就是针对的⼀个具体的模块。打⼀个不算恰当的⽐⽅,我们都知道⼀块2克拉的钻⽯,价格肯定不是⼀块1克拉钻⽯的两倍。类似的,如果每个软件模块有2个bug,那么你从集成好的软件⾥去消除这20个bug,耗费的精⼒肯定不是从每个单元模块⾥去消除bug所耗精⼒的总和。 说⽩了,早期验证是⾮常重要的,很多软件⼯程的教材⾥都有相关的统计数据说明早期验证的重要性,对应到基于模型的开发过程,能在模型级别做的验证,⼀定不要拖到后续的环节中。 中国有句⽼话,“⼼急吃不了热⾖腐”,“项⽬时间紧”或者“⼈⼿不够”不能成为我们忽略模型测试的借⼝。继续说⼀下MBD开发过程中都有哪些验证⼯作(verification)要做。 模型出来并且可以编译之后,⾸先要做建模标准检查,这个过程使⽤⼯具(⽐如MathWorks公司的Simulink Verification & Validation提供的model advisor)⾃动化的完成,检查过后,修改模型中不符
合公司建模规则的项⽬。 接下来,就可以进⾏模型评审了,也就是说,评审的模型有两个前提,⼀是可以编译的,⼆是符合公司建模规则的。这两个前提可以帮助我们消除模型中的⼀些低级错误,避免在评审过程中有太多的时间花费在这些错误上。因为评审是建模的⼯程师和其他同事共同参与的活动,做到上述两个前提,也是对其他同事⼯作时间的⼀种尊重。 评审之后,建模的⼯程师会修改评审中发现的问题,问题多的话,⼀般会要求修改之后再进
⾏“再评审”,直到在评审中不会发现⼤量问题。 接下来,我们可以使⽤Simulink Design Verifier进⾏模型的结构分析,借助于Simulink Design Verifier⾃动⽣成测试⽤例的功能,去检查结构上是否存在问题,⽐如是否有不合理的逻辑设计,是否有运⾏不到的分⽀等。 再往后,就可以进⾏模型单元级别的功能测试了。软件开发过程中,对单元测试的要求是很⾼的,⼀般会根据应⽤的安全性、可靠性要求,给出测试的覆盖率要求。 这个过程中⼯作量最⼤的应该是测试⽤例设计以及测试向量的⽣成。测试⽤例设计,我们⼀般会根据需求去设计测试⽤例,当然,也会结合模型结构设计测试⽤例,这样说来,这⾥的测试,已经包含了⿊盒测试和⽩盒测试。有了测试⽤例,如何把测试⽤例转换为测试向量,这也是⾮常重要的环节。我们知道,在MBD开发过程中,代码都可以⾃动⽣成,其他环节,我们要努⼒做到⾃动化实现。我们可以使⽤MATLAB脚本开发⼀些转换⼯具⽤于将测试⽤例转换为测试向量,我们还可以通过脚本实现测试过程的⾃动化。
测试的指标,即测试覆盖率是否达到公司的要求或者⾏业的要求。
单元级别的功能测试完成之后,我们⾃然会进⾏集成测试,当然,集成测试是分阶段、有步骤的,我们可以先把⼀些单元模块集成为组件级,进⾏组件级的集成测试,然后再将组件集成为系统级,进⾏系统级测试。集成测试和单元测试关注的内容不同,集成测试,我们更关注于单元模块之间的接⼝关系、调⽤关系等等,所以,单元测试中要求的判定覆盖率、MCDC覆盖率等,在集成测试中没有这样的要求。 条件允许的情况下,集成测试之前或者之后,可以通过快速原型的⽅式和实物相连,进⾏测试。 集成测试通过之后,我们基本上可以认为模型或者说算法是正确的了。接下来,我们就可以进⾏代码⽣成了。 代码⽣成之后,会跟着做SIL、PIL、HIL等测试,所有这些In-the-Loop 测试都不是必须的,⼯程师应该根据项⽬的实际情况,选择合理的测试⽅案,当然,建议SIL测试不要省略,原因在于这种测试的确⾮常⽅便做,并且也的确会发现⼀些代码⽣成过程中出现的问题。
前⾯提到模型验证,下⾯再说说代码⽣成。对象模型是什么
代码⽣成的前提是模型已经是验证过的模型,或者说,是正确的模型。
正确的模型包含两层含义,模型做过⾜够多的验证,验证的结果都是正确的。前⾯提到的各种验证⽅式,都有必要做,对于功能测试来讲,还有必要达到⾜够⾼的覆盖率要求。 做到以上这些,就可以考虑进⾏代码⽣成⼯作了,代码⽣成是否就是按⼀下“Code Generation”按钮的⼯作呢?⼯程项⽬开发中,没那么简单,代码⽣成过程中,⼯程师要做的主要⼯作是数据管理⼯作,除此之外,还会有⼀些代码相关
的配置,⽐如函数原型、⽐如代码⽂件等等。 数据管理主要是对Simulink/Stateflow模型中的两类数据进⾏管理,⼀是信号,⼀是参数。对应于C代码,我们可以简单的把信号对应到变量上,⽽参数,则是不通过程序运⾏⽽发⽣变化的,参数的变化,⼀般是通过⼈⼯调节完成的,也就是参数调节,参数调节的⽬的是为了选择合适的参数以得到最佳的性能。 数据管理的⽅式,使⽤的是数据对象进⾏数据管理,这⾥的“对象”⼆字,和我们经常听到的“⾯向对象编程”⾥⾯的“对象”意义相同。Simulink为⽤户事先定义好两个包,⼀个是Simulink Package,⼀个是mpt Package。以Simulink Package为例,包⾥⾯有类,分别为Simulink.Signal和Simulink.Parameter两个类。⽤户可以通过这两个类定义相应的对象(Object),然后通过类提供的属性(Property)定义数据的属性。其实这两个类⾥⾯除了属性之外,还定义了⽅法(Method),⼀般情况下,我们管理数据,使⽤属性就够了。 当然,不管是Simulink Package还是mtp Package,都不能完全满⾜⽤户的所有要求,所以,很多时候,需要⽤户定义⾃⼰的Package。依然按照⾯向对象⾥⾯的⼀些概念,我们可以从Simulink Package或者mpt Package继承并创建⾃⼰的包。所有我们关⼼的数据都通过数据对象的⽅式做了定义之后,接下来的⼯作,就是按下按钮,⽣成代码了。 ------------------------------------------------------------------------------------ 因为前⾯预留的帖⼦不够多,所以,就继续在这个帖⼦⾥讨论⼀下⾃动⽣成的代码吧。 ⾸先说⼀下⼤家很关⼼的效率问题,代码效率,我之前做过对⽐,⽐⼀般的⼯程师写的代码效率要⾼,当然,我相信对于那种C代码⾼⼿,⼀定可以写出效率更⾼的代码。不过我想强调的是,⾃动⽣成的代码,是可以⽤的,不要有任何⼼理障碍,毕竟,我们项⽬开发中的多数⼯程师也不是绝对的C语⾔⾼⼿。另外,关于效率,我最近也做过⼀次对⽐,就在这个
帖⼦最开头提到的那个贴⼦⾥,虽然代码没有⼈去做编译,但从代码⾏数来看,和⼀个写了6年C代码的⼯程师的代码基本差不多。 再说说代码可读性的问题,很多⼈和我强调代码的可读性不如⼿写的好,我有条件的承认这⼀点。为什么是有条件的承认呢,我想说,如果你对模型做⾜够多的配置,⽣成的代码可读性基本上可以和⼿写的差不多。当然,我更想强调,在基于模型的开发过程中,我们是不读代码的(如果⼀定要读,那也是读那个.h⽂件),我们有其他⽅式保证代码是正确的,⽆须读代码。 再有⼀个问题,就是代码的集成问题,很多⼈也⽐较关⼼⾃动⽣成的代码如何集成到底层代码或者如何与其他⼿写代码做集成的问题,我⼀般会问他,如果这个模块的代码是⼿写的,你会怎么集成?他当然知道⼿写代码该怎么集成,好,⾃动⽣成的代码也同样可以集成。做代码集成的时候,我们关⼼的就是那个.h⽂件。
有关底层驱动的建模
我⼀直认为在产品化项⽬开发中,底层驱动是没有必要建模的。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论