问题

怎么实现matlab自定义函数(而不是在m文件中)中调用simulink?

回答
好的,咱们今天就来聊聊如何在 MATLAB 自定义函数(而不是直接写在 m 文件里)里面,把 Simulink 模型跑起来。

你有没有遇到过这样的场景:你写了一个 MATLAB 函数,里面有很多参数需要调整,你想用 Simulink 来模拟这个系统的不同工况,然后把 Simulink 的输出结果通过 MATLAB 函数进行处理、分析,甚至作为下一次仿真的输入?直接在 m 文件里调用 `sim` 命令当然是最直接的方式,但有时候,我们希望把 Simulink 的调用逻辑封装得更“函数式”一些,比如作为另一个更复杂 MATLAB 函数的一部分,或者需要更灵活地控制仿真过程。

下面,咱们就一步步拆解,看看怎么实现这个目标。

核心思路:MATLAB 函数作为“控制器”

想象一下,你的 MATLAB 自定义函数就像一个“指挥官”,它负责:

1. 准备参数: 根据你的需求,生成 Simulink 模型需要的输入信号、模型参数等等。
2. 设置仿真: 告诉 Simulink 模型要以什么方式运行(仿真时间、步长、是否使用外部模式等)。
3. 执行仿真: 启动 Simulink 仿真。
4. 获取结果: 从仿真后的 Simulink 模型中提取你关心的输出数据。
5. 后续处理: 用 MATLAB 函数对这些数据进行进一步的计算、绘图、或者反馈给下一次迭代。

步骤详解

假设我们有一个简单的 Simulink 模型,名为 `my_simple_model.slx`,它有一个输入端口 `In1` 和一个输出端口 `Out1`。我们想在 MATLAB 自定义函数中控制它的仿真,并读取输出。

第一步:准备你的 Simulink 模型

首先,确保你的 Simulink 模型已经搭建好,并且具有明确的输入和输出接口。

输入: 通常是 Signal Builder、Inport 模块,或者可以通过 `set_param` 直接设置的数据。
输出: 通常是 Outport 模块,仿真结束后可以通过 `simOut` 变量访问。

第二步:MATLAB 自定义函数的编写

咱们来写一个 MATLAB 函数,比如 `runSimAndAnalyze(param1, param2)`。这个函数会接收一些参数,然后调用 Simulink,最后返回一个分析结果。

```matlab
function analysisResult = runSimAndAnalyze(param1, param2, varargin)
% runSimAndAnalyze: 这是一个示例 MATLAB 函数,用于调用 Simulink 模型并进行分析。
%
% Inputs:
% param1: Simulink 模型中的一个参数,例如增益。
% param2: Simulink 模型中的另一个参数,例如一个初始状态。
% varargin: 可选参数,例如仿真时间、模型名称等。
%
% Output:
% analysisResult: 对 Simulink 仿真结果进行分析后得到的值。

% 1. 解析可选参数 (例如:仿真时间,模型路径)
defaultModelName = 'my_simple_model'; % 假设模型文件名为 my_simple_model.slx
defaultStopTime = 10; % 默认仿真时间
defaultInputSignal = []; % 默认输入信号

p = inputParser;
addParameter(p, 'ModelName', defaultModelName, @ischar);
addParameter(p, 'StopTime', defaultStopTime, @isnumeric);
addParameter(p, 'InputSignal', defaultInputSignal, @(x) iscell(x) || isempty(x)); % InputSignal 可以是 cell 数组

parse(p, varargin{:});

modelName = p.Results.ModelName;
stopTime = p.Results.StopTime;
inputSignal = p.Results.InputSignal;

% 2. 设置 Simulink 模型的参数
% 在调用 sim 之前,我们可以使用 set_param 来动态修改模型参数
% 或者,如果模型有 Simscape Electrical (Simscape Power Systems) 的 Electrical
% Reference 等模块,可以通过其参数来影响仿真。
% 这里我们演示如何修改一个名为 'GainValue' 的 Gain 模块的值,
% 以及一个名为 'InitialState' 的 StateSpace 模块的初始状态。
% 注意:你需要根据你的具体模型来修改模块名和参数名。

% 找到模型中的 'Gain' 模块,并设置其 'Gain' 属性
% 假设模型中有个 Gain 模块,名字叫 'MyGainBlock'
try
% set_param([modelName, '/MyGainBlock'], 'Gain', num2str(param1));
% 如果你的模型是直接使用 Model Workspace 或 Workspace 变量,
% 可以在 MATLAB workspace 中设置这些变量,然后 Simulink 模型引用它们。
% 这种方式更推荐,因为它分离了模型结构和运行数据。

% 假设我们直接在 MATLAB Workspace 中定义了需要传递给 Simulink 的变量
sim_gain = param1;
sim_initial_state = param2;

% 如果模型使用了 Global Parameters,也可以在这里修改
% set_param(modelName, 'Solver', 'ode45'); % 设置求解器
% set_param(modelName, 'FixedStep', '0.01'); % 设置固定步长

catch ME
warning('Failed to set Simulink model parameters: %s', ME.message);
% 可以选择抛出错误或者继续执行
% rethrow(ME);
end

% 3. 准备输入信号
% 如果你的模型有输入端口,你需要提供输入信号。
% Simulink 的 sim 函数可以接受一个 `timeseries` 对象或一个 `struct` 数组作为输入。
% 这里我们演示如何创建一个简单的输入信号。
% `inputSignal` 可以是一个 cell 数组,每个 cell 包含一个输入端口的信号。
% 每个信号是一个 struct,包含 'Time' 和 'Data' 字段。

if ~isempty(inputSignal)
% 假设只有一个输入端口
signalTimes = inputSignal{1}.Time;
signalData = inputSignal{1}.Data;
inputTimeseries = timeseries(signalData, signalTimes);
else
% 如果没有提供输入信号,或者模型没有输入端口,则留空
inputTimeseries = [];
end

% 4. 设置仿真参数
% Simulink 的 sim 函数有丰富的参数可以控制仿真。
% 例如:'SimulationMode', 'SaveOutput', 'SaveFormat', 'ReturnWorkspaceOutputs' 等。
% 最常用的是 'ReturnWorkspaceOutputs', 配合 'SaveOutput', 'SaveFormat'
% 来获取仿真输出。

simOptions = simset('SrcWorkspace', 'current'); % 使用当前 MATLAB workspace
% simOptions = simset('SrcWorkspace', 'caller'); % 使用调用函数的 workspace

% 5. 执行 Simulink 仿真
% sim(modelName, stopTime, simOptions, inputs...)
% inputs 部分可以是一个 Cell Array,每个元素对应一个输入端口的信号。
% 如果模型有多个输入端口,inputs 需要是 {signal_port1, signal_port2, ...}

disp(['Starting Simulink simulation for model: ', modelName]);
disp(['Simulation StopTime: ', num2str(stopTime)]);

try
% 传入模型参数(如果之前设置了 Workspace 变量)
% 也可以直接通过 sim 函数的参数传递,但方式比较复杂,通常不推荐。

% 如果模型有输入端口,并且我们准备了 inputTimeseries
if ~isempty(inputTimeseries)
% 假设模型只有一个输入端口 'In1'
% 这里的 'In1' 是 Simulink 模型中 Inport 模块的名称
% 实际上,sim 函数更倾向于通过结构体来传递输入信号,
% 结构体的字段名对应模型中全局变量或 Signal Builder 的变量名。
% 更直接的方式是使用 timeseries 对象直接传入,sim 函数会解析。
%
% 另一种常见且推荐的方式是,在 MATLAB workspace 中定义一个
% 结构体变量,例如 `sim_inputs`,然后 `sim` 函数会查找。
%
% 示例:
% if ~isempty(inputSignal)
% sim_inputs.Time = inputSignal{1}.Time;
% sim_inputs.Data = inputSignal{1}.Data;
% % 如果有多个输入,可以这样组织:
% % sim_inputs.Time1 = ...; sim_inputs.Data1 = ...;
% % sim_inputs.Time2 = ...; sim_inputs.Data2 = ...;
% % 或者使用 timeseries 结构体数组
% sim_inputs = {timeseries(inputSignal{1}.Data, inputSignal{1}.Time)};
% else
% sim_inputs = {};
% end

% 假设我们直接将 timeseries 对象作为输入参数传递
% 注意:sim 函数的输入参数顺序非常重要,与模型的输入端口顺序一致。
% 如果模型有 N 个输入端口,则需要 N 个输入参数。
% sim(modelName, stopTime, simOptions, Input1, Input2, ...)

% 假设模型只有一个输入端口,我们将其命名为 'InputSignalData'
% 并且在 MATLAB workspace 中定义了 sim_input_data
% sim_input_data = timeseries(inputSignal{1}.Data, inputSignal{1}.Time);
% 另一种更灵活的方式是:
% sim(modelName, stopTime, 'ReturnWorkspaceOutputs', 'on', ...
% 'Solver', 'ode45', ...
% 'SimInput', {timeseries(inputSignal{1}.Data, inputSignal{1}.Time)});

% 最终,最通用的方式是直接通过 sim 函数的最后一个参数(一个cell数组)
% 来传递输入信号。cell 数组中的每个元素都是一个输入信号,
% 顺序与模型中 Inport 模块的顺序相对应。
%
% 让我们简化一点:如果我们希望传递一个名为 `sim_input_data` 的 timeseries
% 变量给模型,我们可以这样做:
sim_input_data_ts = timeseries(inputSignal{1}.Data, inputSignal{1}.Time);
% 并且在 MATLAB workspace 中定义 sim_input_data_ts
% 或者直接在 sim 函数中传递:
simOut = sim(modelName, stopTime, simOptions, {sim_input_data_ts});

else
% 如果模型没有输入端口,或者不提供输入信号
% simOut = sim(modelName, stopTime, simOptions);
% 假设模型内部有 Signal Generator,或者我们不需要外部输入
% 并且我们希望将模型中的变量(如 sim_gain, sim_initial_state)
% 传递给模型,可以通过设置 'SrcWorkspace' 为 'caller'
% simOptions = simset('SrcWorkspace', 'caller');
% simOut = sim(modelName, stopTime, simOptions);

% 最标准的方式是:
simOut = sim(modelName, stopTime, 'ReturnWorkspaceOutputs', 'on', 'Solver', 'ode45');

end


% 6. 获取仿真结果
% simOut 是一个 Simulink.SimulationOutput 对象。
% 要获取信号数据,需要访问它的 .get() 方法。
% 你需要知道 Simulink 模型中 Outport 模块的名称。
% 假设模型有一个名为 'Out1' 的 Outport 模块。

% 检查 simOut 是否成功获取
if isempty(simOut)
error('Simulink simulation did not return any output.');
end

% 假设你的模型只有一个 Outport 模块,命名为 'Out1'
% simOut.get('Out1') 会返回一个 timeseries 对象
outputSignal = simOut.get('Out1');

% 如果模型输出多个信号,你需要知道它们的名称
% 例如:
% outputSignal1 = simOut.get('Out1');
% outputSignal2 = simOut.get('Out2');

% 提取 timeseries 中的数据
outputTime = outputSignal.Time;
outputData = outputSignal.Data;

disp('Simulink simulation finished successfully.');

% 7. 对仿真结果进行分析
% 这里可以进行任何你需要的 MATLAB 操作,
% 例如计算平均值、最大值、绘制曲线等。

averageOutput = mean(outputData);
maxOutput = max(outputData);

analysisResult = struct('average', averageOutput, 'maximum', maxOutput, ...
'time', outputTime, 'data', outputData);

% 也可以选择在函数内绘图
figure;
plot(outputTime, outputData);
title(['Simulink Output for param1 = ', num2str(param1)]);
xlabel('Time');
ylabel('Output');
grid on;

catch ME
disp('Error during Simulink simulation or result processing:');
disp(ME.message);
analysisResult = []; % 返回空或者错误指示
rethrow(ME); % 抛出错误,让调用者知道出了问题
end
end
```

第三步:如何在 MATLAB 函数中调用它

现在,我们有了 `runSimAndAnalyze` 这个自定义函数。你可以这样在 MATLAB 命令窗口或另一个 m 文件中调用它:

```matlab
% 示例 1:基本调用
gainValue = 5;
initialState = 0.1;
result1 = runSimAndAnalyze(gainValue, initialState, 'ModelName', 'my_simple_model', 'StopTime', 15);

if ~isempty(result1)
disp('Analysis Result 1:');
disp(result1);
end

% 示例 2:提供输入信号
% 创建一个正弦波输入信号
t_input = 0:0.1:10;
u_input = sin(t_input);
input_signal_cell = {struct('Time', t_input, 'Data', u_input)};

result2 = runSimAndAnalyze(2, 0.5, 'ModelName', 'my_simple_model', ...
'StopTime', 10, 'InputSignal', input_signal_cell);

if ~isempty(result2)
disp('Analysis Result 2:');
disp(result2);
end

% 示例 3:只修改参数,使用模型默认的输入或无输入
result3 = runSimAndAnalyze(10, 0.2, 'ModelName', 'my_simple_model');
if ~isempty(result3)
disp('Analysis Result 3:');
disp(result3);
end
```

关键点总结与注意事项

1. `sim` 函数是核心: `sim(modelName, stopTime, options, inputs...)` 是在 MATLAB 中运行 Simulink 的主要命令。
`modelName`: Simulink 模型的 `.slx` 文件名(不带扩展名,如果文件在当前路径或 MATLAB 路径下)。
`stopTime`: 仿真的终止时间。
`options`: 一个 `simset` 对象,用于设置仿真选项。
`inputs...`: 这是一个 可选 的参数。如果你需要向模型输入数据,它是一个 Cell 数组,其中每个元素代表一个输入端口的信号。信号通常是 `timeseries` 对象,或者一个包含 `'Time'` 和 `'Data'` 字段的结构体。信号的顺序必须与模型中 Inport 模块的顺序一致。

2. `simset` 的用法:
`simset('SrcWorkspace', 'current')`:让 Simulink 仿真在 MATLAB 当前工作区(`ans` 所在的那个 workspace)查找变量。
`simset('SrcWorkspace', 'caller')`:让 Simulink 仿真在调用 `sim` 函数的那个 MATLAB 函数的工作区查找变量。这对于我们自定义函数内的调用非常有用,可以让我们直接在函数内部定义变量,然后传递给 Simulink。
`simset('ReturnWorkspaceOutputs', 'on')`:告诉 `sim` 函数将仿真输出(如信号数据)作为 `Simulink.SimulationOutput` 对象返回。这是获取结果的关键。
`'SaveOutput', 'on', 'SaveFormat', 'StructureWithTime'`:也是一种获取输出的方式,会将数据保存到结构体中,并且 `simOut` 对象也是结构体。`ReturnWorkspaceOutputs` 通常更方便。

3. 修改模型参数:
推荐方式:Workspace 变量。 在 MATLAB workspace 中定义与模型中参数名同名的变量(例如 `sim_gain = param1;`),然后在 `simset` 中设置 `'SrcWorkspace', 'caller'` 或 `'current'`。Simulink 模型在仿真时会自动查找并使用这些变量。这种方式最灵活,也最容易管理。
直接修改模块参数(`set_param`): `set_param([modelName, '/BlockPath'], 'ParameterName', value)`。这种方式可以动态修改模型中的任何参数,但需要你知道准确的模块路径和参数名,并且每次仿真前都需要设置,可能不如 Workspace 变量管理方便。
Model Workspace: 在 Simulink 模型内部,你可以通过“Model Explorer”配置 Model Workspace,然后将变量定义在那里。当你在 MATLAB 函数中调用 `sim` 时,可以通过 `simset('SrcWorkspace', 'model')` 来指向模型的工作区,或者直接在 MATLAB workspace 中定义同名变量,让它覆盖模型工作区中的变量(优先级取决于 Simulink 的变量查找机制)。

4. 获取仿真输出: `sim` 函数在设置为 `ReturnWorkspaceOutputs` 时,会返回一个 `Simulink.SimulationOutput` 对象。
`simOut.get('OutputPortName')`:这是获取特定输出信号(来自 Outport 模块)的标准方法。`OutputPortName` 是你在 Simulink 模型中 Outport 模块的 `Port name` 属性。
它返回一个 `timeseries` 对象,你可以从中提取 `Time` 和 `Data`。

5. 错误处理: 使用 `trycatch` 块来捕获 `sim` 函数执行过程中可能出现的错误,例如模型不存在、参数错误、仿真崩溃等,并给出友好的提示。

6. 函数封装: 将 `sim` 函数的调用和结果处理逻辑封装在你的自定义 MATLAB 函数中,使得主程序更加清晰,易于重用和调试。

这个过程就像是在用 MATLAB 脚本“编程”来控制 Simulink 仿真,你可以根据需要构建复杂的仿真流程,比如:

参数扫描: 在一个循环里调用你的自定义函数,每次传入不同的参数组合。
优化: 将你的自定义函数作为目标函数,配合 MATLAB 的优化工具箱(如 `fmincon`, `patternsearch`)来寻找最优的模型参数。
集成: 将 Simulink 仿真结果与其他 MATLAB 工具(如信号处理工具箱、控制系统工具箱)结合使用。

希望这个详细的解释能帮到你!动手实践一下,你会发现这种方式的强大和灵活。

网友意见

user avatar

首先,sim是可以用local workspace的,比如

       function the_best_function() ... options = simset('SrcWorkspace', 'current'); sim(modelname, [], options) ... end     

更新一点的版本里可以直接用

sim(modelname, ‘SrcWorkspace’, ‘current’)

但是注意这个方法不能和PCT(并行计算工具箱)一起用。




然后,如果要用PCT的话,可以这样搞

hw = get_param(modelname, ‘modelworkspace’)
hw.assignin(variablename, value)

也就是把变量assign到模型的model workspace里面。不过这种方法会把模型变dirty,所以如果函数的开头用

open_system(modelname)

或者

load_system(modelname)

那么结尾最好用

close_system(modelname, 0)

避免保存修改的模型


以上这些基本技巧应该够用了


最后,重要的事情说三遍:不要用全局变量,不要用全局变量,任何情况下都不要用全局变量。

类似的话题

  • 回答
    好的,咱们今天就来聊聊如何在 MATLAB 自定义函数(而不是直接写在 m 文件里)里面,把 Simulink 模型跑起来。你有没有遇到过这样的场景:你写了一个 MATLAB 函数,里面有很多参数需要调整,你想用 Simulink 来模拟这个系统的不同工况,然后把 Simulink 的输出结果通过 .............
  • 回答
    经济内循环,这个词近几年我们听到太多了,听起来高大上,但具体怎么实现,可能很多人跟我一样,心里没个特别清晰的谱。我个人觉得,它不是一拍脑袋就能实现的,更像是一个系统工程,需要我们方方面面都动起来,而且是动得恰到好处。首先,得明白内循环的核心是什么?简单来说,就是让国内的生产、消费、投资、分配这几个环.............
  • 回答
    想从头开始搭建一个属于自己的数据库系统?听起来有点像个大工程,但别担心,这其实是一个循序渐进的过程。我来跟你好好聊聊,怎么从最基础的概念出发,一点一点地构建一个能用的、简单的数据库系统。这篇文章不会像那些冷冰冰的AI教程,咱们就当是老朋友之间聊技术,把事情说透了。首先,我们得明确“数据库系统”到底是.............
  • 回答
    .......
  • 回答
    核聚变发电,听起来就像科幻小说里的情节,但它却是人类一直以来追求的终极能源梦想之一。简单来说,核聚变就是把两个轻原子核,像氢一样,在极高的温度和压力下“捏”在一起,形成一个更重的原子核,同时释放出巨大的能量。这和我们目前广泛使用的核裂变发电完全不同,后者是通过分裂重原子核来获取能量。为什么说核聚变是.............
  • 回答
    抗日战争时期,八路军作为中国共产党领导的一支重要的抗日武装力量,其通讯保障是贯穿整个战争的关键环节。在极其艰苦的条件下,八路军通过多种手段和方法,克服了通讯器材落后、技术力量薄弱、敌特破坏等重重困难,基本实现了对各部队的指挥和信息传递。下面将详细讲述八路军在通讯方面的实现方式:一、 主要通讯手段:八.............
  • 回答
    你家里的预埋五类线(Cat 5)想要实现千兆网络,这事儿,咱们得好好唠唠。别看它名字里有个“五”,好像有点老掉牙,但仔细琢磨琢磨,它在很多情况下,真不是没救。不过,要彻底跑上千兆,也得看点“缘分”,也就是你家里的具体情况。首先,咱们得弄清楚,这个“五类线”到底是个啥?五类线,学名叫Category .............
  • 回答
    sizeof 关键字在 C++ 中,并不是一个普通的函数,而是一个编译时常量。理解它的实现,关键在于区分它在编译期和运行时的行为。1. 编译期的魔法:类型的大小计算当你使用 `sizeof` 关键字时,比如 `sizeof(int)` 或者 `sizeof(MyClass)`,编译器会立即在编译阶段.............
  • 回答
    .......
  • 回答
    .......
  • 回答
    .......
  • 回答
    .......
  • 回答
    .......
  • 回答
    .......
  • 回答
    .......
  • 回答
    芯片中集成几千万甚至数十亿个晶体管,这是现代电子工程的奇迹。这一切的实现离不开以下几个关键方面的协同作用:1. 集成电路(IC)技术的核心:微电子制造工艺 硅基底(Silicon Wafer): 芯片制造的第一步是使用高纯度的硅晶圆作为基底。硅是一种半导体材料,可以通过掺杂(引入其他元素,如硼或.............
  • 回答
    香水中的花香味,绝大多数确实是提取自鲜花的,但具体实现过程远比我们想象的要复杂和精细。简单来说,花香味的实现是一个集生物提取、化学合成、调香艺术于一体的复杂过程。下面我们来详细讲述: 一、 天然提取:从鲜花中获取芬芳这是最传统、也最能代表“花香”的来源方式。天然花香的获取主要依赖以下几种提取技术:1.............
  • 回答
    一字涨停一字跌停,听起来像是市场里的“传说”,但其实,它是特定条件下市场行为的一种极端体现,背后有着清晰的逻辑和机制支撑。想要实现这种极端走势,需要 极度的供需失衡 且这种失衡在交易时段内 持续且不可打破。咱们一点点来拆解。 为什么叫“一字”?首先,这个“一字”就很有画面感。在股票K线图上,当股价在.............
  • 回答
    美国的司法独立,是一个建立在三权分立、互相制衡的宪法框架下的复杂而精妙的体系。总统任命大法官是这个体系中的一个重要环节,但恰恰是这个环节的设计,为司法独立提供了保障。要理解司法独立如何实现,我们需要深入剖析美国宪法的设计理念以及配套的制度安排。首先,要明白司法独立并非意味着司法机构完全不受任何外部干.............
  • 回答
    断电后报警灯如何工作,这事儿说起来也挺有意思,它背后其实藏着一些小小的“心机”。你想想,咱们平时用的灯,插着电才能亮,对吧?但报警灯不一样,它在断电这种关键时刻,反而要闪烁或者鸣响,这就得有点特殊的本事才行。咱们先得明白,一个正常的报警灯,它的基本工作原理就是通电后,通过内部的电路控制,让灯珠发光或.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有