资讯动态

轮腿机器人Simscape仿真建模:从URDF导入到LQR调参实战指南

发布时间:2026/10/14 14:20:51 来源:尧图企业网站定制
简介面向机器人研究者与自动化专业学生的轮腿机器人MATLAB仿真建模资源基于上海交通大学相关模型整理。压缩包共10个文件约479KB包含C语言控制算法源码Chassis_Task.c/h、MATLAB脚本含LQR线性二次调节器实现及仿真数据、香港大学轮腿平衡步兵机械与电控解决方案PDF以及readme说明文档覆盖从底层代码到高级控制策略的完整流程。已有204人学习下载。这份资料可作为轮腿机器人运动控制入门与进阶参考帮助理解建模思路、算法实现与工程实践方案。1. 这个轮腿仿真模型为什么值得花一周时间跑通它轮腿机器人仿真建模新手最容易掉进“从零开始搭运动学”的坑自己推公式、自己写积分、自己去画受力分析忙了一个月还在坐标变换里打转。标题里说的这份模型是某高校机器人实验室开源出来的轮腿仿真资源在 MATLAB 生态里已经相当完整URDF 描述、Simscape Multibody 模型、初始化脚本和基础控制器全部打包好了。它解决的诉求很直接——别重复造轮子。你把模型跑起来把参数读进去再把控制器换成自己的算法一周之内就能拿到轮腿机器人的姿态、关节角、轮速和接触力数据。适合刚接手轮腿项目的学生也适合暂时没有硬件、想先验证控制算法的工程师。下面按“模型原理→跑通→调参→避坑”的顺序讲清楚。2. 轮腿构型到 Simscape 建模运动学、接触与 URDF 导入2.1 轮腿机器人的构型与坐标约定轮腿机器人这个名字核心就是“轮子管平路腿管姿态和越障”。常见的开源构型是四条腿每条腿由髋关节、膝关节和一个末端轮组成轮子负责平地上快速移动腿负责把机身抬到合适高度、调整姿态、跨过障碍。相比纯四足机器人轮腿机器人多了一组非完整约束动力学上更接近“有轮子的倒立摆”和“多刚体支撑”的混合系统。开始建模前要把坐标系约定彻底想清楚否则后面每一步都在给前面的草率填坑。我一般会在纸上先画出三层坐标系世界坐标系固定在大地上重力沿 Z 轴负方向机身坐标系固定在机体质心定义俯仰、横滚、偏航每条腿的髋关节在机身坐标系上有一个固定偏移再通过关节旋转和杆长平移到达轮轴位置。Simscape 里这套关系是用 Rigid Transform 模块串联的每个 Solid 必须跟正确的 Frame 对齐差一个角度仿真出来的姿态就全歪了。拿到这份模型之后我会先核对三件事世界系原点是否在轮子接触面的高度、机身坐标系 Z 轴是否朝上、轮子旋转轴是否与地面平行。别看这些只是小问题真到了调 LQR 的时候一个反方向的坐标轴会让反馈符号反掉控制量直接推着机器人往地上栽。2.2 正逆运动学与轮地接触的作用轮腿建模的核心量是轮心位置。给定机身位姿和四个关节角通过正运动学求轮心在世界系下的坐标逆运动学则反过来给定期望机身高度和姿态反求关节角度。这部分先用 MATLAB 脚本验证是正确的做法不急着拖进 Simulink因为函数形式简单、调试成本低。以一条腿为例髋关节位置加上旋转矩阵和杆长向量就是轮心的位置% 单腿轮心位置计算示例髋关节位置 旋转后的杆长 % p_hip: 3x1 髋关节在世界系下的位置 % R_body: 3x3 机身相对世界系的旋转矩阵 % theta_hip, theta_knee: 关节角 % L1, L2: 大腿、小腿长度 T1 eye(4); T1(1:3,1:3) R_body; % 机身旋转变换 p_hip_world p_hip; % 按模型实际坐标约定取髋关节世界位置 p_wheel p_hip_world L1 * [cos(theta_hip) * cos(theta_knee); sin(theta_hip) * cos(theta_knee); sin(theta_knee)]; plot3(p_wheel(1), p_wheel(2), p_wheel(3), o); % 可视化轮心位置逻辑说明这段代码是把关节角换算成轮心位置用的是最直观的几何叠加法。L1、L2 和关节角都从资源包的初始化脚本里读不要自己拍脑袋。髋关节旋转角、膝关节俯仰角在多腿模型里不是同一个方向写脚本时必须按照模型的坐标约定去取正负号如果发现轮心高度算出来是负的说明旋转矩阵或者关节角零位取反了。轮地接触是轮腿仿真与机械臂仿真最大的差异点轮子必须产生法向支撑力和切向摩擦力否则整机会在第一秒就穿进地面。Simscape 里常用 Spatial Contact Force 模块法向力用弹簧阻尼模型近似切向力用库仑摩擦加一个静摩擦过渡带。这里有几个量是必调的法向刚度、法向阻尼、静摩擦系数、动摩擦系数。初始值我一般给法向刚度 1e5 N/m 量级、法向阻尼 1e3 N·s/m 量级然后根据仿真发散情况再往小调。接触这块不是越硬越好刚度过大会让求解器为了捕捉接触状态把步长压到极小仿真跑一年都跑不完 10 秒。2.3 为什么用 Simscape Multibody 而不是纯数学建模轮腿机器人的纯数学建模指的是自己在 MATLAB 里把牛顿-欧拉方程展开写出机身加速度、关节力矩、轮子加速度的耦合关系。这件事不是不能做但轮腿机器人这种多关节、多轮、带接触的系统手推方程会非常痛苦摩擦力的方向每时每刻都在变腿与地面接触的时候会产生瞬时的约束力和冲击这些都要靠接触模型去近似。自己搭动力学方程最常见的结果是某个交叉项少了一项仿真曲线单看挺合理一拿去比对真机数据就露馅。Simscape Multibody 的价值在于它帮你做了这件事你只需要把刚体、关节、接触和驱动配置好它会自动组装动力学方程把重力、科氏力、离心力、接触力全部算进去。对轮腿机器人这种拓扑很规范的系统用 Simscape 搭出来的仿真模型在物理完整性上更接近真机而且后续改腿长、改轮径、加障碍物都比改公式快得多。我自己的习惯是“脚本验证运动学Simscape 验证动力学”两条线同时跑数值对上了再继续做控制器。2.4 从 URDF 到 Simscapesmimport 的最小用法很多开源轮腿资源包同时提供 URDF 描述文件和 Simscape 模型。如果拿到的只有 URDF或者你想自己改构型最常用的导入方式是smimport。它会把 URDF 里 link 和 joint 的定义翻译成 Simscape 的 Solid 与 Joint 模块质量、惯量、关节轴方向都自动带过来addpath(/your/path/to/urdf); % 文件夹路径里不要有中文和空格 smimport(wheel_leg_robot.urdf); % 生成 slx 模型与初始化脚本逻辑说明smimport执行后工作目录会出现一个 slx 模型文件和一个对应的物理参数脚本脚本里是每个 Solid 的密度、质量和惯量矩阵。运行这个脚本参数写入基础工作区Simulink 模型里的模块再通过变量名引用它们。URDF 里如果没有写 inertial 节点Simscape 会按默认钢材性质填充质量和惯量这种情况必须逐个 Solid 核对否则重心位置完全不准。smimport适合纯刚体结构如果模型里有软体或柔性关节导入后还要手动补模块。3. 把开源模型跑起来环境准备、初始化脚本与第一条仿真曲线3.1 环境与依赖先把环境清一遍避免跑到一半报错。这个轮腿仿真资源是标准 MATLAB Simulink 项目依赖集中在 Simscape 体系建议按下面的表格逐项确认依赖项说明最低建议MATLAB基础环境R2020b 及以上Simulink模型运行环境随 MATLAB 版本Simscape物理建模基础库随 MATLAB 安装Simscape Multibody多体动力学模块库必须Simscape Multibody Contact Forces Library接触力模块必须Add-On 安装环境是否齐全可以在 MATLAB 命令行直接检查% 检查工具箱是否可用 ver(Simulink) ver(Simscape) ver(SimscapeMultibody)如果缺少 Simscape Multibody Contact Forces Library直接用 Add-On Explorer 搜索安装不装这个库模型里的接触力模块会报 Block not found。装完库重启一下 MATLAB不要偷懒。3.2 跑通初始化脚本把参数写进 Workspace拿到资源包第一步不是双击 slx而是把目录加进 MATLAB 路径、运行初始化脚本。这个顺序弄反了模型打开就是一片红色报错——Simulink 模型里的质量、惯量、控制器增益全部是变量名工作区里没有这些变量模块参数解析失败% 把解压后的模型根目录加入搜索路径用绝对路径最稳 rootDir D:/workspace/wheel_leg_robot; addpath(genpath(rootDir)); % 运行参数初始化脚本脚本名以资源包实际文件为准 init_params;逻辑说明addpath(genpath(...))会把根目录下所有子目录一次性加进搜索路径避免漏掉脚本和回调函数。init 脚本做的事一般有三件定义物理参数结构体机身质量、腿长、轮径、惯量矩阵、把期望速度和初始姿态写入工作区、调用 lqr 或 place 计算平衡控制增益矩阵并赋值给某个反馈增益变量。如果你下载的包里脚本叫 setup_xxx.m就运行那个不要强行照抄脚本名。运行完之后用whos看一眼工作区确认出现了 M_body、K_feedback 这类变量。如果没有任何新变量说明脚本没有成功执行优先看脚本路径是否包含中文字符、脚本里有没有引用不存在的文件。3.3 打开 Simulink 模型并启动仿真参数进工作区之后直接用open_system打开模型再用sim跑仿真。这里我一般用脚本启动而不是点绿色三角按钮因为sim可以把结果输出到变量里后续处理数据方便% 模型名以实际 slx 文件名为准 model wheel_leg_robot; open_system(model); % 启动仿真时长 10 秒结果存到 out out sim(model, StopTime, 10);逻辑说明sim的第一个参数是模型名第二个参数是仿真参数对。StopTime 给 10 秒是先看动态行为够不够不够再拉长如果模型发散得很厉害5 秒就够了没必要跑满 30 秒等它爆炸。模型内部如果已经配置了求解器和步长不要在sim里再传 MaxStep 去覆盖除非你已经确定问题就出在求解器设置上。模型名里不要带 .slx 后缀open_system和sim都只接受模型名。另外如果仿真跑得很慢先别急着加硬件配置。检查一下接触刚度是不是设得过高或者机械结构里有没有无意义的过约束轮腿模型关节多仿真一步要算的约束方程不少把最大步长放开到 0.01 通常能明显提速。3.4 从 Scope 里看第一条仿真曲线仿真跑完后第一件事是看机身俯仰角曲线。Scope 里如果有这个信号就直接看没有的话我习惯从 out 变量里取% 假设模型里把俯仰角信号导到了 out.pitch t out.pitch.Time; pitch out.pitch.Data; figure; plot(t, pitch, LineWidth, 1.5); grid on; xlabel(t (s)); ylabel(pitch (rad)); title(机身俯仰角曲线);逻辑说明out 是一个 Simulink.SimulationOutput 对象信号的名字和层级取决于模型里 To Workspace 模块的变量名pitch 只是示例别拿一个不存在的名字硬取。如果 out.pitch 不存在用out.who看看有哪些变量可用。正常的平衡曲线应该是在初始扰动后 2 到 3 秒内收敛到 0 附近如果曲线直接发散或出现高频震荡不要急着怀疑模型先回 3.2 检查初始化脚本跑没跑、反馈增益是不是全零。4. 调参才是仿真的一半平衡、速度与轮腿关键参数4.1 控制器分层先稳住姿态再谈速度轮腿机器人的控制器我一般按两层拆内环姿态环外环速度环。内环用关节电机力矩把机身俯仰角稳定在期望值附近外环根据速度偏差算出期望俯仰角再喂给内环。这是最稳的收敛顺序——先别想着跑得快先把姿态稳住。在 Simulink 模型里内环通常是一个 LQR 或 PID 控制器输入是俯仰角误差和角速度输出是作用于关节的力矩指令外环是一个轻量级的 PI 控制器。调试时先给外环一个很小的速度指令比如 0.1 m/s观察内环能不能压住姿态内环都稳不住再调外环只会两头乱。资源包的模型一般自带一套默认控制器参数默认参数只是“能跑”不是“好用”。打开控制器子系统先确认它的输入信号是角度误差还是角度本身、输出是力矩还是加速度这个看反了后面调参全是白调。4.2 LQR 权重 Q 和 R 怎么选资源包里的平衡控制器很多用的是 LQR。LQR 的核心是状态权重矩阵 Q 和控制权重 R。以轮腿平衡最简模型为例状态向量一般选为机身俯仰角、俯仰角速度、轮速、轮速积分反馈控制律就是 u -K * x。权重矩阵的物理含义是“你有多在乎某个状态偏差”% 状态含义: [俯仰角(rad), 俯仰角速度(rad/s), 轮速(m/s), 轮速积分(m)] Q diag([20, 1, 5, 0.5]); % 角度权重最大速度权重其次 R 0.05; % 控制力矩的权重 K lqr(A, B, Q, R); % A、B 来自线性化模型逻辑说明Q 里第一个元素是俯仰角权重给 20 是因为姿态偏差是平衡控制最核心的指标第二个是角速度权重给 1 就够了太大容易放大角速度噪声第三个是轮速权重给 5第四个是轮速积分权重给 0.5作用是消除稳态速度误差。R 越小控制器越敢输出大力矩机器人响应越快但也越容易激发高频震荡。这四个数的比例关系比绝对值重要——先固定 R 0.1只调 Q 的比例如果平衡曲线有低频摆动加大第一个元素如果高频抖动加大第三个元素或者减小第一个元素。每调一次就跑一次 5 秒仿真别一次调一堆参数然后说不清楚是哪一步起了作用。LQR 有个前提A、B 矩阵必须来自平衡点处线性化的模型。如果资源包脚本里已经给了线性化好的 A 和 B直接用没有的话用linmod或者 Simulink Control Design 里的线性化工具重新求别自己去手推一套。线性化模型里的机身惯量参数如果和 Simscape 里不一致LQR 算出来的 K 看起来合理放进去就是发散。4.3 轮腿参数对仿真行为的影响除了控制器增益模型里的物理参数也会显著影响仿真行为。这些参数在 init 脚本里都是一行行赋值改完重新运行 init 再仿真不需要动 Simulink。下面这个表是我常用的初值范围和调参方向参数典型初值范围调大后的趋势调小后的趋势腿长 L0.2 - 0.5 m机身升高重心抬高恢复力矩变大机身变矮稳定范围变小轮半径 R_w0.05 - 0.1 m最大速度变大接触冲击更柔速度变慢对地面起伏更敏感机身质量 M_body3 - 10 kg惯性变大控制响应变钝响应变快但容易过冲法向接触刚度 k_n1e4 - 1e6 N/m接触更硬画面更干净步长更小接触变软容易穿地腿长和轮径的改动会影响运动学改完之后先跑一下运动学验证脚本确认轮心高度是正的、关节角度在合理范围内。机身质量影响的是动力学它决定同样一个力矩能带来多大的角加速度质量设成真机的估计值就行没必要刻意调大调小。改完参数后记得重新运行 init 脚本否则 Simulink 里引用的还是旧变量值这一点是最容易被忽略的。5. 避坑五个让新手崩溃的轮腿仿真翻车现场5.1 仿真直接发散接触参数或求解器设置现象仿真开始后一两秒曲线直接变 NaN 或者数值爆炸模型从地面上弹飞。原因最常见的是法向接触刚度设置过大Simscape 求解器步长压不住接触瞬间的数值冲击其次是求解器选了非刚性求解器比如默认的 ode45接触这种强非线性问题需要刚性求解器。解决先把接触刚度往小调一个数量级比如从 1e6 调到 1e5再用 set_param 切到 ode15sset_param(wheel_leg_robot, Solver, ode15s); % 刚性求解器 set_param(wheel_leg_robot, MaxStep, 0.01); % 限制最大步长MaxStep 单位是秒0.01 通常够如果模型里轮速高、关节动作快可以再压到 0.005。注意这个操作会用脚本覆盖模型内的求解器配置跑完验证没问题后再把模型保存一次否则下次打开还是原来的求解器设置。5.2 地面穿透轮子陷进地面或者上下抖动现象轮子在地面以下 1 到 2 厘米处悬浮或者上下抖个不停。原因Spatial Contact Force 的法向阻尼太小穿透深度设置不对。弹簧阻尼模型里法向力等于刚度乘穿透深度加阻尼乘穿透速度如果阻尼项压不住回弹轮子就会反复陷进去、弹出来。解决把法向阻尼提高到刚度的一半量级并在接触参数里把穿透极限设到和刚度匹配的值。一般刚度 1e5 时阻尼取 5e3接触算法里给一个 1e-4 量级的穿透深度限位。还有一个配合手段把仿真最大步长再压小或者给接触模块单独配置更细的采样时间。这里有个经验方向宁可让轮子在地面上轻轻浮动 1 毫米也不要为了“画面好看”把刚度拉到 1e7后者会让你整个仿真慢到没法调参。5.3 关节初始角度和机身位形不一致现象模型打开时四条腿姿态不对称机身歪向某一侧仿真一开始就倒了。原因URDF 导入的初始关节角度与初始化脚本里定义的零点不一致。最常见是初始化脚本里设定的关节角是从某个参考位形算出来的而模型里 Solid 的初始装配位形是 URDF 里的原始位置两者混用导致整机位形错乱。解决在初始化脚本里显式设置关节初始状态模型里的 Revolute Joint 模块初始角度不要用硬编码数字而是引用脚本变量比如 theta_hip_0。做法是先把四条腿的初始关节角全部设为 0跑 0 秒仿真看轮心位置再逐条腿修正零点。这个排查过程比较枯燥但值得做透因为后面所有轨迹规划都要依赖这套零位定义。5.4 控制器输出饱和与积分饱和现象姿态在初始扰动后回摆很大一圈才稳定甚至超调后来回震荡。原因关节力矩指令超出了执行器上限或者 PID 积分项在饱和期间持续累积等到误差反向时积分项还在往一个方向推。解决在力矩指令后面加一个 Saturation 模块上限按真机电机的峰值扭矩设置PID 控制器里给积分限幅或者直接用带 anti-windup 的 PID 结构。LQR 本身没有积分饱和问题但外环 PI 控制器必须考虑。我还见过有人把 Saturation 模块放到了反馈回路里而不是力矩指令后面导致控制律失真调了半天没有效果这种情况要检查模块位置和作用对象。看仿真曲线时如果力矩信号长时间贴在饱和值上说明控制器在“硬顶”要么是增益太大要么是期望速度给得太高。5.5 惯量、质心参数和模型不匹配现象仿真能跑但机身一直带一个固定角度的倾斜像站歪了。控制器增益没改换一台电脑跑结果还不一样。原因Solid 模块里的惯量矩阵或质心位置和 URDF 里的设定值不一致。smimport 导入 URDF 时如果参数脚本没有运行Solid 模块会按默认材质生成一组惯量重心位置完全对不上。解决打开 Solid 模块逐个核对质量、惯量、质心偏移。资源包脚本里一般有对应变量比如 M_body、COM_body把模块里的硬编码数值换成工作区变量名以后改参数只改脚本一处就够。这套排查本质上是在给模型“称体重”最隐蔽的翻车点之一模型能跑、曲线也漂亮但质心偏了 2 厘米最后和真机对不上白白浪费时间。建议把模型自带的默认参数和仿真输出导出来和真机做一次对比偏差在 10% 以内就基本可用了。6. 进阶把仿真数据导出、做成动画、再落回真机参数当模型稳定之后下一步可以做三件事把仿真数据整理成统一格式、用 MATLAB 动画验证运动轨迹、把关键参数落回真机模型。这三件事按顺序做正确率更高。% 提取仿真结果中的关节轨迹并保存 time out.tout; % 仿真时间 joint_angles out.joint_angles.Data; % 四条腿的关节角矩阵 save(wheel_leg_traj.mat, time, joint_angles); % 用 mat 文件驱动一个简单的 MATLAB 动画 for k 1:length(time) if mod(k, 5) 0 % 每 5 帧刷新一次 plot3(px(k, :), py(k, :), pz(k, :), o-, LineWidth, 2); view(3); grid on; title([t , num2str(time(k)), s]); drawnow; end end逻辑说明第一条代码把仿真时间与关节角存成 mat 文件这是后续做参数辨识、数据回放的标准格式。第二条代码直接基于轮心位置画散点图适合快速检查腿部轨迹是否平滑、有没有穿地或跳变。参数说明px、py、pz 需要在模型里通过 To Workspace 模块导出列数等于腿数行数对应时间戳。动画里每 5 帧刷新一次是为了避免 drawnow 性能太差影响调参节奏。真机映射时把 L1、L2、轮径、机身质量和惯量替换成你硬件的实测值即可。数据导出后我习惯再补一个简单核验把俯仰角的稳态均值算出来如果偏差超过 0.05 rad说明姿态环的稳态误差还没处理干净不适合直接拿去标定真机参数。这个流程走完你手上的资源就不再是一个“能跑的黑匣子”而是一套可以自己改、自己验、自己往真机上迁移的轮腿仿真环境。我自己最初的教训是太执着于“赶紧把控制器换成自己的”结果连初始化脚本都没跑对环境报错就卡了两周。后来养成的习惯是无论拿到什么轮腿仿真资源第一遍一定先用它自带的默认控制器完整跑通再逐层替换。先复现再改进这条路最稳。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑