Simulin金宝appk上的家伙

金宝appSimulink和基于模型的设计

加速模式与正常模式的不同结果

博主Guy Rouleau说通过家伙卷轴

这周我收到了一个大模型,当用作一个引用模型加速模式,相比之下正常模式.为了给你一个概念,这个应用程序中的顶层模型是这样的:

表示问题的模型

在对模型进行了快速检查后,我没有发现明显的东西。加速模式使用代码生成技术来运行模拟。实时车间嵌入式编码器提供代码生成验证(CGV) API验证所生成代码与仿真结果的数值等价性。使用这个API,我决定测试为这个参考模型生成的代码。下面是它的工作原理。

日志输入数据

首先,我启用信号记录为以正常模式进入参考模型的信号。然后我扮演了顶级模特。这些数据将允许我在没有plant模型的情况下单独测试Controller子系统。

记录控制器输入数据

建立待分析的模型

从现在开始,我只需要参考模型。在这个模型中,我启用数据导入从模型配置中,以便import块可以读取先前记录的数据。

然后我启用信号记录我要比较的信号。对于第一次运行,我只记录了控制器的输出,以确认这个设置重现了问题。

为SIL测试编写一个测试脚本

CGV API设计用于对模型执行软件在循环(SIL)和处理器在循环(PIL)测试。为了编写一个脚本来验证生成的代码的数值等价性,我从文档部分开始验证模型两种执行模式之间数值等价性的实例.基于这个例子,我只花了几分钟就写了以下内容:

cgvModel =“孤立”%配置模型cgvCfg = cgv。配置(cgvModel“连接”“银”) cgvCfg.configModel ();%执行模拟cgvSim = cgv。CGV (cgvModel“连接”“sim卡”result1 = cgvSim.run()执行生成的代码cgvSil = cgv。CGV (cgvModel“连接”“银”result2 = cgvSil.run()%获取输出数据simData = cgvSim.getOutputData(1);silData = cgvSil.getOutputData(1);%比较结果[matchNames, ~, mismatchNames, ~] =...比较(simData, silData,“阴谋”“不匹配”

完成该脚本后,会出现下图,确认生成的代码的结果与模拟的结果不同。

CGV输出显示结果不匹配

找出差异的根源

为了识别差异的根源,我启用了日志记录,以便在模型中记录更多的信号。经过几次迭代之后,无需修改上面的脚本我确定了以下子系统,其中输入是相同的,但输出是不同的:

有问题的子系统

当查看生成的代码时,我发现这个子系统的行是:

(*rty_Out2) = 400.0F * (*rtu_In1) * 100.0F;

我做了一个快速测试,并手动更改代码为:

tmp浮动;
* (*rtu_In1);
(*rty_Out2) = tmp * 100.0F;

令人惊讶的是,修改后的代码产生的结果与模拟完全相同!

更新2011-03-22:注意,这并不总是有效的。下面是更多信息。

咨询专家

我必须承认,我不知道这两个相似的代码怎么会导致不同的结果,所以我问了我们的一个数值计算专家。

我了解到一些编译器使用一种叫做扩展精度.有了这种技术,当一行代码包含多个操作时,编译器可以使用更大的容器来存储中间结果。这项技术的目标是提供更准确的结果,然而在这种情况下,它也会导致意外。

在理解了这种行为之后,我们向用户推荐了一些选项来避免这种类型的表达折叠在生成的代码中,从而避免编译器的这种行为。

注意,这种差异的根本原因不是RTW表达式折叠选项,它只是碰巧绕过了编译器的行为。防止编译器使用扩展精度的正确方法是提供编译器标志,迫使它按照所写的方式进行计算。

结论

如果没有代码生成验证API,我将花费大量时间在模型中连接调试信号。这个工具帮助我在不修改模型的情况下快速识别出问题的根本原因。注意,CGV API可以做的比我在这里展示的多得多。看看CGV文档了解更多细节。

现在轮到你了

如何验证生成的代码在数值上与模型等价?留下一个这里的评论

|

评论

如欲留言,请点击在这里登录到您的MathWorks帐户或创建一个新帐户。