简介:压缩包整合了轮腿机器人仿真建模的完整资源,包含上海交大与香港大学的相关方案,面向机器人工程师和研究人员,适用于MATLAB环境下轮腿机器人动力学建模、控制算法设计与仿真验证。包内共10个文件,约479KB,核心包括两个C代码文件及对应头文件,用于底盘任务与功能函数的控制实现;一个MATLAB脚本体现基于LQR的最优控制策略,可直接观察带数据的仿真流程;另有香港大学轮腿平衡步兵机械与电控解决方案的PDF文档,以及readme说明和IDE配置文件,便于快速上手。目前已吸引204人学习浏览,说明其对轮腿机器人方向有一定参考价值。资源将底层C语言实现与MATLAB高层仿真相结合,从基础算法代码到LQR控制策略再到前沿方案分析,形成了从理论到实践的完整工具链,可帮助读者理解轮腿平衡控制的关键环节并在此基础上开展二次开发。
1. 轮腿机器人仿真建模:MATLAB 仿真资源的正确打开方式
轮腿机器人仿真建模这几年成了机器人入学和入门的热门方向,很多同学拿到相关仿真资源包后,第一反应是解压、打开模型、点运行,结果要么模型根本不动,要么一启动就“起飞”。这不是 MATLAB 不行,而是大多数人把一个多体动力学问题当成普通 Simulink 控制问题去处理。轮腿机器人同时包含腿部支撑结构和轮式驱动,它的动力学不是简单的倒立摆,也不是四足机器人,而是两者的混合体。MATLAB 环境下仿真建模的好处是能直接看到力矩、角度、接触力的变化曲线,调试周期比实物快得多,但前提是你得先明白这类模型在什么条件下才能稳定跑起来。
这类仿真资源适合谁?如果你在做轮腿机器人毕业设计、备赛,或者想验证平衡控制算法但手里没有实物,那这方向值得投入。它能帮你解决三个问题:第一,确认控制算法的可行性;第二,快速调出能自平衡的控制器参数;第三,把仿真结果映射到后续硬件设计中。但前提是别把模型当成黑匣子,得知道模型里哪些参数能碰、哪些参数不能碰。这篇文章就用一个常见轮腿机器人模型把这条路走一遍。
2. 先从简化模型下手:轮腿机器人的动力学怎么提取
2.1 从大腿、小腿到轮子:轮腿结构的自由度拆分
轮腿机器人的结构常见的配置是一条大腿连接髋关节(躯干),大腿末端连接小腿,小腿末端直接装轮子。听起来像是倒立摆加轮子,但真正的动力学难点在于:大腿和小腿之间的膝关节角度会在运动过程中持续改变,这意味着质心位置一直在变,等效倒立摆的摆长不是常数。
拿到一个仿真资源包,无论里面是 URDF 模型还是 Simscape 多体模型,第一步都应该是把自由度拆清楚。常见拆法是:躯干一个俯仰自由度,髋关节一个旋转自由度,膝关节一个旋转自由度,轮子一个旋转自由度。对于平面运动来说,4 个自由度足够描述整个系统。每个关节的旋转正方向定义,建议统一用右手定则,并把髋关节和膝关节的零点定义在机器人竖直站立姿态下。
我一般会先把这些参数写进一个配置文件,而不是直接在 Simulink 模型里改。这样做的好处是后续做参数扫描时不用反复打开模型界面,改脚本就能批量跑仿真。参数表大致如下:
% 轮腿机器人关键参数配置(单位:kg, m, N*m/N) params.m_body = 12; % 躯干质量,典型值 8~15 kg params.m_thigh = 2.5; % 大腿质量,含关节电机 params.m_shank = 1.8; % 小腿质量,含轮毂电机 params.l_thigh = 0.35; % 大腿长度,髋关节到膝关节 params.l_shank = 0.30; % 小腿长度,膝关节到轮轴中心 params.r_wheel = 0.10; % 轮子半径 params.g = 9.81; % 重力加速度 params.length_ratio = params.l_thigh / params.l_shank;这段配置里,大腿和小腿的质量分布对模型影响很大。许多仿真资源包里给的质量是均匀分布的,但真实硬件中电机都集中在关节处,质心会更靠近关节。你拿到资源后,建议先看一眼模型文件里的惯性张量设置,如果它把质量集中在几何中心而你的目标硬件不是这样,仿真结果只能当作参考。
2.2 用拉格朗日法把模型写出来,然后做线性化
自由度拆完了,接下来就是把动力学方程提取出来。常见做法是用拉格朗日法推导,但实际做仿真时很少有人手动推全方程,更稳妥的做法是直接用 MATLAB 的 Symbolic Math Toolbox 推导,再把结果转成数值函数。
先定义广义坐标 q = [θ_body, θ_hip, θ_knee, θ_wheel],其中 θ_body 是躯干相对竖直方向的倾角。拉格朗日方程可以写成:M(q) q_ddot + C(q, q_dot) q_dot + G(q) = τ。这个方程直接放着没太大用,因为轮腿机器人控制通常只关心平衡点附近的线性化模型,所以要做两步处理:第一步,把平衡点设成躯干竖直、膝关节锁定、轮子角速度为零;第二步,在平衡点做泰勒展开,得到一个 4 阶的线性状态空间方程。
这一步常常被跳过,但如果你直接跳到 Simscape 非线性模型去调控制器,会非常被动,因为你不知道控制器的极点应该放在哪。用线性化模型先算出反馈增益,再放到非线性模型里验证,这才是高效的顺序。线性化后的模型状态可以取 4 个:躯干倾角、躯干倾角速度、轮子角度、轮子角速度。如果你用的是现成资源包,可以直接在 Simulink 里用linearize指令在指定的平衡点提取状态空间矩阵,不用手动求导。
% 在 Simulink 模型中提取平衡点处的线性模型 % 假设模型文件名为 wheel_leg_model.slx,控制输入端口为 tau_wheel opspec = operspec('wheel_leg_model'); opspec.States(1).x = 0; % 躯干倾角平衡点为 0 rad opspec.States(2).x = 0; % 躯干角速度平衡点为 0 opspec.States(3).x = 0; % 轮子角度 opspec.States(4).x = 0; % 轮子角速度 opt = findop('wheel_leg_model', opspec); [A, B, C, D] = linearize('wheel_leg_model', opt);这段代码的作用是让 Simulink 自动找到平衡点并线性化。注意operpoint求解过程是迭代式的,如果模型本身带有比较强的非线性接触力,这一步可能收敛不到 0,这时要先把接触力设置为禁用或直接调到理想的刚体模型上。多数资源包里给的全模型可以直接用作线性化,但如果你发现findop报错,优先检查模型是否在平衡姿态下静态稳定,而不是急着调求解器。
2.3 动力学参数验证:模型是否合理的三个快速检查
参数写完、线性模型也提取了,不等于模型就是可靠的。做仿真建模最怕的就是模型本身有问题,你调了三个月控制器,最后发现是脚轮摩擦参数写错了。三个快速检查每次必做:
第一个检查是静态重力矩。把机器人放在竖直平衡位置,计算髋关节和膝关节受到的静态力矩,和资源包模型输出对比,偏差应该在 5% 以内。第二个检查是轮子自由滚动。把机器人从竖直姿态轻微推倒,在不施加控制的情况下,观察质心投影点相对轮轴的移动轨迹是否合理。第三个检查是关节限位。大腿和小腿的活动范围有没有在关节模块里设置,如果没有设置,模型可能会在极端姿态下出现穿模,导致后续仿真结果全部作废。
做完这三个检查,简化模型的可信度就够了。下一步才是进入 Simscape 搭完整多体模型,但如果你拿到的资源包里已经有完整模型,那这三个检查相当于验收,确保你不会在错误的地基上盖房。
3. Simscape 搭建可运行的多体模型:从 URDF 到接触力
3.1 URDF 导入方式:smimport 的合理用法与限制
拿到仿真资源包,里面一般有两种模型:纯数学模块搭出来的简化模型和 Simscape Multibody 多体模型。前者跑得快,后者更接近真实。如果你的资源包只有 URDF 文件,需要自己转成 Simscape 模型,常见做法是用smimport函数。
smimport的流程其实很短:先把 URDF 读进来,它会自动生成一个 Simscape 模型文件和对应的刚体、关节模块。但它生成模型有几个固有缺陷:一是默认把每个 link 的惯性参数原样抄进来,而 URDF 里的惯性数据通常是不准的;二是生成的关节默认没有力矩传感器,你要手动加;三是模型里的坐标系方向和 URDF 里的方向在导入后可能有差异,尤其是如果你的 URDF 文件用的是左手坐标系,那转出来会出现整体镜像的情况。
% 导入 URDF 并生成 Simscape Multibody 模型 urdf_file = 'wheel_leg_robot.urdf'; addpath('urdf'); % smimport 会生成 wheel_leg_robot_import.slx smimport(urdf_file);执行完这段代码,你会在当前目录得到一个_import.slx文件。打开之后先不要急着保存,先检查三处:模型树的根坐标系是否在机器人质心投影点;每个转动副的 axes 方向是否指向真实旋转轴;轮子的转动副是否和地面接触平面平行。这三处只要错一处,后面仿真一定会出现诡异结果。smimport生成的多体模型默认不包含接触模块,也就是说轮子和地面之间没有力的作用,机器人会直接往下掉,所以必须在轮子下方手动添加地面和接触力。
3.2 关节驱动配置:位置、速度、力矩三种模式怎么选
关节驱动是轮腿机器人仿真里最容易让人困惑的地方。Simscape 里的关节执行器有三种模式:位置模式、速度模式、力矩模式。很多学习者一上来就用位置模式控制髋关节和膝关节,因为这样最不容易发散——确实,位置控制下机器人能保持某个姿态,但这不是轮腿机器人该有的表现。
轮腿机器人之所以叫轮腿,是因为它在运动时要靠力矩控制实现动态平衡,尤其是膝关节,它在支撑相和摆动相之间切换,必须用力矩模式才能模拟真实驱动器的行为。速度模式适合在调轮子速度闭环时用,但轮子本身也应该用力矩模式更合适,因为轮子打滑和摩擦的影响只有力矩模式才能真正体现出来。
我一般这样配置:髋关节和膝关节都用力矩输入,力矩值由上方控制器计算后给到执行器;轮子用速度输入做底层速度环,上层控制器输出的期望轮速,底层用比例控制器跟踪。这样做的原因是,轮子速度环的时间常数远远小于机身姿态环,分离设计之后,姿态控制器不用考虑轮子的惯性滞后,调参更容易收敛。
仿真资源包给出来的模型里,关节模块可能已经配置好,也可能只给了关节而没有驱动。你要做的就是确认每个关节的驱动模式,并在 MATLAB 脚本里集中定义。以下是配置参考:
% 在 Simscape 中设置关节执行器参数 % hip_joint: 力矩驱动 % knee_joint: 力矩驱动 % wheel_joint: 速度驱动(带 PI 速度闭环) set_param([model '/Hip_Joint'], 'Actuation', 'Torque'); set_param([model '/Knee_Joint'], 'Actuation', 'Torque'); set_param([model '/Wheel_Joint'], 'Actuation', 'Motion'); % 速度控制器参数:Kp = 8, Ki = 2 set_param([model '/Wheel_Speed_PI'], 'P', '8', 'I', '2');注意set_param只能修改已有配置,如果你的模型里没有对应的执行器模块,你需要打开 Simulink 模型手动添加。另外,力矩模式的电机如果不加限幅,仿真初期可能会出现超大力矩,导致数值发散。常见做法是在执行器前加一个饱和模块,把关节力矩限制在硬件能承受的范围内。
3.3 轮地接触:摩擦系数、接触刚度与阻尼的参数范围
轮地接触是整个轮腿机器人仿真里最影响横行的环节,没有之一。接触参数设置不合理,最典型的现象就是机器人像站在冰面上一样滑出去,或者反过来像被焊在地上一样动不了。Simscape Multibody 里处理接触一般用空间接触力模块,里面需要设置刚度、阻尼、静摩擦系数、动摩擦系数和穿透深度。
初始参数上,我一般推荐给一组经验起步值:接触刚度 1e5 N/m,阻尼 10 N*s/m,静摩擦系数 0.8,动摩擦系数 0.6,穿透深度 0.1 mm。这组参数适合轮径 10 厘米左右、质量 15 kg 级别的轮腿机器人。如果你的模型质量更大,或者轮子材料是硬质塑料而不是橡胶,动摩擦系数应当调低到 0.3 以下。
摩擦参数属于那种“改一个数仿真结果天翻地覆”的典型。接触刚度太小,轮子会陷进地面,机器人出现明显的垂直抖动;接触刚度太大,仿真步长必须缩小到微秒级,跑 10 秒仿真要几个小时。一个偷懒的做法是:先用小刚度跑通整个控制链路,再逐步加大刚度到合理值,这样调试期不会卡在仿真速度上。
% Simscape 空间接触力参数(以轮子与地面接触为例) contact.K = 1.0e5; % 接触刚度:1e4~1e6 之间按质量调整 contact.D = 10; % 阻尼:刚度太高时同步增大阻尼 contact.mu_s = 0.8; % 静摩擦系数,取值与轮面材料强相关 contact.mu_k = 0.6; % 动摩擦系数:略小于静摩擦 contact.penetration = 0.1e-3; % 最大穿透深度注意,接触刚度和阻尼并不是独立变化的。刚度调高一倍,阻尼最好也跟着调高,否则系统会出现高频振荡。振荡的典型表现是轮子接触力曲线呈锯齿状,甚至在仿真日志里出现 “Nonlinear iterations did not converge” 的警告。这时不要急着改求解器,先把接触阻尼调到刚度的 0.001~0.01 倍量级再试。
4. 自平衡控制器搭建:让轮腿原地稳住并跑起来
4.1 从 LQR 出发:用线性化模型计算反馈增益
轮腿机器人自平衡控制器里,最靠谱的起步方案依然是 LQR。理由是线性二次型调节器可以把姿态误差和轮子速度同时放进代价函数里,调 Q 和 R 矩阵就能直观表达你的控制目标:躯干保持竖直优先,还是速度跟踪优先。
如果你在第二章已经通过linearize拿到了 A、B 矩阵,那么控制器设计就是一行代码的事。状态向量建议取为 [θ_body, θ_body_dot, θ_wheel, θ_wheel_dot],控制输入是膝关节和髋关节的补偿力矩加上轮子力矩的合成值,但在简化模型里可以先只控制轮子力矩,让髋关节和膝关节保持锁定,看能不能实现自平衡。
% 根据线性化模型计算 LQR 反馈增益 % 状态: [倾角, 倾角速度, 轮子角度, 轮子角速度] Q = diag([100, 10, 1, 1]); % 倾角权重 100,角速度 10,轮速 1 R = 0.01; % 控制力矩权重 [K, S, e] = lqr(A, B, Q, R); disp('闭环极点:'); disp(e);这里 Q 矩阵的物理含义很直接:第一项 100 表示躯干倾角偏差 1 度对应的代价,远远大于轮子角度偏差 1 度的代价值,也就是说这个控制器优先保姿态。R 取 0.01 表示不限制控制力矩的大小,适合仿真阶段,等后面要部署到硬件时再把 R 调大,避免控制器输出超出电机峰值力矩。
算出 K 后,控制律就是 u = -K * x。在 Simulink 里搭一个状态观测反馈环,把四个状态信号从模型中引出来,乘以 K 矩阵得到力矩,再送回关节执行器。这一步听起来简单,但 80% 的问题是出在状态信号的正负号上:倾角传感器输出方向和状态向量定义相反时,反馈会变成正反馈,机器人会在 0.1 秒内朝地面倒下去。遇到这种情况,先看反馈曲线,再检查坐标系方向,不要一上来就怀疑 LQR 参数算错了。
4.2 加入速度和转向:从自平衡过渡到直行
能原地自平衡之后,下一个目标是让机器人往前直行而不倒。这需要在 LQR 的基础上加一个速度前馈项,或者更精确一点,把轮子角度状态改成轮子速度的积分误差。常见做法是在 LQR 外部再套一层速度环,速度环输出一个期望倾角给姿态环。
速度环的原理很朴素:想要往前加速,机器人必须先往前倾一点;想要减速停车,机器人必须往后仰一点。所以速度控制器的输出不是直接给轮子力矩,而是给一个期望躯干倾角偏移量。这个偏移量加到 LQR 的参考输入上,就实现了速度跟踪。
% 速度环控制器 % 输入: 期望速度 vs, 实际速度 v % 输出: 倾角参考偏移 theta_ref_offset Kp_v = 0.8; % 速度误差增益 Ki_v = 0.15; % 速度积分增益,消除稳态误差 theta_ref_offset = Kp_v * (vs - v) + Ki_v * integral(vs - v, 0, t); % 最终倾角参考 = theta_ref_offset + theta_balance_ref速度环整定的目标是让机器人从静止加速到 0.5 m/s 时不倒、不振荡。Kp_v 太小,机器人反应迟钝,速度跟踪误差大;Kp_v 太大,机器人倾角变化过猛,姿态环容易被带飞。先固定姿态环参数,再单独调速度环,每次只改一个数,记录速度阶跃响应曲线。
4.3 姿态状态估计:仿真里也要做传感器融合?
仿真的一个好处是理想的状态信号可以直接从模型里引出,不用滤波。如果你直接把模型里的角速度和角度拿出来用,控制器会非常稳。但这个稳是假象,因为真实系统里陀螺仪和加速度计都有噪声,而且角度和角速度的采样频率不同步。
所以,如果你的目标是仿真资源最终要落到实物上,就应当从一开始在仿真里加入传感器模型。常见做法是给姿态传感器的输出加高斯白噪声,再通过卡尔曼滤波器估计倾角。MATLAB 里有现成的航姿参考系统模块,可以直接拖进去用,参数只需要设置噪声方差和初始协方差。
在仿真阶段模拟传感器噪声还有另一个好处:它能暴露出控制器在高频抖动下的鲁棒性问题。有些控制器在理想信号下表现完美,一旦信号带噪声就开始颤抖,原因往往是 R 矩阵过小,或者反馈矩阵里角速度项增益过高。在仿真里提前暴露这个问题,可以省掉大量上硬件之后排错的时间。
4.4 关节力矩限幅与柔顺控制:为什么仿真也要限幅
很多人把仿真当成无限力矩的理想环境,觉得控制器输出多大都行。但轮腿机器人膝关节和髋关节的电机峰值力矩是有限的,如果你在仿真里忽略了限幅,调出来的控制器参数放到硬件上大概率会损坏电机或者机器人直接摔坏。
所以控制器输出之后、进入关节执行器之前,务必加上饱和模块。限幅值参考:髋关节峰值力矩 60 Nm 左右,膝关节 80 Nm,轮子力矩 20 N*m。这组数据和你的硬件能力不一定一致,但从这个数量级出发比较稳妥。注意限幅会改变控制器的有效增益,也就是说当限幅起作用时,LQR 的线性假设已经失效,仿真结果会出现非线性振荡。这不是模型出错,而是需要你调整期望性能,或者引入积分分离等抗饱和策略。
5. 轮腿机器人仿真建模常见问题排查:五条实测记录
5.1 模型一启动就“起飞”:接触参数不合理
现象:仿真运行一开始,机器人直接向上弹起,或者跑动过程中整个机身周期性跳离地面。
原因:轮子和地面之间的空间接触力模块穿透深度设置太小,或刚度参数过大,导致在接触发生的第一个仿真步长内产生了极大的弹性恢复力,把机器人弹向空中。
解决:先把接触刚度降到 2e4 N/m,穿透深度放大到 0.5 mm,确认机器人姿态不炸之后再逐步调回。同时查看接触力输出曲线,如果曲线出现尖锐脉冲,说明刚度和阻尼匹配有问题。我的经验是,刚度 1e5 时阻尼至少给到 8~12,否则振荡很难压住。
5.2 控制器输出方向反了导致秒倒
现象:算好了 LQR 反馈增益,但一运行机器人就往某个方向加速倒下,像被一股力量拽倒。
原因:状态向量的符号约定和传感器输出方向不一致。公式里倾角正方向定义为逆时针,但模型里倾角却按顺时针输出,反馈出的力矩正好推着机器人加速倒向地面。
解决:检查三处——关节旋转副的 axis 方向、传感器模块的测量输出方向、状态转换矩阵里的正负号。最快的验证办法是把轮子速度的反馈通道先置零,只保留倾角反馈,然后给一个正倾角初值,观察轮子是否往反方向滚动。方向对了再放开全部反馈通道。
5.3 仿真速度慢到无法忍受:求解器选择问题
现象:模型每秒钟只能仿真 0.2 秒实时时间,跑完 10 秒仿真要等待几十秒甚至数分钟。
原因:Simscape 多体模型默认用的是变步长刚性求解器,当接触力和关节限位同时作用时,求解器为了满足容差,自动把步长缩到很小。特别是有摩擦接触的模型,Stribeck 摩擦效应会让求解器频繁减小步长。
解决:在求解器设置里选择 odel3 或 odel5,然后手动限制最大步长。但更关键的是把接触刚度控制在合理范围,不要为了追求硬接触把刚度拉到 1e7,那会让求解器几乎卡死。也可以先用简化的轮地摩擦模型代替完整接触力,等控制器验证时用线性模型跑,只在最后验证阶段开启完整接触模型。
5.4 机器人静止时关节输出抖动不止
现象:机器人看似稳住了,但关节力矩曲线发出高频锯齿,峰值超过正常值的三到五倍。
原因:控制器采样频率和物理模型的求解步长不匹配。如果控制器以 1 kHz 频率计算力矩,而 Simscape 仿真步长只有 0.1 ms,控制器输出的数字脉冲会激励起结构的结构振动模态,尤其在膝关节刚度高的路径上。
解决:给控制器输出加一阶低通滤波,截止频率取 20 Hz 左右。如果你用的是变步长求解器,建议先固定仿真步长为 1 ms,与控制器频率一致,再观察力矩是否平滑。抖动仍然存在时,检查关节执行器前方的增益是否过高。
5.5 模型能跑但姿态控制效果和理论计算不一致
现象:按照线性模型算出来的极点位置明明是稳定的,放在非线性模型里却一直存在低频摆动,频率在 1~2 Hz。
原因:线性化模型忽略了轮子打滑、关节摩擦和腿部连杆质量的时变效应。动态平衡点附近这些因素并非小量,尤其膝关节锁定后,整个腿部等效为一个变长度摆,线性化误差较大。
解决:把简化模型和 Simscape 模型在相同输入条件下跑对比曲线,看差距从哪个时间点开始增大。多数情况下差距会一大就大在接触力突变时刻。可以把接触参数调得更理想一些,比如增加摩擦系数到 0.9,排除打滑干扰之后,再逐步调回真实摩擦,区分出是摩擦造成的偏差还是模型本身的动力学偏差。这步排查是让模型从“能跑”走向“可信”的关键步骤。
6. 从仿真到硬件映射:三个收尾技巧
6.1 模型置信度验证:用仿真记录器做一致性比对
仿真模型能不能指导硬件,取决于它的还原度。验证方法不用太复杂:在 Simulink 里搭一条从输入信号到输出响应的一致性对比通路,把简化模型、Simscape 模型和实测数据的响应曲线画在同一张图上。如果你的资源包里有实测数据,哪怕是别人跑出来的记录,也可以用它做参照。没有实测数据时,至少保证简化模型和多体模型在相同输入下的响应趋势一致,控制器才能迁移。
6.2 从 Simulink 模型生成可部署代码的核心门槛
把自平衡控制器部署到嵌入式硬件上,是很多人拿到仿真资源之后的最终目的。Simulink 的代码生成工具确实能省掉手写 C 语言的工作,但它对模型规范要求很高。最常被忽略的是变量数据类型:仿真里默认的 double 类型,在嵌入式环境里可能直接被替换成单精度浮点,控制器增益不变但数值精度下降,可能导致微小的稳态误差。生成代码之前,强制把所有控制器常量和状态量设定为定点和上下文清晰的类型,优先选择单精度而不是双精度,以匹配常见控制器的运算能力。
6.3 我的习惯:参数分层与记录
我自己的一个习惯是把所有控制器参数分层管理:一层是模型参数,一层是控制器参数,一层是部署参数。仿真调参时只动控制器参数,模型参数保持不变;每次试验前把参数快照写进 JSON 文件,跑完仿真自动读取快照和结果匹配。这样做的原因是轮腿机器人控制器参数之间耦合关系非常强,今天调好的倾角权重,很可能因为换了模型版本就得全部重调。留下参数快照,比什么记忆都可靠。这个方向做到最后,你会发现真正值钱的不是模型本身,而是你手里不断迭代的参数记录与调试思路。希望帮到你。
本文还有配套的精品资源,点击获取