查找模型中的所有异构比较模块(不同数据类型的比较)m脚本

33 次阅读

本文最后更新于 2026年5月11日。

simulink模型要在normal模式下运行编译





findAndCheckRelationalOperators('AlgoSim_251111');


function findAndCheckRelationalOperators(modelName)
% 查找模型中所有关系运算符(Relational Operator)模块,并检查输入类型是否一致。

% 确保模型已加载
if ~bdIsLoaded(modelName)
    load_system(modelName);
end

disp(['--- 正在检查模型: ', modelName, ' 中的关系运算符 ---']);

% 1. 查找模型中所有的 Relational Operator 块
relationalBlocks = find_system(modelName, ...
    'BlockType', 'RelationalOperator');

if isempty(relationalBlocks)
    disp('模型中未找到 Relational Operator 块。');
    return;
end

% 清理所有块路径中的不可见字符(换行、回车、空格等)
relationalBlocks = cleanBlockPaths(relationalBlocks); % 新增函数:清理路径

blocksFound = 0;
heterogeneousBlocks = {}; % 存储需要修复的块路径

% 🚨 关键步骤 1: 尝试进入编译状态
try
    feval(modelName, [], [], [], 'compile');
catch ME
    fprintf(2, '警告:模型编译失败。无法获取编译后的数据类型。错误: %s\n', ME.message);
    return;
end

% 🚨 关键步骤 2: 遍历块,并在 finally 块中终止编译
try
    for i = 1:length(relationalBlocks)
        blockPath = relationalBlocks{i};

        % 获取两个输入信号的端口句柄
        ports = get_param(blockPath, 'PortHandles');
        inputPorts = ports.Inport;

        if length(inputPorts) ~= 2
            warning('Simulink大师:SkipBlock', '跳过块 %s,因为它不是双输入关系运算符。', blockPath);
            continue;
        end

        % 获取输入信号的数据类型
        try
            dataType1 = get_param(inputPorts(1), 'CompiledPortDataType');
            dataType2 = get_param(inputPorts(2), 'CompiledPortDataType');

            % 比较数据类型
            if ~strcmp(dataType1, dataType2)
                blocksFound = blocksFound + 1;

                % 🚨 修正 1: 清理模块路径后再用于超链接
                safeBlockPath = escapeSingleQuotes(blockPath); % 转义单引号(避免 MATLAB 语法错误)

                % 🚨 修正 2: 使用 fprintf 和超链接语法(已清理路径)
                fprintf('\n🚨 发现异构比较模块 (%d): <a href="matlab:open_system(''%s'');">打开模块</a>\n', blocksFound, safeBlockPath);
                fprintf('   - 模块路径: %s\n', strrep(blockPath, newline, ' ')); % 显示时替换换行为空格
                fprintf('   - 输入 1 类型: %s\n', dataType1);
                fprintf('   - 输入 2 类型: %s\n', dataType2);

                heterogeneousBlocks{end+1} = blockPath; % 保存原始路径用于后续修复
            end
        catch ME_inner
            warning('Simulink大师:TypeError', '无法检查块 %s 的编译类型: %s', strrep(blockPath, newline, ' '), ME_inner.message);
        end
    end

finally
    % 确保无论是否发生错误,编译状态都会被终止
    feval(modelName, [], [], [], 'term');
end

disp('--- 检查完成 ---');
disp(['总共发现 ', num2str(blocksFound), ' 个异构类型比较模块。']);

if ~isempty(heterogeneousBlocks)
    disp(' ');
    disp('** 建议立即在这些模块的输入端添加 Data Type Conversion 块进行统一。**');
    disp('以下模块需手动检查或修复:');
    for i = 1:length(heterogeneousBlocks)
        fprintf('   (%d) %s\n', i, strrep(heterogeneousBlocks{i}, newline, ' '));
    end
end

end % 结束 function


%% ================================
% 辅助函数 1:清理块路径中的多余空白字符(包括换行、回车、制表符)
% ================================
function cleaned = cleanBlockPaths(blockPaths)
cleaned = cell(size(blockPaths));
for i = 1:length(blockPaths)
    path = blockPaths{i};
    % 去除首尾空白 + 替换中间换行、回车、制表符为空格(防止路径解析失败)
    cleaned{i} = regexprep(strtrim(path), '[\n\r\t]+', ' ');
end
end


%% ================================
% 辅助函数 2:转义单引号,防止在 MATLAB 超链接中出错
% ================================
function out = escapeSingleQuotes(str)
% 将 ' 替换为 '',以便在 matlab:open_system('...') 中安全使用
out = strrep(str, '''', '''''');
end