Simulink Model Reference:模型模块化拆分与集成实践指南

Simulink Model Reference:模型模块化拆分与集成实践指南 1. 为什么大型 Simulink 模型需要 Model Reference1.1 从一个常见的开发痛点说起很多刚开始接触 Simulink 的同学应该都有过这样的经历在做一个完整的控制系统、车辆动力学模型或者电力电子变换器仿真时把所有模块都在同一个模型文件里连线从输入到输出一路连到底。模型规模不大的时候这种方式确实直观双击打开就能看到全部逻辑调参也方便。但是当模型逐渐变大问题就来了。比如一个完整的纯电动汽车整车模型可能包含动力电池系统、驱动电机系统、整车控制器、驾驶员模型、热管理系统等。如果所有内容都堆在同一个.slx文件里会面临几个非常现实的问题打开慢、编译慢模型稍微复杂一点每次更新图或者启动仿真都要等待较长时间。多人协作困难同一个模型文件同一时间只能由一个人打开团队成员想并行开发是不可能的。模块复用率低同一个控制算法如果在多个项目里都要用只能复制粘贴算法一改就要同步修改多处。功能边界模糊做底层软件的和做上层策略的都在维护同一个文件很容易出现误改、冲突。我之前在参与一个电机控制项目时就遇到过这种情况模型里既有电机本体模型又有弱磁控制算法还有 PWM 调制和故障保护逻辑加起来几百个模块挤在一个文件里。每次运行仿真前光编译模型就要等一分多钟而且只要有人动了某个环节整个模型就可能报错。后来把模型按功能拆分成多个独立文件用 Model Reference 模块进行集成问题才真正得到解决。1.2 Model Reference 模块是什么Model Reference 是 Simulink 中用于“模型引用”的模块。它的核心思路很简单把被引用模型当作一个独立的组件主模型通过 Model 模块来调用这个组件。从 Simulink 库浏览器的角度来看Model Reference 模块位于Simulink / Ports Subsystems / Model也可以直接在建模画布中输入 “Model” 三个字母通过搜索框快速找到。从功能上讲Model Reference 允许你创建一个独立的 Simulink 模型文件比如Controller_LowPass.slx然后在另一个模型主模型中添加一个 Model 模块指向这个文件。主模型通过 Model 模块的输入输出端口与被引用模型交换信号。仿真时主模型会自动加载并执行被引用模型的内容。这种方式和“子系统Subsystem”在功能上有相似之处但在工程管理、代码复用、模型编译和代码生成方面Model Reference 具有明显的优势。1.3 Model Reference 与传统 Subsystem 的区别很多人第一次接触 Model Reference 时会把它和子系统搞混。它们确实都可以把一组模块封装起来但从本质上讲两者有很大的不同对比维度Subsystem 子系统Model Reference 模型引用存储方式保存在主模型文件内部被引用模型是独立的.slx文件复用方式复制子系统时是拷贝一份多个模型可以引用同一个模型文件编译方式随主模型一起编译被引用模型可单独编译、缓存多人协作同一文件难以并行开发不同人员可独立开发不同模型代码生成生成代码内嵌到父模型中可为被引用模型单独生成函数/代码仿真加速加速模式有限支持 Normal、Accelerator、Rapid Accelerator模型封装可以封装参数支持通过 Model Arguments 传递参数简单总结一下如果你只需要把一个功能块收拾整齐用 Subsystem 就足够了如果你需要把一个完整的算法、控制策略或对象模型做成可独立维护、可复用、可并行开发的组件就优先考虑 Model Reference。2. Model Reference 的典型应用场景2.1 大型模型的模块化拆分Model Reference 最常见的用法就是把一个复杂模型拆成多个独立模型文件。比如整车控制器模型可以拆成VCU_Input.slx、VCU_Strategy.slx、VCU_Output.slx然后在顶层模型中用三个 Model 模块把它们组装起来。拆分的核心原则是“按功能边界划分”而不是按模块数量平均分。每个被引用模型应该是一个相对独立的可复用单元有明确的输入输出接口尽量避免模块之间跨文件引用工作区变量防止出现隐性耦合。2.2 团队协作与并行开发在项目开发中不同模块往往由不同人员负责。使用 Model Reference 后A 同学可以专注于开发Plant_Model.slxB 同学同时开发Controller_Model.slx两者不互相影响。每人负责的模型都是独立的.slx文件提交到 Git 或 SVN 后各自维护各自的版本。主模型只需要在集成阶段统一更新引用即可不需要把所有人的工作都合并到一个文件中。2.3 模型复用与版本管理如果你在公司里沉淀了一套成熟的算法模型比如扩展卡尔曼滤波 SOC 估计模型、无传感器 FOC 控制模型那么通过 Model Reference可以在多个项目模型中直接引用同一个模型文件。算法升级时只需要更新被引用模型然后让所有使用它的项目重新仿真验证即可。配合 Simulink 的模型版本管理还可以实现同一模型的不同版本切换方便回溯和对比。2.4 代码生成与硬件在环仿真Model Reference 在自动代码生成场景中也非常重要。通过 Embedded Coder可以为被引用模型生成独立的 C 函数或 C 类而这些生成的函数可以直接部署到嵌入式系统中。同时被引用模型支持多种仿真模式其中“Rapid Accelerator”模式可以与外部硬件实现快速联合仿真也可以配合“外部模式External Mode”进行参数在线整定和信号监测。这也是为什么很多汽车电子和工业控制项目会优先选择 Model Reference 而不是传统的子系统。3. 环境准备与版本说明3.1 MATLAB/Simulink 环境要求Model Reference 功能从 Simulink 早期版本就已经存在不同 MATLAB 版本在界面细节、参数名称和性能方面会有一些差异但核心概念是通用的。本文示例基于常见的 MATLAB R2020b 及以上版本编写界面截图位置可能与你的版本略有差别但参数名称基本一致。如果你的版本较旧遇到找不到某个参数名的情况可以优先查看当前版本的 Simulink 文档确认参数是否发生了重命名。3.2 模型规划与目录结构在实际建模之前建议先规划好工程目录。下面是一个推荐的目录结构Project_Root/ ├── models/ │ ├── Main_Model.slx │ └── components/ │ ├── Controller_LowPass.slx │ └── Plant_SecondOrder.slx ├── data/ │ └── params.m ├── scripts/ │ └── setup_workspace.m └── results/ └── sim_output/这样的好处是被引用模型统一放在components子目录中方便管理和修改。初始化脚本、参数文件和数据文件分开避免把工作区变量散落在各处。生成的仿真结果和中间文件不会污染工程根目录。3.3 准备一个最小的实验模型为了让后面的实战案例更清晰我们准备两个简单的模型Controller_LowPass.slx一个一阶低通滤波器输入是带噪声的信号输出是滤波后的信号。Plant_SecondOrder.slx一个二阶惯性环节模拟被控对象。主模型Main_Model.slx中引用这两个模型组成一个闭环系统。你不需要完全按照我这里的模型名称来建可以换成你自己的命名规范但建议保持一致方便对应阅读。4. Model Reference 核心原理与参数解析4.1 被引用模型的接口要求并不是任何模型都可以直接被引用为 Model Reference。被引用模型需要满足一些基本条件必须有明确的输入输出端口使用 Inport 和 Outport 模块定义接口。不能包含某些顶层模块比如没有实际信号的 To Workspace 模块可能会在引用时报错。模型求解器配置建议与被引用场景匹配如果主模型是变步长仿真被引用模型建议也使用变步长如果主模型是定步长被引用模型通常也应为定步长。尽量避免直接使用基础工作区变量因为被引用模型被加载时变量的可见性可能与预期不同。推荐使用数据字典或者模型参数Model Arguments传递。4.2 Model 模块的配置参数选中 Model 模块后双击打开参数设置窗口最常用的几个配置项如下Main 选项卡Model name被引用模型的文件名。可以点击右侧的浏览按钮选择当前路径下的.slx文件。Parameters如果被引用模型定义了模型参数可以在这里为参数赋值实现“一个模型多种配置”。Model variant如果同一接口存在多个模型变体可以在这里选择激活哪个变体。Instance 选项卡可以查看当前 Model 模块对应的模型实例状态比如是否已经编译、是否加载成功等。Ports 选项卡显示 Model 模块的输入输出端口信息。端口数量和类型由被引用模型内部的 Inport/Outport 决定。Code Generation 选项卡可以配置代码生成相关选项例如是否为被引用模型单独生成代码、代码生成格式等。4.3 仿真模式设置Model Reference 支持三种仿真模式在 Model 模块参数中的Simulation mode下拉框里可以选择Normal普通模式在仿真过程中解释执行被引用模型不开任何加速。调试方便可以进入被引用模型内部设置断点观察信号。优点是直观缺点是速度较慢适合模型开发调试阶段。Accelerator加速模式对被引用模型生成一些缓存代码C MEX 文件从而加快仿真。这种方式适合模型已经基本稳定、仿真次数较多的时候使用。Rapid Accelerator快速加速模式被引用模型会被编译成独立的可执行目标主模型通过快速加速接口与它通信。仿真速度通常最快尤其适合被引用模型代码量很大的情况。缺点是在该模式下被引用模型的信号在线调试能力会弱一些。下面是一个通过命令行动态切换仿真模式的示例% 获取当前 Model 模块路径 modelPath Main_Model/Controller; % 切换为 Rapid Accelerator 仿真模式 set_param(modelPath, SimulationMode, Rapid Accelerator); % 检查当前设置 get_param(modelPath, SimulationMode);4.4 Model Reference 与数据字典的关系在大型项目中数据字典.sldd文件几乎是标配。数据字典集中管理信号、参数、数据类型定义避免了工作区变量散落各处的混乱。当使用 Model Reference 时需要注意一个经典问题如果想在多个被引用模型中共享同一个数据字典那么这个数据字典必须通过引用将其挂接到每个模型上。例如如果你有一个common_params.sldd里面定义了Ts 1e-4并且Controller_LowPass.slx和Plant_SecondOrder.slx都需要使用Ts那么建议在两个被引用模型中都挂接同一个数据字典而不是在主模型中挂接。这样的话即使被引用模型单独打开、单独仿真也不会出现找不到参数的问题。如果出现“找不到数据字典 xxx.sldd”的错误通常就是因为被引用模型挂接了数据字典但该字典不在 MATLAB 搜索路径中。数据字典文件被移动或重命名。主模型打开了但被引用模型没有正确加载对应的字典依赖。5. 完整实战从零搭建 Model Reference 模型接下来我们通过一个完整的例子演示如何创建被引用模型、创建主模型、添加 Model 模块并完成仿真。5.1 创建被引用模型 Controller_LowPass第一步新建一个 Simulink 模型命名为Controller_LowPass.slx并保存到工程目录的components子文件夹中。在模型中添加如下模块模块作用Inport输入信号命名为raw_signalGain增益设置滤波系数alphaIntegrator积分器对误差积分模拟滤波器动态Sum做信号加减Outport输出滤波结果命名为filtered_signal一个最简单的低通滤波器模型可以表示为一阶惯性环节[ G(s) \frac{1}{\tau s 1} ]在 Simulink 中我们可以直接用如下方式搭建Inport 进入 Sum 的正端。Sum 输出到 Gain增益为1/tau再进入 Integrator。Integrator 输出一方面作为 Outport 输出另一方面反馈回 Sum 的负端。这样闭环之后整个模型就是一个一阶低通滤波器。为了后续演示参数传递在模型的模型属性中定义参数alpha并让 Gain 模块的增益直接写为alpha。具体操作双击 Gain 模块把 Gain 参数改成alpha。在 Simulink 编辑器中点击“Model Settings”在“Parameters”选项卡中添加alpha并设置默认值0.1。5.2 创建第二个被引用模型 Plant_SecondOrder再新建一个模型Plant_SecondOrder.slx保存到components文件夹。这个模型模拟一个二阶被控对象[ P(s) \frac{\omega_n^2}{s^2 2\zeta\omega_n s \omega_n^2} ]搭建方式Inport 输入控制量u。经过 Gain 模块增益为wn^2。经过两次 Integrator。输出端作为 Outport。从第一个积分器输出引反馈到输入求和处反馈系数为2*zeta*wn。从第二个积分器输出引反馈到输入求和处反馈系数为wn^2。将两个反馈系数写入模型参数名称分别定义为zeta和wn默认值可以设置为0.8和10。5.3 创建主模型 Main_Model新建Main_Model.slx作为顶层模型。在模型画布中引用两个被引用模型。操作步骤从库浏览器中拖入两个 Model 模块。双击第一个 Model 模块修改Model name为components/Controller_LowPass。双击第二个 Model 模块修改Model name为components/Plant_SecondOrder。添加一个 Step 阶跃信号作为输入连接到 Controller 模块的输入。把 Controller 的输出连接到 Plant 的输入。把 Plant 的输出反馈到 Controller 的输入形成负反馈需要添加一个 Sum 模块使实际输入为“目标值 - 反馈值”。连接关系Step -- Sum() -- Controller_LowPass -- Plant_SecondOrder -- Scope ^ | |________________________________|在模型中加入一个 Scope 模块用于观察系统响应。5.4 配置参数并运行仿真在运行之前需要在主模型中设置好被引用模型的参数值。选中 Controller_LowPass Model 模块在参数设置中找到Parameters列表为alpha赋值0.2。选中 Plant_SecondOrder Model 模块为参数赋值为zeta 0.8 wn 10然后回到主模型设置仿真时间为5秒点击运行。如果一切正常Scope 中会显示一条平滑的阶跃响应曲线超调量大约在几个百分点以内然后逐渐稳定到 1说明闭环系统工作正常。这其实就是一个非常典型的“被控对象 控制器”闭环模型只是我们用 Model Reference 的方式把两个部分拆成了独立文件。5.5 通过 MATLAB 命令行完成模型引用设置除了通过界面操作Model Reference 也可以通过命令行自动配置这在自动化测试和批量建模时非常有用。% 打开主模型 open_system(Main_Model); % 添加一个 Model 模块 add_block(simulink/Ports Subsystems/Model, Main_Model/Controller); % 设置被引用模型名称 set_param(Main_Model/Controller, ModelName, components/Controller_LowPass); % 设置仿真模式为加速模式 set_param(Main_Model/Controller, SimulationMode, Accelerator); % 设置模型参数 set_param(Main_Model/Controller, ... ParameterArgumentNames, alpha, ... ParameterArgumentValues, 0.2);需要注意的是ParameterArgumentNames和ParameterArgumentValues的具体取值方式和版本有关如果执行报错请参考当前版本的set_param帮助文档。6. Model Reference 的高级应用6.1 使用 Model Arguments 实现一个模型多配置上文提到过通过 Model Arguments 可以让同一个被引用模型在不同的主模型中表现出不同的参数。举个例子假设Plant_SecondOrder.slx需要用在不同项目中项目 A 的阻尼比zeta 0.5项目 B 的阻尼比zeta 1.2。我们不需要复制两份模型文件只需要在引用该模型时在 Model 模块的 Parameters 里传入不同的参数值即可。这就相当于把模型变成了一个可配置的“函数”输入是端口信号参数是模型参数。从架构上讲这种方式让模型复用能力大大提高。6.2 使用 Model Variant 实现多版本切换有时候同一个控制接口会有几套不同的实现方案比如 “PID 控制” 和 “滑模控制”。如果我们希望在做仿真对比时快速切换可以使用 Model Variant。操作方式在模型资源管理器中创建变体控制变量例如Variant_Controller PID。将多个被引用模型放在同一个 Model Variant 中。运行时根据变量值选择激活哪个模型。这种方式的优点在于代码生成时只生成选中变体的代码不会把无关代码编译进去对最终产品的代码体积非常友好。6.3 为 Model Reference 生成独立 C 代码在嵌入式开发中一个常见需求是“被引用模型单独生成一个 C 函数方便集成到我的工程里。”使用 Embedded Coder 时可以对被引用模型单独配置代码生成打开被引用模型。在 Model Settings 中配置 Code Generation选择目标语言为 C。如果需要生成独立的函数接口把 Code Generation 选项中的“Generate code only for the model reference”勾选上。生成后在slprj目录下可以找到该模型对应的源代码文件。这样生成的代码可以作为一个独立模块集成到底层软件中。这种能力在汽车电子AUTOSAR 软件组件映射和工业控制中非常常见。6.4 Model Reference 与外部模式External Mode外部模式是 Simulink 与嵌入式硬件联合调试的重要功能。通过外部模式可以直接在物理控制器上运行 Simulink 模型然后通过宿主机实时调整参数和观察信号。使用 Model Reference 时建议把需要在线标定的模块放到被引用模型中外部模式支持对模型引用模块进行参数在线修改和信号监测。不过在连接硬件前需要确认目标硬件是否支持外部模式。是否已经为目标硬件配置了合适的硬件支持包。被引用模型是否能够编译为可下载到目标板的可执行文件。7. 常见问题与排查思路7.1 找不到被引用模型文件错误现象当打开主模型时提示找不到被引用模型例如Cannot find the model file components/Controller_LowPass.slx.常见原因被引用模型被移动到其他目录。主模型保存时使用的路径和当前路径不一致。被引用文件没有保存在当前 MATLAB 搜索路径中。解决思路检查目录结构确认.slx文件是否存在。将components目录通过addpath添加到 MATLAB 路径中。重新打开主模型Model 模块会自动刷新。% 将 components 目录加入搜索路径 addpath(fullfile(pwd, components)); savepath;7.2 找不到数据字典错误现象原因: 找不到数据字典 can.sldd。 组件: Simulink | 类别: Model 错误常见原因数据字典文件.sldd被移动或重命名。被引用模型挂接了数据字典但打开主模型时没有同步加载依赖。数据字典文件不在 MATLAB 搜索路径中。解决思路在 MATLAB 中执行which can.sldd查看字典是否可被找到。如果不可找到将该字典所在目录加入搜索路径。打开主模型前先手动打开一次被引用模型确认其能正常加载字典。如果字典路径发生了变化可以打开 Model Explorer找到被引用模型的 Data Dictionary 设置重新指定字典路径。7.3 LAPACK 加载错误错误现象Caused by: LAPACK loading error: mllapack.dll常见原因这种问题通常和 MATLAB 运行环境有关常见原因包括杀毒软件或系统权限阻止了 MATLAB 加载动态链接库。MATLAB 安装目录中包含中文或特殊字符。缺少必要的 Microsoft Visual C 运行库。MATLAB 版本和操作系统兼容性有问题。解决思路以管理员身份重新运行 MATLAB。检查 MATLAB 安装路径是否包含中文如果包含建议重装到纯英文路径。安装/修复 Microsoft Visual C 运行库。在 MATLAB 命令行中运行ver检查是否有组件缺失提示。如果问题依然存在考虑使用matlab -clean启动清除缓存。7.4 模型引用层数过多导致编译失败Model Reference 是支持嵌套引用的也就是被引用模型内部还可以继续引用其他模型。但是模型引用层级过多会导致编译时间暴涨甚至出现内存不足或编译失败。建议层级控制在 3 层以内。如果确实需要深层嵌套可以优先考虑把内部的 Model Reference 改为子系统或者用模型变体减少活跃的引用层。7.5 仿真结果与单一模型不一致有时候你会遇到一种情况同一个模型直接放在主模型中仿真结果正常但用 Model Reference 引用后结果发生了细微差异。可能的原因有被引用模型和主模型的求解器配置不一致。被引用模型的采样时间与主模型不匹配。被引用模型使用了绝对时间或全局变量多次引用时产生了状态冲突。仿真模式从 Normal 切换为 Accelerator/Rapid Accelerator 后存在数值精度差异。排查建议优先使用 Normal 模式对比结果。检查模型中的Clock、To Workspace等模块的使用方式。确认被引用模型是否有隐藏的全局状态。7.6 如何让封装的模型设置密码有同学会问到“Simulink 如何对封装的模块设置密码”这类问题。严格来说Simulink 模块没有内置的“密码保护”功能但可以通过以下方式做一定程度的保护使用 Simulink 的“模型属性”保护功能将模型设置为只读或不可修改。使用 Simulink Coder 生成代码发布的模型中只保留代码不发布.slx模型文件。在公司环境中使用 Simulink Requirements 或模型审查工具做权限管理。Model Reference 本身不能解决“防止别人打开模型”的问题但它可以做到“只给别人一个封装好的模块接口”从工程协作角度降低内容泄露风险。8. Model Reference 最佳实践与工程建议8.1 命名规范模型文件名、模型内部模块名、信号名都建议使用有意义的英文命名不要使用中文命名或者默认名称。推荐命名风格模型文件模块_功能.slx如Controller_LowPass.slx、Plant_SecondOrder.slx。模块内部模块名Filter_Alpha、Fbk_Gain。信号线名Voltage_Ref、Current_Fbk、Torque_Cmd。命名时不要使用空格和特殊字符否则代码生成阶段容易出问题。8.2 接口最小化原则被引用模型的输入输出端口数量应当尽量少。每多一个端口就多一层接口复杂性。如果多个信号在逻辑上是同一个总线的不同字段建议使用 Bus 对象把信号聚合起来然后通过一个 Bus 端口传递。这样模型接口更清晰也便于在数据字典中统一管理和类型校验。8.3 参数传递与数据字典分工建议遵循以下分工被引用模型内部的固定参数直接写入模型参数。主模型需要在集成时调整的参数通过 Model Arguments 传递。全工程共享的全局参数采样时间、物理常量放进数据字典。用于标定和测试的参数使用Simulink.Signal和Simulink.Parameter定义并标注属性。这样的层次设计可以避免“参数到处定义、改一处漏三处”的混乱。8.4 版本控制与集成流程在团队协作时建议每个模型文件作为独立 Git 仓库或者同一仓库下的独立目录管理。被引用模型的版本号可以通过模型属性中的描述字段维护。推荐集成流程各成员在自己的分支上开发被引用模型。在合并到主分支前用自动化脚本对被引用模型进行验证测试用例仿真通过。主模型只引用已经合并到主分支的模型版本。主模型集成测试通过后再进行代码生成和硬件部署。8.5 仿真加速和代码生成优化在模型验证阶段可以使用 Normal 模式在批量仿真和参数扫描阶段使用 Rapid Accelerator 模式在代码生成阶段使用 Accelerator 模式提前发现可能的代码生成问题。如果模型中有大量 MATLAB Function 模块或 S-Function 模块这些模块在模型引用加速模式下可能会成为瓶颈建议提前用 Profiler 分析仿真性能找出耗时热点。8.6 安全与权限管理在工业级项目中模型往往涉及核心算法和知识产权。建议对模型文件进行权限管理按角色分配读写权限。关键算法模型生成代码后将算法抽象为动态链接库只暴露调用接口。建模过程中不依赖个人工作区变量避免他人无法运行模型。定期备份模型和数据字典模型文件如果损坏可以通过备份快速恢复。9. 总结与下一步学习建议到这里我们已经把 Model Reference 模块从概念到实战完整梳理了一遍。回顾一下本文主要讲了Model Reference 是什么和 Subsystem 有什么区别。为什么大型模型需要采用模型引用架构。如何创建被引用模型并在主模型中通过 Model 模块完成集成。如何配置仿真模式、模型参数和模型变体。常见错误的原因和排查思路。工程化实践中的命名、接口、参数、版本控制和团队协作建议。Model Reference 是 Simulink 模块化开发中一个非常重要的能力。很多初学 Simulink 的朋友喜欢把一切堆在一个模型里这种情况在学生项目、简单验证阶段没有太大问题。但一旦走上实际工程项目尤其是汽车电子、航空航天、机器人等领域模型规模和复杂度会迅速增加Model Reference 几乎是绕不开的架构选择。如果你想继续深入下面几个方向值得优先学习Simulink 数据字典把参数、信号、数据类型统一管理起来。Simulink 模型变体用一套模型框架管理多种硬件配置和算法版本。Simulink 的自动化脚本用 Matlab 脚本批量创建模型、自动设置参数、批量仿真。Embedded Coder 代码生成了解被引用模型如何生成独立 C 代码以及如何集成到嵌入式工程中。S-Function 与模型引用的结合当被引用模型中包含自定义 C 代码或 S-Function 时如何处理编译和加速模式。我在实际项目中最深的体会有两点第一模型的架构设计比建模技巧更重要一开始就规划好模型拆分边界后面会省下大量时间和精力第二模型引用不是银弹它带来模块化优势的同时也引入了编译依赖、配置管理和版本同步的复杂度需要一套明确的工程规范来约束。如果你正准备把一个大型模型拆成 Model Reference 架构建议不要一口气拆完而是先从小规模试点开始。比如先拆出一个独立的控制算法模型在主模型中引用跑通流程后再逐步拆分其他模块。等整个流程走顺了你会发现后续的调试、测试和代码生成都会变得清爽很多。如果你在搭建过程中遇到了报错欢迎把具体的错误信息记录下来对照本文的排查思路逐一尝试。很多时候问题不是出在某个参数配置而是路径、数据字典和版本依赖这类基础环节上耐心排查就能解决。