工程软件开发之基于模型设计的敏捷方法
作者 Roger Aarenstrup and Gaurav Tomar, MathWorks
如今,大多数为工程应用开发软件的团队都意识到了传统开发方法(瀑布式)的缺点。这包括在项目后期发现缺陷和设计问题,无法适应需求的更改,以及交付的系统不满足客户需求的风险。
为了克服这些缺点,许多团队采用了将敏捷方法与基于模型的设计相结合的开发流程。
有关基于模型的设计和敏捷方法的研究表明,对工程应用而言,基于模型的设计不仅是敏捷开发的有效补充,甚至有时使敏捷开发成为可能。像敏捷开发一样,基于模型的设计最初是为了支持快速迭代,其还满足了系统工程方面的挑战,而这些挑战不是敏捷开发单独能够解决的:
- 如何在不使用设备的情况下进行早期测试
- 如何管理工程系统的复杂性
- 如何降低在昂贵的硬件上测试未经验证的软件的风险
- 如何满足功能安全及其他标准的要求,包括DO-178B/C和ISO 26262
本文解释了基于模型的设计是如何支持敏捷开发的核心价值体系,并通过一个自适应巡航控制示例对其进行介绍,该示例结合了基于模型的设计、敏捷方法和Scrum框架。
敏捷开发和基于模型的设计:基础
软件敏捷开发方法建立在2001年出版的《敏捷宣言》中概述的核心价值体系和原则之上。如今,敏捷开发最广泛使用的框架之一是Scrum。在Scrum中,开发以称为sprint的一系列周期进行,在每个周期中,开发团队在项目待办事项列表中的一个子集上工作一段时间(通常是一到两个星期或者一个月)。在每个sprint中,开发团队对软件进行开发、测试、集成,最后对可工作的软件设计文档(图1)。
基于模型的设计是一种以模型为中心的系统开发方法。基于模型的设计在整个开发过程中使用模型作为设计载体,而不是依赖物理原型和文本规范的在团队内传递。模型包含了与系统行为相关的所有组件——包括算法、控制逻辑、物理组件和环境组件。一旦模型被开发(细化)出来,就可以用其来生成代码(C/C++、HDL或结构化文本)、报告和其他类型的文档。基于模型设计的核心要素包括系统级和组件级的设计和仿真、自动代码生成,以及持续测试与验证。
将敏捷开发的核心价值体系映射至基于模型的设计
敏捷宣言定义了软件开发的四个核心价值观:
- 个体和互动高于流程和工具
- 工作的软件高于详尽的文档
- 客户合作高于合同谈判
- 响应变化高于遵循计划
宣言作者指出,“高于”并不意味着“否定”。他们所倡议的是开发要素要有所侧重:“虽然右边的开发要素也有价值,但我们更注重左边的要素。”
让我们看看这些敏捷方法的价值观如何映射到基于模型的设计。
专注个体和互动
基于模型设计的流程和工具——特别是建模和仿真——能够促进个人和团队之间进行高效的交互。模型可以直接通过Simulink®,报告或web页面进行共享, 使所有相关人员能够使用模型作为一个共同的工作参考点,避免产生分歧。仿真结果清晰可见,有助于设计决策、Scrum规划以及促进相关人员的讨论。
注重客户合作
客户合作是敏捷方法的核心。每个sprint以计划会议开始,以评审会议结束,在会议上,客户经常被邀请提供输入。建模和仿真不仅支持高效的客户合作,还支持跨团队、跨领域和跨学科的合作。采用MathWorks公司基于模型的设计工具,来自硬件设计、系统设计、功能和组件开发的工程师们使用共同的语言/平台,可以集中精力在一起工作,而不必担心工具兼容问题。
关注可工作的软件
对于采用敏捷开发的团队来说,基于模型设计的主要优势之一是,即使没有嵌入式目标硬件、被控对象实物、传感器或其他硬件,也能够在最初的sprint中开发出一个可工作的系统。通过仿真验证后的Simulink模型可以作为可工作的软件服务于整个项目的开发。模型作为系统开发过程中的可执行规范,在早期的sprint中,当硬件还不存在时,作为硬件测试结果的替代,也可以与客户共享模型的仿真结果,以用于评估项目进度、寻求支持或计划下一次sprint。模型还提供了一种清晰而便捷的方法来评估项目进度。随着模型的细化,可以用其生成代码,用于软件在环(SIL)、处理器在环(PIL)和硬件在环(HIL)测试,以及用于实时原型和生产系统。
模型还可以作为文档的载体。在基于模型的设计中,文档是模型设计过程的输出,而不是一个单独的任务,文档和报告可以根据需要从模型直接生成。
注重响应变化
瀑布开发的一个主要障碍是不能对不断演化的需求和条件做出足够的反应。敏捷开发和基于模型的设计解决了这一缺陷,使团队能够更有效地应对变化。对于工程应用软件中的任何重大更改,使用基于模型设计的工程师可以修改模型,然后简单地重新生成代码。在实现任何更改之前,开发团队可以执行假设分析来确定适应特定更改请求的最佳方法。对模型进行更改后,工程师可以进行回归测试,以确保更改不会为系统引入意外行为。当模型与需求相链接后,开发团队还可以进行影响分析,以了解对模型其中一个部分的更改将如何影响其他部分。
用例:将敏捷开发与基于模型的设计相结合,开发自适应巡航控制器
在这个例子中,某汽车工程团队正在开发一套具有传感器融合算法的自适应巡航控制系统软件。该系统融合了车载雷达和视觉传感器的输入数据,识别出最重要的目标及其与当前车辆的距离,以调整车速并保持安全距离。
在这个项目中,其中一组工程师负责开发控制算法,另一组工程师负责开发驾驶场景和传感器数据综合算法。这些合成数据将使工程师能够在获得实际的传感器数据之前开发和测试算法。在开发的早期阶段,使用合成数据进行仿真可以为设计决策提供信息,例如车内传感器的类型、数量和位置。
在第一个sprint中,每个子团队(或工程团队)都对各自负责的子系统进行建模,使用共享的系统级的Simulink模型来协调各自的工作(图2)。甚至在这个初期阶段,工程师们可以运行仿真以观察在不同工况下控制器的行为。在编写或生成代码之前,工程师们可以调试控制器,识别出要优化的参数,并利用可工作的系统模型来可视化关键性能指标。
在第一个sprint快结束时的评审会议上,开发团队可以与客户分享模型和仿真结果 (图3)。该模型提供一个具体的可工作的软件,比如, 可以用来演示当另一辆车驶入当前车辆的车道后,当前车辆会如何进行减速。
在随后的sprint中,开发团队基于客户反馈对模型进行改进或增强——例如,通过调整安全跟踪距离或改变车辆加速或减速的速率——对这些参数进行优化,并生成代码,部署到ECU上。生成的代码可以按照原样使用,也可以作为较大系统的一部分与已有代码集成。Jenkins™提供的持续集成(CI)功能可以用来不断检查生成代码与手工代码的集成活动, 比如运行模型测试,检查建模规范的符合性,对生成的代码进行测试等。所有这些活动的结果都会被自动报告,以跟踪进度,并且提供给不使用开发工具的相关人员。
在之后的sprint中,开发团队加入了更严格的验证和确认活动,包括SIL、PIL或HIL测试,以确保设计满足需求。此外,开发人员还检查模型和代码是否符合已建立的标准和指南,使用静态分析和形式化方法来证明软件不存在严重的运行时错误,并为标准的认证生成认证报告及其他所需文件。
随着项目的进行,客户需求可能会发生变化。例如,客户可能要求模型使用预测控制,而不是经典的控制算法,因为先进的MPC(模型预测控制)控制器使车辆能够对场景中其他车辆的激进动作更好地做出反应。由于在这个项目中使用了系统模型,算法团队可以很容易地用新开发的模型预测控制器替换原来的控制算法,并保持模型的其余部分不变。团队重新运行仿真并与客户分享结果,进而就是否继续进行设计更改还是恢复到原先的控制算法设计做出更好的决定。
该团队在其敏捷开发工作流中使用了基于模型的设计,并且在涉及到具体硬件之前就交付了可以工作的软件。建模和仿真使得团队能够根据客户反馈不断改进设计,甚至在项目后期适应重大的需求更改。
2018 年发布