捕获模型作为需求并创建链接
在此步骤中,您使用 Requirements Toolbox™ 编程接口将 Simulink® 模型中的元素捕获到一组与您的模型具有相同层次结构的代理 slreq.Requirement
对象中。然后,您可以使用代理需求对象的 Description 和 Rationale 属性来记录设计的每个元素。该示例还展示了如何在模型元素和代理需求对象之间创建链接以实现可追溯性。
打开模型
打开 slvnvdemo_powerwindow_vs
和 slvnvdemo_powerwindowController
模型。slvnvdemo_powerwindow_vs
模型是一个规范模型,用于验证 slvnvdemo_powerwindowController
中设计的功能属性。
open_system("slvnvdemo_powerwindow_vs"); open_system("slvnvdemo_powerwindowController");
捕获模型作为代理需求
使用 Requirements Toolbox API 将 Simulink 模型捕获为需求编辑器中 slreq.Requirement
和 slvnvdemo_powerwindow_vs
模型的代理 slvnvdemo_powerwindowController
对象。
首先,创建一个包含模型名称的数组,以便轻松对两个模型进行更改。
models = ["slvnvdemo_powerwindow_vs", ... "slvnvdemo_powerwindowController"];
对于每个模型:
for modelIndex = 1:numel(models) modelName = models(modelIndex); reqSetName = modelName+".slreqx"; myReqSet = slreq.new(reqSetName); topProxy = add(myReqSet,Id=modelName, ... Summary=modelName+" Description"); open_system(modelName); [elementHandles,parentIndex,isSf,SID] = rmi( ... "getObjectsInModel",modelName);
对于模型中的每个元素,使用 getNameAndType
函数获取元素的名称和类型。要查看该函数的代码,请参阅辅助函数。在模型层次结构中模型元素父级的 slreq.Requirement
对象下添加一个 slreq.Requirement
对象。根据名称和类型向 slreq.Requirement
对象添加摘要。
createdProxies(1) = topProxy; for elementIndex = 2:numel(elementHandles) [name,type] = getNameAndType(isSf(elementIndex), ... elementHandles(elementIndex), ... modelName,SID(elementIndex)); if ~isempty(name) && ~isempty(type) parentProxy = createdProxies( ... parentIndex(elementIndex)); createdProxies(elementIndex) = add(parentProxy, ... Id=SID{elementIndex}, ... Summary=name+" ("+type+")"); end end save(myReqSet); end
打开需求编辑器查看需求。
slreq.editor
链接需求和模型元素
在 slvnvdemo_powerwindow_vs
和 slvnvdemo_powerwindowController
需求集中创建链接,以便在 slreq.Requirement
对象和相应的模型元素之间导航。
对于每个模型及其相关需求集,创建一个包含需求的数组。
for modelIndex = 1:numel(models) modelName = models(modelIndex); reqSetName = slreq.find( ... Type="ReqSet",Name=modelName); proxyRequirements = find(reqSetName,Type="Requirement");
对于需求集除顶级需求之外的每个需求:
获取关联模型元素的 SID,然后获取该模型元素的句柄。
在模型元素和需求之间创建链接。
为链接添加描述,其中包括链接需求的索引。
记录创建的链接数量。
counter = 0; for reqIdx = 1:numel(proxyRequirements) myProxy = proxyRequirements(reqIdx); if ~contains(myProxy.Summary,modelName) sid = strcat(modelName,myProxy.Id); linkSrc = Simulink.ID.getHandle(sid); newLink = slreq.createLink(linkSrc,myProxy); newLink.Description = strcat( ... "Link between requirement ", ... myProxy.Index," and model element"); counter = counter + 1; end end disp(strcat("Created ",num2str(counter), ... " links for ",modelName)); end
Created 116 links for slvnvdemo_powerwindow_vs Created 59 links for slvnvdemo_powerwindowController
通过点击某个需求并在右侧窗格中滚动到链接部分,可以查看需求编辑器中的新链接。
保存链接集。
lsArray = slreq.find(Type="LinkSet");
save(lsArray(1));
save(lsArray(2));
辅助函数
该函数返回模型元素名称和类型。此函数跳过除 Stateflow.State
和 Stateflow.Transition
之外的 Stateflow 对象类型。
function [name,type] = getNameAndType(isSf, ... elementHandle,modelName,SID) if ~isSf name = get_param(elementHandle,"Name"); type = get_param(elementHandle,"BlockType"); else sfObj = Simulink.ID.getHandle(strcat(modelName,SID)); sfType = class(sfObj); switch sfType case 'Stateflow.State' name = sf('get',elementHandle,'.name'); type = strrep(class(sfObj),"Stateflow.",""); case 'Stateflow.Transition' name = sf('get',elementHandle,'.labelString'); type = strrep(class(sfObj),"Stateflow.",""); otherwise warning( ... 'Stateflow object of type %s was skipped.' ... ,class(sfObj)); name = ""; type = ''; end end end