ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Adams与Matlab联合仿真实战指南:从环境配置到模型跑通

Adams与Matlab联合仿真实战指南:从环境配置到模型跑通 Adams和Matlab联合仿真这件事我在刚接触的时候差点被劝退。网上教程零零散散要么只讲Adams里面怎么建模要么只给一段Matlab代码让你自己悟真正把“两个软件怎么把数据接上”这层窗户纸捅破的内容少之又少。我第一次按着某篇博客操作卡在adams_sys模块一直报错折腾了整整一个周末最后发现是版本不匹配和环境变量的问题根本没到模型那一步。所以这篇东西我想写成那种“当年我自己最想看到的教程”——从为什么要联合仿真讲起到你第一个模型完整跑通的每一步再到跑通之后那些你大概率会踩的坑全部摊开来讲。1. 为什么要费劲把Adams和Matlab接在一起单一工具解决不了机电耦合问题很多刚入门的朋友会问一个特别实在的问题Adams自己就能做动力学仿真Matlab里的Simulink也能搭建物理模型为什么非要把两个软件联合起来用1.1 Adams和Simulink各自擅长什么Adams的核心优势是多体动力学求解。你可以把它理解成一个“机械系统运动求解器”它对刚体之间的约束、接触碰撞、大位移运动、非线性摩擦这些问题的处理能力非常强。不管是汽车悬架的跳动还是机器人手臂的挥舞在Adams里建模都能获得相当可靠的运动学和动力学结果。Simulink的强项在控制系统和信号处理。PID控制器、状态观测器、滤波算法、逻辑判断这些控制策略在Simulink里搭建和调试非常顺手。你可以在Simulink里跑一个复杂的控制算法实时观察系统响应快速迭代参数。关键在于真实的机电系统机械本体和控制算法是一个整体。执行器施加力到机械结构上机械结构产生运动传感器测量运动状态反馈给控制器控制器再调整执行器的输出——这是一个闭环。1.2 联合仿真解决的核心问题用Adams独立仿真时你想模拟一个电机驱动负载的场景只能通过函数表达式近似拟合电机的输出特性。但如果你需要精确验证一个带PID控制的伺服系统在启停瞬间的响应靠函数拟合会非常痛苦而且很难调参。用Simulink独立仿真时虽然Simscape Multibody也能做多体动力学但在面对复杂约束、接触碰撞、大变形这些场景时求解效率和稳定性跟Adams相比还是有差距的。联合仿真的逻辑就是让专业工具干专业的事Adams负责把“机械本体”这半边算准Simulink负责把“控制系统”这半边算准两个软件在设定的时间步长上交换数据——Adams把当前时刻的位移、速度、加速度这些状态量送给SimulinkSimulink根据控制算法计算出控制力、力矩回传给Adams如此循环推进。注意联合仿真和“协同仿真”在工程语境下经常混用指的是一回事。本质就是两个求解器在运行过程中实时交换数据而不是把模型导出到另一个工具里重新求解。这篇教程面向的读者是那些学过理论力学和自动控制原理但还没动手做过联合仿真的人。不需要你精通Adams的高级宏命令也不需要你是Simulink专家只要会基本操作跟着一步步做就能把第一个模型跑起来。2. 搭建环境的前置功课版本匹配、环境变量和接口插件先说一个扎心的现实联合仿真失败的案例里至少有一半是栽在环境配置环节不是模型问题。这个环节的相关信息最零散所以这里先把它彻底讲清楚。2.1 版本匹配是第一道门槛Adams和Matlab之间通过一套叫Adams Controls的接口模块进行通信。这个接口对不同版本的软件支持程度不一样盲目选版本会吃大亏。Adams版本推荐的Matlab版本区间注意事项Adams 2013-2016MATLAB 2012b-2016b老接口稳定性不错但新系统上可能有问题Adams 2017-2020MATLAB 2016b-2020b使用较广泛资料最多推荐入门Adams 2021-2023MATLAB 2020a-2023a新接口注意检查mex文件兼容性Adams 2024MATLAB 2022b以上需要确认官方发布说明里的验证列表一个残酷的经验是Adams和Matlab版本差得太大接口的mex文件几乎必然加载失败报错形式五花八门最常见的是“Unable to load mex file”或者“Invalid MEX-file”。所以如果条件允许优先选择同一时期发布的版本组合这是最省心的方案。2.2 环境变量配置大多数人忽略的关键一步Adams安装完成后需要确保以下环境变量在系统变量中存在否则Matlab可能连Adams的接口函数都找不到。ADAMS_CONTROLS_USE_MDIFLAG设置为YES这是老版本需要的标志新版本也要确认一下ADAMS_CONTROLS_BIN_PATH指向Adams的controls插件可执行文件目录通常是C:\MSC.Software\Adams\2021\controls\win64这样的路径ADAMS_BIN_PATH指向Adams主程序目录通常是C:\MSC.Software\Adams\2021\win64一个非常容易踩的坑是系统位数问题。Adams和Matlab都必须安装为64位如果有一个装了32位版本接口几乎必然失败。检查方法很简单在Matlab命令窗口输入computer输出是PCWIN64就没问题在Adams启动界面也能看到版本位数标识。2.3 验证接口是否配置成功环境配置完成后不要急着建模型先在Matlab里做一个快速检查% 在Matlab命令窗口执行 which adams_plant which adams_sys如果都能返回文件路径说明安装位置正常。接着在Matlab命令窗口输入adams_sys这个命令会尝试启动Adams的接口模块界面。如果弹出窗口说明接口完整可用如果报错需要根据错误信息回到环境变量排查。这一步花两分钟做完能避免你后面浪费半天时间。提示如果adams_sys能返回但没有窗口弹出检查一下Matlab当前路径是否加入了Adams的接口文件目录。在Matlab里执行addpath(genpath(C:\MSC.Software\Adams\2021\controls\matlab))然后保存路径。3. 从零建模实测用弹簧-质量-阻尼系统跑通第一个联合仿真很多人一开始就想仿真一个机器人或者整车模型这容易掉进复杂度的泥潭。我的建议是先搭建一个最简单的弹簧-质量-阻尼系统目的是把联合仿真的数据通道跑通确认流程没问题之后再替换成你真正关心的复杂模型。3.1 在Adams里搭建机械本体打开Adams View按以下步骤操作。如果你是第一次使用Adams可能对这些界面不太熟悉照着做就行。第一步设置工作环境在菜单栏选择Settings - Units把长度单位设为MM毫米质量单位设为Kg力的单位设为Newton时间单位设为Second角度单位保持Degree。这个设置后续会和Matlab里的参数单位对应上。第二步创建模型部件用一个质量块加一个弹簧阻尼器是最经典的入门组合在Main Toolbox中选择Rigid Body刚体创建一个长方体Part作为质量块例如尺寸为100mm x 100mm x 50mm给这个Part赋予质量属性右键选择Part - Modify将质量设为1.0kg创建一个Ground零件作为固定基座软件默认存在改名即可在Ground和质量块之间创建一个Translational Joint移动副约束质量块只能在垂直方向运动第三步施加弹簧阻尼力在Main Toolbox中选择Spring-Damper工具连接Ground上的一个标记点Marker点和质量块上的一个标记点。设置弹簧刚度K1000 N/m阻尼系数C10 N·s/m。到这里一个简单的单自由度振动系统就建好了。你可以先不联合仿真直接在Adams里给质量块一个初始位移跑一下Solver看它的自由振动响应确认模型本身没问题再进入下一步。3.2 定义状态变量联合仿真的数据交换接口Adams和Simulink之间的数据交换靠的是状态变量State Variable。状态变量就是你在Adams里指定的一组变量在联合仿真时对Simulink可见。这个环节是最容易搞混的地方很多新手不知道“我要把哪些量传给Matlab把哪些量从Matlab接进来”。我用这个简单的例子说明白。这个系统需要交换的数据只有两个从Adams传给Simulink的状态量质量块的位移x符号定义为q实际值取质量块Marker点的位移分量DM(MARKER_1, MARKER_2)这类测量函数从Simulink传给Adams的输入量施加在质量块上的外部控制力F_control创建输出状态变量的步骤在菜单栏选择Build - System Elements - State Variable - New命名变量为x类型设为State Variable在Function表达式里输入位移测量函数如DM(MARKER_1, MARKER_2)两个Marker分别位于Ground和Mass上同理创建状态变量v函数表达式输入速度测量函数如VY(MARKER_1, MARKER_2, MARKER_2, GROUND)创建输入状态变量的步骤新建一个State Variable命名为F类型设为Force函数表达式先设为0因为初始时刻外部力还没接入在质量块上施加一个力力的大小直接用变量F表示3.3 导出Adams Plant模型模型搭建完成后通过Adams Controls插件导出联合仿真模块在菜单栏选择Plugins - Adams Controls - Export在弹窗中指定文件名前缀比如srping_massFile Prefix填spring_massMajor Mode选择Nonlinear非线性模型大多数机械系统都是非线性Model Name选择你创建的模型名Initial Static Analysis选择No如果系统无静力平衡问题Output State Variable选择前面创建的x和vInput State Variable选择前面创建的FSolver Choice选择Adams/Solver C新版本推荐或Fortran兼容性好一些Adams/Solver Type选择Library C或Library Fortran点击OK导出导出完成后会在当前工作目录生成几个关键文件文件后缀含义.m文件在Matlab中运行它来初始化参数.adm文件Adams模型文件包含完整模型描述.cmd文件Adams命令文件可在Adams中重新加载模型.acf文件Adams求解控制文件.adm文件多提一句这个文件很重要它是你联合仿真时的机械本体3.4 在Simulink中搭建联合仿真模型导出完成后启动Matlab将工作目录切换到刚才导出的目录。按以下流程操作第一步运行初始化文件srping_mass这个.m文件会在工作空间生成Adams模型所需的参数变量。执行完毕后命令窗口会显示一些变量信息不用太在意内容确认没有报错即可。第二步生成Adams接口模块adams_sys此时Simulink会打开一个名为adams_sys的模型窗口里面包含ADAMS Plant模块这是Adams机械模型的S-Function封装ADAMS Plant Demo子模块里面给出了标准连接示例包括状态量输出端口、控制量输入端口、以及MSC Software提供的一个预定义的观察窗口模块第三步搭建你的控制回路新建一个Simulink模型把ADAMS Plant模块拖进去。这个模块的默认接口是上面是状态变量输出向量x和v下方是控制输入端口u也就是我们定义的力F。为了做一个最简单的闭环验证我建议先不接控制器直接给一个恒定力输入看看系统的开环响应是否正确。操作方式用一个Step模块连接到ADAMS Plant的输入端口设置Step Time0.1Final Value50表示在0.1秒时施加50N的阶跃力用一个Scope模块连接到ADAMS Plant的输出端口查看位移和速度变化第四步设置仿真参数并运行在Simulink界面的Simulation - Model Configuration Parameters中Solver选择ode15s这是一个刚性求解器适合机械系统与控制系统耦合的场景Stop Time先设为5秒Max Step Size设为一个合适的值比如0.01然后点击运行按钮如果信号曲线是一个典型的弹簧质量系统阶跃响应先振动后衰减稳定恭喜你你的第一个Adams-Matlab联合仿真模型已经跑通了。3.5 为什么坚持用最简单的系统做第一个模型我知道很多教程会直接用四连杆机构甚至整车模型来教学但我不建议这么做。你的目标不应该是“做出一个好看的动画”而应该是“先驾轻就熟地掌握这套联合仿真的数据交互模式”。弹簧-质量-阻尼系统足够简单不管哪一端出了问题都很容易定位原因——是Adams的模型建错了是状态变量定义错了还是Simulink的仿真参数的设置不对。4. 打通接口之后必做的几项检查数据对得上、方向不反、单位不乱模型第一次跑通挺有成就感的但我要泼一盆冷水——跑通了不代表仿真结果是可信的。联合仿真的结果验证比“能跑”重要得多下面这几项检查必须逐条过。4.1 数据通道验证在Simulink里同时接几个Display模块或Scope模块实时查看Adams传递给Simulink的位移和速度数据。一个很容易被忽视的点是Adams里角度单位是度还是弧度。如果你在Adams里建模时采用的是Degree那么导出的角度量到这里单位是度而Simulink控制算法里三角函数默认是按弧度计算的。这个单位不一致的问题很隐蔽一旦出现会造成控制量计算错误还很难发现。我的习惯是所有涉及角度的参数一律在Simulink里统一乘以pi/180或180/pi转成同一单位。4.2 输入输出方向验证对弹簧-质量-阻尼系统验证方法很直接在Simulink里给一个正向的阶跃力观察位移输出是否正向增加。如果位移反向变化说明Adams里的力作用方向和控制输入的正负号约定不一致需要回到Adams模型检查力的方向。这个方向问题看起来基础实际中却经常出问题因为Adams里建立力作用点时系统会根据你选择的Marker点自动确定方向。如果你的模型复杂力的方向有多个分量建议在Adams里提前施加一个简单常力跑一个纯Adams仿真看一下默认的运动方向再和联合仿真的结果对照。4.3 零状态响应验证很好的验证手段是把Simulink里的输入设为0然后从Adams侧给初始位移跑一次纯Adams仿真记录结果。再把相同的初始条件输入到联合仿真模型跑一次。两条位移曲线应该完全重合。如果不重合说明Adams导出的模型在联合仿真中并不等价于Adams独立仿真。这种情况通常出在导出时没有选择正确的状态变量Adams模型中存在不参与联合仿真的隐藏自由度求解器设置不一致比如步长差异过大导致数值精度不同4.4 数据保存与后处理联合仿真跑完后Adams View的后处理界面可能不会自动保存图形结果。你需要手动保存Adams模型文件同时用Matlab的save命令保存Simulink的仿真结果数据xout yout; % 假设yout是Scope或To Workspace模块输出的状态数据 save(spring_mass_result.mat, xout, tout);在联合仿真中Adams后处理界面看到的时间和状态数据与Simulink中的数据并非完全同步。如果要在论文或报告里引用数据我建议以Simulink的To Workspace模块保存的数据为准因为控制算法的数据流都在这里。5. 深入解析联合仿真的接口原理不只是“连起来”那么简单从操作层面跑到通之后就必须说清楚背后的原理了。因为你不理解接口产生数据的机制后面的参数调整和故障排查都会像无头苍蝇一样。5.1 Adams Controls联合仿真的工作方式Adams和Simulink都拥有自己的求解器。Adams内部的Solver负责求解多体动力学方程组——也就是位置、速度、加速度、约束反力等物理量Simulink内部的Solver负责求解控制系统的微分状态量——比如控制器的积分项、滤波器的中间状态等。在联合仿真中两个求解器并非“同时推进”到同一个时刻而是通过“通信步长”来协调步伐在t0时刻Adams把位移、速度等状态变量传给SimulinkSimulink在接收到的状态下控制算法计算一个控制量输出回传给AdamsAdams接到控制量以后把当前时刻的载荷代入运动微分方程自己内部求解若干个微小的积分步长推进到下一个通信时刻t0 T_comm重复这个过程这就是为什么联合仿真无法做到像单一工具内仿真那样严格控制全局误差——数据在每个通信步长里是“保持”的状态这个理想化的保持阶段会带来一定的误差。通信步长越小精度越高但计算量越大。5.2 离散模式与连续模式的区别到底是什么在Adams导出Plant时你会看到一个Type选项可以选择discrete离散或continuous连续。这个话题衍生出的坑非常多。对比项离散模式连续模式通信方式固定步长交换一次数据在求解过程中通过插值保持连续性适合场景控制频率明确、步长固定变量步长求解、精度要求较高Simulink中推荐求解器ode45等非刚性变步长求解器ode15s等通用刚性求解器坑点步长选小了计算昂贵选大了精度丢失偶尔会出现代数环警告需要处理新手推荐度一般更推荐以我的经验对于Spring-Mass-Damper这种简单系统两种模式都能跑通。但如果你的系统带有较强的刚性特征——比如存在高频振动模态或非线性接触——连续模式下用ode15s往往更稳定。5.3 通信方式选择PIPE、TCP/IP与MATLAB ModeAdams和Matlab的接口支持好几种通信方式最常用的三种PIPEWindows管道通过进程间的内存管道通信速度最快但只支持同一台机器上的两个进程。绝大多数本地联合仿真推荐用它。TCP/IP通过网络端口通信支持远程仿真。如果你有两台机器一台跑Adams高负载计算一台跑Matlab控制算法测试就用这种模式。MATLAB Mode作为Matlab的MEX接口模式直接在Matlab进程内调用Adams动态库省去进程间通信开销。这种模式对防火墙和网络安全要求最低最省事。在导出Plant时Communication Interval是一个关键参数。它决定两个求解器之间多久交换一次数据。我的建议是取Simulink里控制周期的1/10到1/5不要为了追求速度直接把它拉得很大。比如你的控制器运行周期是10ms通讯间隔建议设置在1ms到2ms左右。如果联合仿真运行太慢可以尝试调到2ms到5ms试算看结果变化是否可接受。6. 常见故障排查从现象到根因的完整定位思路联合仿真最大的麻烦在于报错信息非常不友好。很多时候你看到的只是一个红色的报错弹窗没有任何有效指引。下面这些是我在实践中反复遇到的几类情况直接给排查思路。6.1 初始化时提示找不到adams_sys或adams_plant排查链路在Matlab里运行which adams_plant确认能否找到在系统环境变量里查看ADAMS_CONTROLS_BIN_PATH是否指向正确的controls目录确认安装的是64位软件且版本匹配检查Matlab的当前路径手动addpath到Adams接口目录并保存路径这个排查流程检查完基本上九成问题都能解决。6.2 仿真刚开始几毫秒就报积分失败现象Simulink仿真启动即报Solver could not be started或Error using adams_plant。排查链路检查Adams模型是否存在约束冗余或机构自由度问题——如果模型本身在Adams里独立仿真就报错那就先修模型检查状态变量的测量函数语法是否正确检查弹簧阻尼器的阻尼系数和刚度是否存在数值过小/过大导致的刚性问题尝试把Simulink求解器切换到ode23t或ode15s减小初试步长如果还是报错把Adams导出的.m文件里的初始状态变量列一遍对照Adams模型确认无误6.3 仿真能跑但结果明显发散现象曲线开始正常过一会儿变成强烈的振荡数值疯狂增大。排查链路看通信间隔Communication Interval是不是太大——这是最常见的原因。想象一下你每20ms才给控制器更新一次状态信息但系统固有周期只有30ms这种“盲区”很容易造成控制震荡在Simulink里缩小Max Step Size强制求解器走小步长试算检查Adams侧是否存在初始穿透或初始过大的接触力逐步检查纯Adams模型是否发散如果纯Adams不发散那就是联合仿真通信步长导致的问题6.4 控制力看起来没有起效现象模型在跑Scope也有波形但整个系统的响应和纯Adams模型几乎一样控制量完全没体现在运动上。排查链路检查Adams导出Plant时是否勾选了正确的Input State Variable检查Simulink里控制模块的输出是否真的连接到了ADAMS Plant模块的输入端口在Adams里查看施加的力是否真正引用到了那个状态变量F——有时候你在Adams里建了一个力但指向了默认值没有联动到控制变量打个断点或临时在Simulink里加大控制器增益看响应是否变化。如果加大了还是没有变化肯定是连接问题6.5 联合仿真结果和纯Adams仿真结果对不上现象同样的初始条件和边界条件联合仿真的曲线和纯Adams独立跑的曲线有明显差异。排查链路对比两种仿真设定的求解容差Adams Solver的误差容限和Simulink的求解器误差容限要设置到相近的量级检查Adams独立仿真时是否加载了额外约束或初始条件联合仿真时丢失了这部分设置检查状态变量的初始值是否一致——这常常发生在转动副上初始角度的惯量虽小但会改变后续动态特性6.6 一个实用的参数调整建议联合仿真刚起步时不要追求大模型、长周期。先用5秒的仿真时间步长设细一点验证结果无误后再逐步扩展。如果发现仿真速度过慢优先调整的是Simulink的Max Step Size和Adams的Communication Interval而不是盲目更换求解器。7. 把联合仿真用到你自己的项目进阶路线和心得当Spring-Mass-Damper模型验证通过后你已经具备了做复杂联合仿真的最重要的能力——定位问题的能力。接下来你大概率想把自己实际的课题或项目模型搭进这套框架里我给你几条实际经验参考。7.1 从简单系统到复杂模型的三条注意事项复杂模型和简单模型在操作流程上没有根本区别但这三条是我踩着坑走出来的经验一是模型的简化。Adams模型不是越细致越好。你关心的主要是控制回路的行为那么机械部分凡是和这个行为无关的细节尽量简化。比如做机械臂轨迹跟踪关节的柔性如果和控制器的设计频率差得很远在初版联合仿真里可以先假设为刚体。把柔性留到后期模型验证阶段再引入。二是状态变量的规划。在Adams里规划好对外接口的命名规则和次序。我见过有人把位移、速度、加速度、力的命名全混在一起最后在Simulink里完全不知道哪个线对应什么。推荐在Adams导出的状态变量列表上自己建一个对照表。三是初始条件的一致性。Adams模型里的初始条件位置、速度和Simulink控制器的初始状态一定要匹配。比如你想仿真一个从静止状态启动的系统原来在Adams里默认有初始重力相关的静力平衡解但在Simulink里没有设置相应的初始控制量启动瞬间就会产生很大的超调。7.2 和优化算法结合做参数自动寻优联合仿真模型跑通之后很多人做的第一件正事是做参数优化——利用Matlab的优化工具箱定义一个目标函数比如跟踪误差积分让优化算法自动调整Adams里的物理参数或控制器参数。具体做法function cost joint_sim_cost(params) % 将优化参数写入Adams模型参数文件 param.K params(1); param.C params(2); % 运行Simulink联合仿真 sim(spring_mass_joint, StopTime, 10); % 计算目标函数比如误差平方积分 cost trapz(tout, err.^2); end % 用fmincon或ga优化 options optimoptions(ga, Display, iter); [x_opt, fval] ga(joint_sim_cost, 2, [], [], [], [], lb, ub, [], options);如果你用遗传算法这种群体搜索算法每评估一次就要跑一次联合仿真资源消耗会非常大。我的策略是在初选阶段把通讯间隔尽量拉大快速淘汰明显不好的参数区最后在精调阶段再恢复细步长仔细验证前几名候选参数。7.3 用神经网络等代理模型加速重复仿真有些场景下联合仿真一次要跑几十分钟甚至几小时根本没法做大规模参数扫描。一种做法是先用联合仿真生成一批“输入参数-输出响应”的样本数据然后用BP神经网络、高斯过程或响应面模型去拟合这个映射关系后续参数寻优在代理模型上进行——热搜词里看到的“bp神经网络拟合曲线”就是这么来的。具体思路用联合仿真生成足够的样本数据参数包括弹簧刚度、阻尼系数、控制增益等输出包括稳态误差、超调量、调节时间等性能指标把这些数据整理成训练集和测试集用Matlab的神经网络工具箱训练一个BP神经网络训练好之后用这个代理模型代替联合仿真做快速评估以我的经验神经网络代理模型在参数维度不高3-5个以内的情况下非常有效拟合精度可以做到95%以上。但维度高了之后需要的样本量会指数级增长这时候更建议改用稀疏网格或高斯过程回归。样本数量尽量覆盖参数的边界区域和交互作用区域否则代理模型在极端工况下会失真。7.4 和其他仿真工具联合使用Adams和Matlab这个组合搭建好后还可以把Carsim、Amesim、Simpack等专业软件串联进来组成更复杂的仿真平台。比如车载底盘控制的研究中Carsim提供整车动力学Simulink提供控制算法Adams可以专门做悬架和转向系统的精细建模。这种多重联合仿真的难点和风险都是指数级上升的不建议新手直接尝试。我自己尝试过几次多工具联合后得出的结论是接口之间每增加一个数据不一致的风险就增加一分。务实的做法是先把每个软件之间的接口映射关系画清楚明确谁在什么频率下向谁提供什么数据然后再动手搭建。通信步长的匹配问题在多工具联合里更加突出建议所有子系统的通信步长取最小控制频率的5到10倍。7.5 一点个人体会折腾联合仿真这几年最大的收获反而不是技术本身而是建立了一种系统思维的习惯——你开始意识到任何一个实际系统机械本体和控制算法都不是孤立存在的它们通过传感器、执行器、通信延迟这些看不见的接口耦合在一起。Adams和Matlab联合仿真这个工具本质上是帮你在设计阶段就把这种耦合关系量化出来让你能提前看见系统在真实工况下的表现。前面写到的故障排查和环境配置内容应该可以帮你避开我当年走过的弯路。如果你照着这篇文章把弹簧-质量-阻尼系统跑通了剩下的路就可以自己摸石头过河了——遇到问题的时候顺着“环境-模型-接口-步长-单位”这五个维度去排查绝大多数问题都能找到答案。
返回列表