第一次意识到FMU这东西非学会不可,是在一个跨团队联合仿真项目上。对面团队用的是自研的仿真环境,手头根本没有Simulink的License,可我这边控制模型已经用Simulink搭完,对方等不了我重写一版。直接发slx文件,他们打不开;把整个模型导出成C代码,又牵扯到手写集成入口和接口映射,两边的软件架构根本对不上。折腾到最后,问题靠一个.fmu文件解决了——对方把FMU(Functional Mock-up Unit,功能样机单元)拖进他们的仿真框架,半小时内就完成了闭环测试。从那时起我就明白,Simulink里导出FMU不是加分项,而是跨工具协作场景下的硬技能。这篇文章我就把从配置到生成的完整流程、容易踩的坑、以及生成之后怎么验证,全部按实操顺序过一遍,适合正在做跨平台联合仿真、模型交付或者工具链整合的工程师参考。
1. 为什么非要用FMU:跨工具联合仿真的刚需
1.1 被割裂的仿真生态
搞嵌入式控制、多物理域仿真的朋友们肯定有同感:这个行业里没有任何一个仿真工具能通吃所有环节。控制系统建模用Simulink很顺手,但机械动力学模型可能在AMESim里,热管理模型可能在Dymola里,整车层面的能量管理又在自家平台上。过去常见的做法是把对方的核心模型拿过来二次建模,或者在两个工具之间做socket通信实时报文交互。前者费人力,后者耦合度高,每次改参数都要同步两边工程,极其痛苦。
FMI(Functional Mock-up Interface)标准的出现就是为了解决这个割裂问题。它定义了一套通用接口,把任何一个工具里建好的模型封装成一个标准二进制组件,也就是FMU。这个组件自带模型描述文件和可执行代码,其他支持FMI标准的工具可以像一个黑盒一样加载它、调用它、读取输出,完全不需要知道模型内部是用什么工具搭的。所以FMU本质上是一种“模型交换中间件”,相当于仿真界的PDF:你用Word排版,我不用装Office也能打开看。
1.2 两条导出路线:官方支持与第三方FMI Kit,到底选哪条
在Simulink里导出FMU,目前一共有两条主流路线,我先把它们摆在台面上让你选。
第一条是MathWorks官方支持。在较新的MATLAB版本里,通过 Add-On Explorer 搜索FMU相关的支持包,配合Simulink Coder可以完成导出,官方路线的好处是跟版本同步,新版本持续维护;坏处是License要求高、可调项偏少,而且有些历史版本对FMI 2.0的兼容并不完整。
第二条是FMI Kit for Simulink,这是Modelon维护的开源工具箱,也是工程社区里更常用的方案。它直接以Simulink菜单的形式集成在Tools栏里,导出对话框里可以自由选择FMI版本(1.0 CS、2.0 CS、2.0 ME)、目标平台(win64/win32)、通信步长等关键参数,用起来比官方方案灵活太多。
我的建议是:如果项目要求只支持FMI 2.0且你用MATLAB R2020a之后的版本,官方支持包够用;如果要做不同FMU类型的组合测试、要控制导出后的源码可见性、或者你的模型里有较多自定义配置,直接选FMI Kit。我自己长期用的是FMI Kit路线,后面所有实操步骤都基于它来写,这样你照着操作不会遇到“官方工具箱和第三方工具界面对不上”的问题。
2. 导出前的环境体检:版本、编译器、支持包缺一不可
很多人在Simulink里点导出FMU失败,第一反应是怀疑模型有问题,但我见过的案例里至少有三分之一是环境没配齐。FMU导出本质上是通过C代码生成器把模型编译成动态库,所以环境里任何一环断了都会翻车。
2.1 版本选型:R2016b是一条分界线,但别盲目追新
先说版本。FMI标准2.0在2014年发布,而MathWorks在R2016b的版本里才正式把FMU相关能力纳入主流程,所以理论上低于R2016b的版本不建议再碰FMU导出这块。你如果还在用R2015b甚至更早的版本,赶紧换个新环境,后面所有步骤都依赖新版本里的代码生成框架,老版本就算装了FMI Kit也会因为编译器接口对不上而失败。
但另一方面也别盲目追新。FMI Kit的发布版本通常滞后于MATLAB大版本更新,我见过有同事刚升级到R2023b,结果装完FMI Kit打开Simulink直接菜单消失。原因很简单:FMI Kit插件向Simulink注册菜单时,依赖一套内部API,这套API在MATLAB大版本升级时可能被改动。如果你需要用FMI Kit,建议先查一下当前MATLAB版本对应的FMI Kit版本和兼容性说明,安装前花五分钟确认,比装完再排查半天强。
2.2 编译器准备:mex -setup这一步卡住了多少人
编译器问题就是很多人卡住的地方。FMU导出过程需要Simulink Coder把模型生成C代码,再用本机C编译器编译成动态库。MATLAB自带的LCC编译器只支持生成Mex文件,不支持FMU这种带模型描述文件的完整动态库,所以你必须额外配置一个被MathWorks支持的C编译器。
Windows平台上最省心的选择是MinGW-w64编译器。在MATLAB命令行窗口先运行mex -setup,看看可用的编译器列表里有没有MinGW。如果没有,需要到MathWorks官网下载对应版本的Support Package。有个容易忽略的细节:编译器一定要和MATLAB版本匹配,R2021a以后的版本对MinGW版本有明确要求,版本不对就算列表里显示可用,实际编译FMU时也会报“undefined reference”之类的链接错误。
配置好之后,建议先随便建一个简单的Simulink模型做一次代码生成测试,确认编译链路通了再开始做正式模型的FMU导出。这个步骤能帮你把环境问题和模型问题区分开,排查效率会高很多。
2.3 支持包与License清单:缺一个都会在导出瞬间翻车
环境里另一个容易被忽略的点是License。FMU导出需要用到代码生成能力,所以至少要有:Simulink、Simulink Coder,如果模型里有MATLAB Function模块,最好再确认一下MATLAB Coder是否可用。没有Simulink Coder的话,FMI Kit面板里Export FMU按钮通常是灰色或者点击后报“no code generator license found”。
此外,FMI Kit这个工具箱本身就依赖一堆运行库,安装时它会自动把必要文件放到MATLAB路径里。需要注意的是,FMI Kit对Simulink模型里的S-Function支持是有限制的,如果你模型里有自研S-Function且没有提供对应的TLC文件,那么导出是一定会失败的。碰到这种情况,要么联系S-Function提供方要TLC文件,要么把这个模块改成纯Simulink原生模块。
我把环境体检的关键项整理成一个速查表,导出前对着过一遍:
| 检查项 | 要求 | 不满足时的后果 |
|---|---|---|
| MATLAB版本 | R2016b及以上 | FMI Kit菜单无法注册 |
| Simulink Coder | 必须有License | 导出按钮不可用 |
| C编译器 | MinGW或MSVC,版本匹配 | 编译阶段报链接错误 |
| FMI Kit版本 | 与MATLAB版本对应 | 菜单消失或选项缺失 |
| S-Function TLC | 自定义S-Function需有TLC | 代码生成失败 |
3. 模型改造:把模型修成“能被导出”的样子
环境准备妥当之后,接下来要收拾模型本身。FMU导出比普通代码生成更严格,它要求模型在结构上满足一些硬性条件,这些条件不满足,导出过程会直接报错。
3.1 求解器设置:固定步长不是建议,是硬要求
导出FMU的第一个硬性条件是求解器类型必须是固定步长。很多人习惯在建模时用默认的变步长求解器(比如ode45),这类求解器可以根据误差动态调整步长,仿真精度确实好,但FMU作为外部仿真的被调组件,外部主仿真框架需要在每一个通信周期精确控制计算推进,不可能容忍内部求解器随意变动步长。所以导出前必须打开模型配置参数,将求解器类型改为固定步长,比如ode4(四阶龙格库塔)。
具体操作为:模型窗口菜单栏点击 建模 -> 模型设置 -> Solver,将“求解器选择”中的“类型”从“变步长”改成“固定步长”,“求解器”建议选“ode4”。固定步长的大小也很讲究,步长过大,连续系统仿真精度下降;步长过小,FMU计算量增大,外部联合仿真的实时性变差。一般先根据模型里最快动态环节的时间常数来定,取时间常数的十分之一到二十分之一作为初始步长,后续再根据联合仿真效果微调。这一步看起来简单,但没有把变步长改成固定步长就点导出,大概率会在代码生成前弹出一串看不懂的报错信息。
3.2 原子子系统与端口接口设计
第二个硬性条件涉及模型结构。FMU导出以子系统为边界,你要导出的部分通常会放在模型的最上层,且这个子系统必须设置为原子子系统(Atomic Subsystem)。右键子系统模块 -> 模块参数 -> 勾选“视为原子单元”,这一步的目的是告诉代码生成器:这个子系统内部的计算不能被优化器打散,必须作为一个整体封装起来,对外的输入输出端口将直接映射为FMU的接口变量。
接口设计是个值得多花时间的环节。FMU的输入输出变量的命名、数据类型、维度,全部来自子系统端口。在正式导出前,双击输入输出端口模块(Inport/Outport),把端口名称改成具有工程含义的名字,比如“cmd_voltage”“feedback_speed”这种,而不要用默认的“In1”“Out1”。接口名一旦发布,外部团队就要按照这个名字来对接数据,后面再改会很麻烦。另外,数据类型建议统一用double,虽然FMU也支持整型、布尔等类型,但外部仿真框架对double的支持最广泛,联合仿真时不容易因为类型不匹配导致数据错位。
这里提醒一个实操细节:不要依赖和父模型共用的信号线名称来定义接口,而是必须改Inport/Outport模块本身的名称。我在项目里见过有人只改了信号线标签,没改端口模块名称,结果导出的FMU接口变量还是In1/Out1,外部团队对接时一头雾水。
3.3 排查“导出污染源”:Simscape、Stateflow等特殊模块特例
模型里如果用了特殊库的模块,需要特别警惕。Simscape物理域模块(电池、电机、液压元件等)在FMI Kit导出时经常报错,因为Simscape的物理建模代码走的是独立求解体系,生成的代码和普通Simulink代码没有统一封装接口,FMI Kit无法把它们封装成单个FMU。如果你模型里包含Simscape部件,同时又要导出FMU,一个常见的变通方案是把Simscape部分单独仿真成查表数据,再在可导出的模型里用Lookup Table替代。
Stateflow状态机模块是另一个特例。理论上它支持通过Simulink Coder生成代码,但通过FMI Kit导出时,在部分版本的MATLAB里会报“Statefun not supported”的错误。遇到这种情况,替换方案有两个:一是把状态逻辑改写成MATLAB Function模块,用纯m代码实现状态迁移;二是把状态机算好的结果存成一个时序信号,导出后让外部环境按时间序列取用。前者是正向解决,后者只适合弱耦合场景。
还有一个容易忽略的污染源是模型里引用了基础工作区变量或数据字典。FMU导出时会尝试把这些外部变量烘焙进生成的代码里,但变量解析时机和路径敏感度很高,如果换一台机器加载FMU,那些变量可能丢失导致初始化失败。稳妥的做法是在导出前,利用Model Explorer把模型用到的所有工作区变量改成模型工作区(Model Workspace)里的变量,或者用常量模块把参数固化到模型结构里。
4. FMI Kit导出全流程:从下载到生成.fmu
环境没问题、模型结构排干净之后,导出流程的绝大部分时间花在配置选项上。这一节我把FMI Kit工具从安装到导出完成的完整步骤拆开讲,确保你照着做能一次成功。
4.1 获取与安装FMI Kit:版本匹配决定成败
FMI Kit for Simulink是开源工具箱,托管在MATLAB File Exchange上,搜索“FMI Kit for Simulink”就能找到。下载前先看它支持的MATLAB版本列表,选择和你当前环境匹配的版本。下载完成后解压,得到一个包含Install.m的目录。
安装步骤其实很简单:先把整个目录加入MATLAB路径(用Set Path或者addpath命令),然后在当前目录运行Install脚本。脚本会自动完成编译、注册菜单、添加Simulink库等一整套动作。运行结束后重启MATLAB,打开任意Simulink模型,菜单栏Tools下面应该能看到“FMI Kit for Simulink”这个条目。
安装过程中最可能出问题的地方是编译环节。FMI Kit安装时需要用你本机配置好的C编译器编译它自己的运行库,如果你前面按照第2节配置过mex环境,这里一般顺滑通过。如果安装脚本报编译错误,先回到mex -setup确认编译器可用,很多情况下是编译器版本太新导致链接失败,换个旧一点但受支持的版本即可。
4.2 导出参数面板逐项过一遍
打开你要导出的模型,点击Tools -> FMI Kit for Simulink -> Export FMU,弹出导出配置面板。这个面板里参数比较多,我把每一项的含义和推荐配置整理成下表:
| 参数项 | 推荐值 | 说明 |
|---|---|---|
| FMI version | 2.0 Co-Simulation | 兼容性最好,应用最广 |
| FMU platform | win64 | 和目标机器架构一致 |
| Solver type | ode4(固定步长) | 与模型求解器保持一致 |
| Communication step size | 取模型步长整数倍 | 影响联合仿真数据交换频率 |
| Parameters | 按需勾选 | 勾选后FMU接口会暴露对应参数 |
| Input variables | 全选需要的Inport | 名称已在第3节设置好 |
| Output variables | 全选需要的Outport | 同上 |
| Include source code | 建议开启 | 便于对方跨平台重新编译 |
面板底部还有个目标文件夹选项,指定导出文件的存放路径。确认所有配置无误后,点击Export,工具会先调用Simulink Coder生成C代码,再调用编译器编译成动态库,最后打包成.fmu文件。整个过程一般在几十秒到几分钟不等,取决于模型规模和机器性能。
4.3 生成的.fmu里到底有什么
导出完成后,在目标文件夹里得到一个.fmu文件。很多人以为它是个跟simulink的slx类似的私有格式,实际上FMU就是一个zip压缩包,用解压工具可以直接打开。里面通常包含:
- modelDescription.xml:FMU的“身份证”,记录了模型名称、GUID标识、变量列表、能力标签、默认参数等信息,外部工具加载FMU时第一个读取的就是这个文件;
- binaries/win64/:编译生成的核心动态库,真正的模型计算逻辑都在这个DLL里;
- sources/:如果导出的配置里勾选了Include source code,这下面会有完整的C源码;
- documentation/:一些生成器自动打包的技术文档,以及模型快照图片资源。
理解这个文件结构对后续排查很有帮助。比如外部工具加载FMU后提示找不到某个变量,大概率是modelDescription.xml里的变量名和接口对不上;再比如对方机器是Linux环境,你的FMU只有binaries/win64目录,就只能靠sources目录里的源码重新编译。我建议每次导出后都手动解压看一下modelDescription.xml,确认变量名和参数名符合预期,这一点在多人协作的项目里能省不少沟通成本。
5. 导出选项背后:FMI版本、平台与解算器类型的选型逻辑
FMI Kit导出面板里那一堆下拉选项,很多人只是默认值一路点过去,生成出来的FMU能不能用就看运气。这些选项不是随便设的,每一项背后都对应着不同的使用场景和技术约束。
5.1 Model Exchange还是Co-Simulation
FMI标准里有两个核心变体,FMI Kit面板中通常对应选择“Model Exchange”或“Co-Simulation”。这是FMU设计时需要想清楚的最关键决策。
Model Exchange类型的FMU只包含模型方程和状态导数函数,它不负责求解,而是把导数计算能力暴露给宿主环境,由外面的仿真器自己决定用什么样的积分算法来推进。这种类型的优势是灵活,外部求解器可以根据系统级的精度需求自动调整步长;代价是要求宿主仿真环境具有强大的求解能力,而且如果多物理域模型数值刚性很强,外部求解器容易发散。
Co-Simulation类型的FMU则自带求解器,它在内部独立推进模型计算,每个通信步长向外部回传状态量。外部工具把FMU当成一个黑盒子系统,通过固定通信步长交换数据。这种类型对宿主环境要求低、集成难度小、数值稳定性更好,是目前工业界使用最广泛的形式,也是FMI 2.0里支持最成熟的能力。
如果你只是做联合仿真验证,不想花很多精力调外部求解器,选Co-Simulation是绝大多数场景的正解。如果你的目标是做一个模型库,让不同用户用不同求解器适配,Model Exchange才值得考虑。
5.2 FMI 1.0还是2.0
FMI版本的选择相对简单,但不是无脑选新。FMI 1.0在2010年推出,历史包袱重,很多老工具只支持1.0,但它的表述能力弱、参数映射逻辑混乱,新项目不建议再用。FMI 2.0是目前的事实标准,全面支持Co-Simulation和Model Exchange,接口定义清晰,几乎所有现代仿真工具(Dymola、ANSYS Twin Builder、GT-SUITE、Python的PyFMI等)都能稳定加载。
选版本前先确认接收方的工具版本。如果对方明确说只能导入FMI 1.0,你不用犹豫,直接选1.0,宁可接口简单也不要让对方工具加载不了;如果对方没有特殊要求,默认FMI 2.0 Co-Simulation是最稳妥的选择,后续迁移和扩展空间都更大。另外提一句,FMI 3.0标准已经发布,但当前第三方工具覆盖度还不高,Simulink侧的工具链支持也参差不齐,暂时不用急着上。
5.3 通信步长与数值稳定性
Co-Simulation方式下,FMU内部由自带求解器推进,但每个通信周期要跟外部框架交换一次数据,这个交换的时间间隔就是通信步长(Communication Step Size)。这个参数经常被忽略,但直接决定联合仿真的数值稳定性。
通信步长比模型内部求解步长大很多时,相当于外部系统在拿较大的数据间隔去同步变量,对于快速动态环节会造成“采样失真”,最终表现为仿真曲线发散或出现非物理的振荡。反过来,通信步长设得太小又会让外部框架的调度开销增大,仿真速度明显下降。
实际项目里的调法一般分两步:第一步,用模型内部固定步长的整数倍作为通信步长,比如模型步长1ms,通信步长取10ms,保证内部计算和外部通信的解耦;第二步,跑一次联合仿真观察波形,如果高频振荡就逐步减小通信步长,如果速度过慢就逐步增大。整体来说,通信步长应与最快动态环节的时间常数匹配,而不是追求越小越好。
6. 实战排查:导出失败到运行异常的四类高频问题
就算前面的配置全都做对了,实际操作中还是会遇到各种奇奇怪怪的问题。这一节我挑四类最高频的,把完整的排查链路写出来,而不是只给结论,这样你下次遇到类似报错也知道从哪里下手。
6.1 求解器约束引发的第一类报错
报错现象:点击导出之后,FMI Kit面板很快弹出红色错误,日志里出现“model is configured for variable-step solver”或者“Sample time must be fixed”字样。
排查链路:这个报错已经非常明确地告诉你问题出在求解器设置上。打开模型设置 -> Solver界面,先确认“类型”是不是固定步长。如果确实是变步长,改成固定步长再导出。还有一种隐蔽情况是虽然顶层模型设置了固定步长,但内部某个子系统或模块显式指定了变步长采样时间,导致整个模型仍然被判定为变步长系统。排查方法比较笨但有效:在MATLAB命令行执行“bad = sldiagnostics(model, 'Compile')”查看诊断信息,或者在模型窗口里用“显示采样时间”高亮出所有非固定步长的模块,定位后把该模块的采样时间改为-1(继承)或显式固定值。
6.2 编译器与路径导致的第二类报错
报错现象:代码生成阶段正常,但编译阶段报错,错误信息可能是“gmake: No rule to make target”“unable to open file .obj”或者直接是“Error using mex”。
排查链路:这类问题先检查编译器配置。在命令行运行mex -setup,确认当前选择的编译器是MinGW。如果之前配置过,但最近更新过MATLAB版本,编译器配置可能被重置,重新设置一下即可。还有一种容易被忽略的情况是工程路径里有中文、空格或特殊字符。FMI Kit在调用编译器时,编译器对带空格路径的处理能力很弱,尤其是路径在C:\Users\张三\这种带中文的目录下,编译失败极大概率是这个原因。把整个工作目录复制到纯英文路径下,比如D:\FMU_Project,重新导出,问题一般能直接消失。
这条经验我说了很多次,但每次都有同事踩坑,在这里再强调一次:项目路径务必使用全英文、无空格。
6.3 换机器运行时的数据接口暗坑
报错现象:FMU导出成功,在自己机器上联合仿真没有问题,但发给对方之后,对方加载FMU直接报“FMU initialization failed”或者“variable not found”。
排查链路:这种问题最常见的根源是FMU里暴露的参数变量引用了外部工作区变量。如果你在导出前没有按第3节的方法把参数固化到模型工作区,生成的FMU会把变量名写入modelDescription.xml,但变量的初始值在加载时从外部上下文读取——本机跑的时候Simulink环境还在,变量自然能解析到;换了一台干净机器,Simulink环境都没有,变量就是未定义状态。解决方式是在导出前用Model Explorer把参数保存到模型工作区,或者在FMU导出面板的Parameters选项卡里给每个参数显式填入初始值。
另一种情况是对方工具不支持你选的FMU平台类型。比如你在win64机器上导出了含win64二进制的FMU,结果对方在Linux服务器上部署,自然跑不起来。这时如果你的导出配置里开启了Include source code,对方可以用自己的工具链重新编译该FMU,否则只能要求生成平台对应的FMU文件。这也是为什么我在第4节强调开启源码选项的原因。
6.4 特殊模块限制与降级方案
报错现象:导出时提示“unsupported block type”“Simscape components are not supported for FMU export”。
排查链路:按第3节里查污染源的方式,在模型里搜索Simscape、Stateflow、自定义S-Function这几类模块。找到之后,不建议强行在同一个模型里导出,更推荐做模型拆分:把可导出的控制逻辑部分做成FMU,把物理模型留在本地做仿真环境,二者通过外部联合仿真方式对接。这样双方的边界清晰,FMU接口也更稳定,不会因为物理模型的复杂度导致FMU文件异常庞大。
如果物理模型的精度要求不高,也可以用查表法替代:离线把物理模型的输入输出关系完整扫一遍,生成一个n维Lookup Table放进模型里。这个方法适合静特性和缓变特性场景,快速动态过程不建议用,查表延时会引入差异。
7. 验证收尾:让FMU“对得上外部接口”才算完工
导出完不是终点。FMU生成的瞬间你只能确认代码编译没问题,无法确认接口数据、仿真行为、参数暴露是否符合预期。FMU到了外部环境里才暴露出问题,代价往往是项目进度延误。所以导出后的验证环节不能省。
7.1 用官方合规检查器做体检
FMI标准组织提供了官方合规检查工具FMI Compliance Checker,可以直接从fmi-standard.org下载。它支持对指定FMU文件做合规性检查,自动判断FMU是否符合FMI 2.0标准要求、各种可选能力是否按规范实现。
操作很简单:打开工具界面,加载FMU文件,选择要检查的标准版本和平台类型,点击运行。工具会输出一份报告,列出发现的问题和警告。比如GUID是否是有效的UUID、变量命名是否合法、platform类型是否与二进制内容匹配等。我习惯每次导出后在发版前跑一遍合规检查,这一步能拦截大多数“我自己跑没问题但别人工具不认”的坑。
7.2 用PyFMI做最小接入验证
合规检查只证明格式正确,证明动态行为可信还得真正把FMU拉起来跑一遍。最快速的环境是Python配合PyFMI库,它是一款开源FMU加载器,支持FMI 2.0 Co-Simulation和Model Exchange。在Python环境里写一个最小验证脚本,加载FMU、设置参数、跑一段时间仿真、检查输出曲线是否符合预期:
from pyfmi import load_fmu model = load_fmu('Pendulum.fmu') # 替换成你的FMU文件 # 可选:修改FMU内部可调参数 model.set('length', 1.2) # 仿真10秒,每0.02秒输出一个结果 opts = model.simulate_options() opts['ncp'] = 500 res = model.simulate(final_time=10.0, options=opts) # 打印最后一个时刻的角度输出 print(res['angle'][-1])脚本跑通并且结果和模型内部仿真一致,说明FMU在外部环境下的行为与Simulink内仿真对齐了;脚本如果报错,把报错信息贴回第6节四类问题里对号入座。这个方法也适合你提前帮接收方踩一遍雷,避免把不确定性带到联调阶段。
7.3 发布前对照检查清单
最后给一张发布前检查清单,我每次对外提交流程时都按这个来,建议你也收藏一份:
- 模型求解器为固定步长,没有变步长残留;
- 参数已固化,不依赖基础工作区变量或数据字典;
- 接口变量名称已定义并经过命名评审;
- 导出的FMU已通过FMI Compliance Checker检查;
- 使用PyFMI(或其他工具)跑通了最小仿真验证;
- 确认接收方工具支持的FMI版本与平台类型;
- 检查FMU文件大小和依赖,确认没有引用外部相对路径。
做完这一整套再发出去,基本不会再收到对方的“加载失败”或者“仿真发散”之类的消息。我在实际项目里养成这个习惯之后,交付FMU的一次性通过率提高了很多,也顺便帮对接团队省了大量排查时间。如果你在导出过程中遇到和上面四类问题都不太一样的状况,建议第一步把FMI Kit生成的日志目录完整保留,日志文件里的编译信息和错误码往往比弹窗提示要多得多,拿着它定位基本能顺藤摸瓜找到根因。