使用转换表维护库模块的兼容性
如果模型是使用库模块的旧版本保存的,转换表允许您检查对库中模块的更改会不会对模型造成破坏。如果您更改库的路径或名称,或者添加、删除或重命名库模块中的参数,转换表可以帮助您保持库模块的兼容性。有关详细信息,请参阅创建自定义库。
创建一个转换表条目,用于将旧库模块映射到新库模块。打开模型时,旧库模块的链接会自动更新,并且不会丢失数据或功能。在您打开模型、关闭模型或执行 add_block
或 replace_block
命令时,会执行转换表。
当进行了以下操作时, 需要在转换表中创建相应的条目:
重命名模块。
将模块从一个库移至另一个库。
向模块中添加或从其中删除参数。
拆分模块的功能。
为模块重命名创建转换表条目
假设有如下示例,其中库 testlib
中模块 ss1
重命名为 ss2
。
打开锁定的库
Lib1
。在“库”窗口中,在库选项卡上,点击锁定的库。现在库已解锁,可以进行编辑。
在建模选项卡上,点击库属性。库属性对话框随即打开。
点击转换表选项卡。
点击“添加新条目”。转换表中将添加一个新行。
在旧模块路径中指定旧模块的名称,在新模块路径中指定对应的新模块路径。如果不知道路径,请选择模型中的模块,然后点击获取 gcb 按钮。模块的路径会自动填充到对应的列中。
将在转换表中创建旧路径到新路径的映射。现在,打开一个包含库链接的模型。模型中旧库模块的链接会自动更新。您可以使用表上方的搜索栏来过滤表内容。您可以按升序或降序对列进行排序。您也可以按值对列进行分组。
为库模块分配版本号
在版本列中,您可以为库模块指定版本号。
如果旧模块名称与新模块名称相同,转换表会自动填充版本号。库版本 (LibraryVersion
) 的初始值从创建库链接时库的 ModelVersion
属性派生而来。对库模块的任何后续更新都会更新库版本,使其与库的模型版本匹配。
版本号:
必须为数值。
当新旧模块路径相同时,格式必须为
<major_version>
.<minor_version>
。包含的圆点不能超过一个。例如,版本号 1.3 是可以接受的。版本号 1.3.1 则不行。
当您使用转换表将库模块从一个库移到另一个库时,版本号的格式并不重要。
将模块从一个库移至另一个库
假设有如下示例,其中模块 ss1
从 testlib1
移至 testlib2
。这种情况的转换表条目如下所示:
添加或删除模块参数
假设有如下示例,库 testlib
中 ss1
的 Gain 参数被删除,然后添加了另外两个参数 Initial condition
和 Delay length
。
为了处理此变化,我们使用变换函数。变换函数可更正新旧库链接之间的参数不匹配,从而确保库链接仍然有效。您可以使用 MATLAB 路径中的 .m
函数文件定义一个变换函数,然后在转换表的变换函数列中调用该函数。
链接模块以名称-值参数形式包含模块参数的实例,以实例化该模块。此实例数据作为 InstanceData
与转换表条目一起传递给变换函数。此数据存储为 struct
字段。
当您为一个库模块创建不同的版本时,会在 InstanceData
中添加或删除参数。在此示例中,删除 增益 参数之前以及添加初始条件和延迟长度后的 InstanceData
如下所示
之前:
'RTWMemSecFuncInitTerm' 'Inherit from model' 'RTWMemSecFuncExecute' 'Inherit from model' 'RTWMemSecDataConstants' 'Inherit from model' 'RTWMemSecDataInternal' 'Inherit from model' 'RTWMemSecDataParameters' 'Inherit from model' 'ContentPreviewEnabled' 'on' 'Gain' '0'
之后:
'RTWMemSecFuncInitTerm' 'Inherit from model' 'RTWMemSecFuncExecute' 'Inherit from model' 'RTWMemSecDataConstants' 'Inherit from model' 'RTWMemSecDataInternal' 'Inherit from model' 'RTWMemSecDataParameters' 'Inherit from model' 'ContentPreviewEnabled' 'on' 'DelayLength' '1' 'InitialCondition' '0'
变换函数的语法如下。
function outData = TransformationFcn(inData)
在此函数语法中:
inData
是一个结构体,包含字段ForwardingTableEntry
和InstanceData
;ForwardingTableEntry
也是一个结构体。ForwardingTableEntry
包含模块的旧名称、新名称、旧路径和新路径。请参考代码来访问ForwardingTableEntry
的成员。
outData
是包含NewInstanceData
和NewBlockPath
字段的结构体:
要在模块中添加或删除参数,请执行以下操作:
获取实例数据和转换表条目。
提取名称-值对组和模块名称的列表。
获取新旧模块名称。
检查新旧模块名称是否相同。如果是,则提取模块的版本。
检查是否旧版本为 1.1、新版本为 1.2。然后,删除
Gain
参数,并添加参数Delay length
和Initial condition
。
注意
您的库可以有多个变换函数文件。然而,为了高效维护,建议每个库有一个变换函数文件。
要添加或删除参数,请使用以下变换函数。
function [outData] = txFcnTestlib(inData) outData.NewBlockPath = ''; outData.NewInstanceData = []; % Get linked block instance data and forwarding entry for which % function is called instanceData = inData.InstanceData; forwardingTableEntry = inData.ForwardingTableEntry; % Get list of name value pair and block names [ParamNames{1:length(instanceData)}] = instanceData.Name; % Get old and new block paths or simply names oldName = forwardingTableEntry.('__slOldName__'); newName = forwardingTableEntry.('__slNewName__'); % If block names are same and its subsys block in the lib if strcmp(oldName, newName) % Get old and new block versions from forwarding table oldVer = forwardingTableEntry.('__slOldVersion__'); newVer = forwardingTableEntry.('__slNewVersion__'); % Each forwarding entry with different version can have separate % entry. Here, for one single entry in forwarding table i.e. % 1.2->1.3 or 1.3->2.0, we have separate transformation making one % TX Fcn for one library or block. if strcmp(oldName, 'testlib/ss1') % Forwarding with same block name ss1 if oldVer == '1.1' && newVer == '1.2' % Remove gain param if (ismember('Gain',ParamNames)) for (i = 1:length(instanceData)) if (strcmp(instanceData(i).Name,'Gain') == true) instanceData(i) = []; break; end end end % Add delay length param if (ismember('DelayLength',ParamNames)) for (i = 1:length(instanceData)) if (strcmp(instanceData(i).Name,'Value') == true) instanceData(i).Value = '5'; break; end end else instanceData(end+1).Name = 'DelayLength'; instanceData(end).Value = '1'; end % Add initial condition param if (ismember('InitialCondition',ParamNames)) for (i = 1:length(instanceData)) if (strcmp(instanceData(i).Name,'InitialCondition') == true) instanceData(i).Value = '0'; break; end end else instanceData(end+1).Name = 'InitialCondition'; instanceData(end).Value = '0'; end elseif (oldVer == '1.2' && newVer == '1.3') % Do version 1.2 to 1.3 specific changes elseif (oldVer == '1.3' && newVer == '2.0') % Do version 1.3 to 2.0 specific changes else % Do default changes not applicable to any version if % required end elseif strcmp(oldName, 'testlib/ss2') % Forwarding for block ss2 with version upgrade end elseif strcmp(oldName, 'testlib/oldblk') && strcmp(newName, 'testlib2/newblk') % Block moved to new library or just block is renamed within same % library, no version is checked here. Do transformation is % required i.e. is block has been modified while renaming or moving % to new lib. elseif strcmp(oldName, 'testlib/blkX') && isempty(newName) % We are splitting the block into 2 different blocks. Hence, kept % newName empty in fwd table. Using one of the block param from its % instance data (which is name-value pair of all block params) to % decide how and what to divide. % Get the index of param we are interested in i.e. param X i = find(contains({instanceData.Name},'X'), true); % Based on its value, do block splitting switch (instanceData(i).Value) case 'op1' newName = 'newlibX/blkX'; % Remove existing param or add new param or modify existing % params etc. case 'op2' newName = 'newlibY/blkX'; otherwise newName = oldName; end end % Return new instance data and new block path outData.NewInstanceData = instanceData; outData.NewBlockPath = newName; end
拆分模块功能
拆分模块的功能涉及添加、删除或修改模块的现有参数然后将其添加到新模块。要拆分模块的功能,请执行下列步骤:
将
newName
参数留为空。获取参数的索引和值。
根据值拆分模块。
如果需要,将
NewBlockPath
与更新后的InstanceData
一起返回。
创建封装参数别名
如果重命名封装参数,则必须确保使用旧参数名称的现有 MATLAB® 脚本能够继续工作。要检查兼容性,您可以为封装参数名称创建别名。别名允许您在库模块中更改封装参数的名称,而无需在现有模型中重新创建模块链接。
假设有一个包含编辑参数的封装模块。此编辑参数的封装参数名称为 p1
。
MaskObj = Simulink.Mask.get(gcb)); hEdit = MaskObj.getParameter('p1'); hEdit= % MaskParameter with properties: Type: 'edit' TypeOptions: {0×1 cell} Name: 'p1' Prompt: 'p1' Value: '0' Evaluate: 'on' Tunable: 'on' NeverSave: 'off' Hidden: 'off' Enabled: 'on' Visible: 'on' ToolTip: 'on' Callback: '' Alias: ''
请注意,编辑封装参数没有别名。要为封装参数添加别名,请为 Alias
封装参数属性设置值。
MaskObj.Alias = 'pa'
您可以使用封装参数名称或别名对封装参数执行函数调用。例如,您可以使用 set_param(gcb, 'p1, '10)
(封装参数名称)或 set_param(gcb, 'pa, '10)
(封装参数别名)为编辑封装参数设置值。