如何在不将其放入工作区的情况下向Simulink模型提供输入

10
我有一个 Simulink 模型,目前是从脚本中运行的(即不是从函数中运行)。该脚本将变量值写入 MATLAB 工作区,运行模型仿真(使用这些值),然后模型将附加值写入工作区。如果我尝试将脚本转换为函数(即在文件顶部放置 function [output] = runSim()),则 Simulink 会抱怨它不知道这些变量,可能是因为它们不在 MATLAB 工作区中,而是在函数范围内。
是否有一种优雅的方法来向 Simulink 模型提供输入并从 Simulink 模型获取输出,而不是将它们插入到工作区中?
4个回答

11

虽然不太明显,但是你可以通过sim()命令和调用函数的工作空间来输入/输出数据。我以前做过这个,而且在工作中有一个示例,但要等到周一才能去验证。不过,你可以尝试MathWorks网站上提供的解决方案

Solution:

When using variable mask parameters in Simulink, the base workspace is the default source workspace of Simulink. However, by using the SIMSET command, this workspace can be changed. SIM is then used with this options structure created by SIMSET. The following is an example on how to do this.

  options = simset('SrcWorkspace','current');
  sim('modelname',[],options)

...尽管显然在R2009b中由于与并行计算工具箱不兼容而被弃用 >:( 看起来正确的解决方案是使用assignin()将变量明确推入模拟的模型工作区(不同于基础工作区)。

http://www.mathworks.com/matlabcentral/newsreader/view_thread/292544

你有两个选项:
  1. 对于R2009b之前的版本,请查看SIMSET文档。它允许您将"SrcWorkspace"属性设置为"current",以使用来自您的函数的数据。

http://www.mathworks.com/support/solutions/en/data/1-1BWDA/?solution=1-1BWDA

  1. 在更新的版本中,此选项已被弃用,因为它不符合Parallel Computing Toolbox和PARFOR的规范。我的建议是:

http://www.mathworks.com/support/solutions/en/data/1-ASPEIV/?solution=1-ASPEIV


这个方法适用于模型引用和使用RTW编译吗? - Miebster
你需要向Mathworks的专家询问这个问题;我从未使用过RTW,也没有深入了解Simulink,除了从M文件中运行模拟。 - Jason S
第一个选项适用于2009a版本...所以我会一直使用它,直到它出现问题。谢谢! - JnBrymn
@MajorApus 我们正在使用RTW,第一个解决方案似乎有效。 - JnBrymn

2
你可以使用evalin()函数在特定工作区中执行MATLAB表达式(作为字符串)从而在你自己的函数中执行,对于SIMULINK来说,'base'是可以找到它们的。然而,如果你不想直接使用工作区,那么你可以使用From/To File模块从/到MAT文件中加载和保存信号或变量。

0

我不知道如何从一个简单的函数中实现它,但从类函数(方法)内部实现它非常方便。在2009b版本中可以很好地工作。

将代码放置在文件Test.m中:

classdef Test < handle
    properties
        mdl
        % Default input signal
        t = [0 1 1 2]'
        u = [0 0 1 1]'
    end

    methods
        function this = Test(mdl)   % Constructor
            this.mdl = mdl;
        end

        function sim(this)
            % Load model
            load_system(this.mdl);
            % Prepare model configuration
            conf = getActiveConfigSet(this.mdl);
            cs = conf.copy();
            set_param(cs, 'StopTime', '4');
            set_param(cs, 'LoadExternalInput', 'on');
            set_param(cs, 'ExternalInput', '[test.t test.u]');  % <-- 1
            % Run simulation
            simout = sim(this.mdl, cs);
            % Plot results
            tout = simout.find('tout');
            yout = simout.find('yout');
            plot(tout, yout(:,1), 'b--');
        end
    end
end

然后只需要:

>> test = Test('TestSim');
>> test.sim();

发生了什么?您创建了一个名为test的对象,它定义了t和u字段。然后在sim()方法中,您告诉Simulink查找输入“[test.t test.u]”。Simulink和sim()方法都可以访问这些变量(我认为这是最重要的事情)。

好吧,它仍然有一个大缺点,这个缺点用数字1标记。您必须明确知道类实例引用在工作区中的名称是如何命名的(在这种情况下为“test”)。您可以通过在构造函数中传递名称来解决它,或者您可以使用静态变量和方法,但这种方式不允许您动态更改输入信号。


嗯,这一开始看起来很优雅,但我相信Test对象仍然必须在基础工作区中 - 所以这只是改变了OP问题的位置。 另外,一个提示:小心将事物命名为“XXXXtest”或“textXXXX” - 你会遇到unittest框架的问题,该框架将以这种方式命名的类文件作为单元测试用例。 - thclark

0

简单回答:不可以。

我可能会错,但让我先给你一些背景。我在一个非常大的Simulink模型上工作了多年。直到今天我们仍然通过工作区加载所有必要的变量。这是我的一个长期投诉,以至于MathWorks甚至通过提供Simulink.save_vars函数来解决这个问题。听起来您已经使用脚本/函数设置了变量,因此Simulink.save_vars对您不太有用。

您可以使用结构体清理工作区中的某些变量,大多数Simulink块不支持结构体,但是一些块支持。此外,请避免将除模型需要的变量之外的任何内容放入工作区中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接