四足机器人这几年在学术圈和工业界的关注度一直在上涨,不管是做足式 locomotion 研究、机器人竞赛,还是产品级的巡检、探测项目,四足平台都是绕不开的载体。而正运动学设计、逆运动学解算、步态设计这三件事,又是四足机器人从“能搭起来”到“能走起来”最关键的一环。用 Matlab 做这一整套方案,成本低、调试快、可视化直观,非常适合课程设计、毕业设计和早期样机验证。这篇文章把我自己做四足机器人模拟项目 X 时的完整思路、推导过程和踩坑记录整理出来,从运动学建模到步态生成,再到整机仿真验证,全部串起来讲,给你一份可以直接参考复现的路线图。
我用的是经典的四足机器人腿部构型——髋关节横滚、髋关节俯仰、膝关节俯仰,每腿三个自由度,全身共十二个自由度。这个构型在真实四足机器人里最普遍,像常见的 MIT Mini Cheetah、宇树系列等基本都是类似布局(我这里只用这个构型的通用几何关系,不涉及任何具体产品参数)。控制架构上,先通过正运动学把关节空间映射到操作空间,再通过逆运动学把足端轨迹反解回关节角度,最后用步态时序把四条腿的相位关系组织起来,生成完整的运动指令。
1. 项目整体思路与模块拆解
1.1 为什么从运动学入手
很多刚开始接触四足机器人的同学,上来就想直接调步态、刷步频,结果腿完全不听使唤,走两步就抡成麻花。这不是控制算法的问题,而是运动学关系没理清楚。运动学是整个 locomotion 系统的地基,它回答三个最基本的问题:关节转多少度,足端在空间里什么位置?足端要移动到某个位置,各关节该转多少度?四条腿按什么顺序摆动,机器人才能稳定前进?
这三个问题分别对应正运动学、逆运动学和步态规划。在我的实现里,正运动学负责建立腿部模型和坐标变换,逆运动学负责把期望的足端轨迹转换成关节角度序列,步态设计负责确定摆动腿和支撑腿的时序关系。三块内容串成一条完整的链路,配合 Matlab 的数值计算和可视化能力,可以在不搭建实体硬件的情况下,先把整套方法在仿真环境里验证清楚。
1.2 整体架构与仿真环境
我用的 Matlab 版本较新,仿真环境主要用脚本 + 基础函数完成,不依赖 Simulink。架构分为四层:
- 模型层:定义四足机器人机身尺寸、腿长、DH 参数,以及每腿三个关节的初始角度。
- 运动学层:正解函数
fk_leg()和逆解函数ik_leg(),输入输出都是向量,方便批量调用。 - 步态层:足端轨迹生成、步态相位调度、支撑态与摆动态切换。
- 可视化层:用
plot3绘制机身和四条腿的三维姿态,用drawnow实时刷新,观察运动效果。
这种分层的好处是各模块解耦,调试任何一层都不影响其他层。比如步态层想换一种轨迹规划方式,运动学层的函数完全不用改。这也是我后来反复修改代码时最受益的一点。
2. 正运动学设计:从关节角度到足端位置
2.1 腿部结构与坐标约定
先把单腿的几何模型讲清楚。我的每条腿由三个关节组成:髋关节横滚(记为 θ1)、髋关节俯仰(θ2)、膝关节俯仰(θ3)。从机身侧面看,大腿长度为 L1,小腿长度为 L2,髋关节横滚轴与机体纵轴垂直。坐标系的约定是参考系的 Z 轴从机体中心指向侧方(横滚轴方向),前向为 X,身高方向为 Y,这个安排和机器人学里常用的 body frame 有所不同,但物理意义对四足机器人更直接。
以右前腿为例,髋关节横滚轴位于坐标原点,横滚角 θ1 绕 X 轴旋转使整条腿有侧向展开的能力;髋俯仰角 θ2 绕某个轴(旋转后的 Z 轴)控制大腿前后摆动;膝俯仰角 θ3 控制小腿相对大腿的弯曲。这样建模的好处是,横滚自由度放在最根部,让腿部可以在不改变机身姿态的情况下左右调整支撑点,这在侧向扰动下的稳定性控制里非常有用。
2.2 用指数坐标与几何法推导变换矩阵(含 Matlab 实现)
正运动学的本质,是把一个旋转和平移的组合用齐次变换矩阵表达出来。对于这条三自由度链,我采用较为直接的方式:先对每个关节定义局部坐标系,再逐级写出相邻坐标系的变换关系。因为大腿和小腿都在一个平面内运动(横滚之后形成的平面),所以髋俯仰和膝俯仰只涉及二维平面内的旋转,复杂度和三关节全空间旋转相比低很多。用几何法推导具体的正解表达式如下:
设髋横滚角为 θ1,从机身坐标系出发做旋转变换,得到髋关节坐标系。接着在髋关节坐标系中,大腿绕 Z 轴旋转 θ2,再沿旋转后的 X 轴平移 L1,得到膝关节坐标系。最后绕 Z 轴旋转 θ3,平移 L2,得到足端坐标系。将这三个变换连乘,就得到足端在机身坐标系下的三维坐标。Matlab 里我用一个自定义函数封装这组变换:
function pos = fk_leg(theta, L1, L2) % theta: [theta1, theta2, theta3] t1 = theta(1); t2 = theta(2); t3 = theta(3); % 使用几何法推导,避免构造复杂旋转矩阵 % 横滚后腿部平面偏转 t1,大腿在平面内俯仰 t2 r = L1 * cos(t2) + L2 * cos(t2 + t3); % 足端在腿部平面的径向距离 h = L1 * sin(t2) + L2 * sin(t2 + t3); % 足端在腿部平面的高度 % 横滚角把平面投影到三维空间 pos = [r * cos(t1), h, -r * sin(t1)]; end这里把横滚角 t1 的作用直观化为“腿部平面绕 X 轴旋转”。如果横滚角为 0,足端只在 YZ 平面内运动;横滚角不为 0,足端会同时产生 X 和 Z 方向的分量。这个实现省去了多个旋转矩阵连乘的麻烦,代码可读性和运行效率都好很多。在实际测试中,我建议先用简单的单腿模型验证正解的几何正确性,再集成到整机模型里。
2.3 正解验证与可视化
正解做完之后,光看数值不够直观。我通常在 Matlab 里画三维线段:从髋关节到膝关节、从膝关节到足端,这样整个姿态一目了然。下面给出一个简单的可视化脚本,循环变化关节角度来观察足端轨迹:
theta = [0.2, -0.4, 0.8]; % 测试角度 pos = fk_leg(theta, 0.25, 0.25); % 大腿小腿均取 0.25m % 绘制腿部 plot3([0 pos(1)], [0 pos(2)], [0 pos(3)], 'k-o', 'LineWidth', 2); hold on; knee = [L1*cos(theta(2))*cos(theta(1)), L1*sin(theta(2)), -L1*cos(theta(2))*sin(theta(1))]; plot3([0 knee(1)], [0 knee(2)], [0 knee(3)], 'b-o', 'LineWidth', 2);可视化调试点在于坐标轴比例要保持一致,不然很容易产生视觉误导:X 轴和 Y 轴单位长度不一样,明明是直线的腿部看起来像折了。我通常在plot3后面加一句axis equal来避免这个坑。正解验证完毕后,就可以放心地用这个函数去倒推逆运动学了。
3. 逆运动学解算:从足端位置到关节角度
3.1 解析法推导过程
逆运动学是本项目里最值得细推的部分,也是出错率最高的地方。我采用解析法而不是数值法(比如雅可比迭代或牛顿法),原因有三点:一是速度极快,一个腿部周期要计算几千次逆解,效率至关重要;二是解析解的结果稳定可预测,不会出现迭代不收敛的情况;三是解析式暴露了数学结构,方便处理奇异位形和多解问题。
推导思路如下。给定足端目标点坐标 (x, y, z),先通过横滚角的几何关系反解 θ1:
tan(θ1) = -z / x
这里注意象限处理要用atan2(-z, x)而不是atan,否则容易丢掉符号信息。求出 θ1 后,旋转回到腿部平面内,得到平面内的 x-y 坐标(腿部平面内径向距离和高度),然后问题退化为经典的二连杆机械臂逆解。设腿部平面内目标点为 (r_d, h_d),其中 R 为径向距离,由余弦定理求膝关节角度:
cos(θ3) = (r_d² + h_d² - L1² - L2²) / (2 * L1 * L2)
然后求 θ3 = atan2(±sqrt(1 - cos²θ3), cosθ3),正负号对应小腿内翻和外翻两种构型,四足机器人一般取负号(膝式构型,小腿向后弯曲)。得到 θ3 后,再求大腿角 θ2:
θ2 = atan2(h_d, r_d) - atan2(L2 * sin(θ3), L1 + L2 * cos(θ3))
这个式子的意思是:目标点在大腿坐标系下的极角,减去大腿末端指向目标点的极角偏移,剩下的就是大腿应该转到的角度。
3.2 解的存在性与多解处理
解析逆解虽是闭式形式,但存在三个天然约束,丢任何一个都会在实机或仿真里炸。
第一是工作空间约束。给定目标点必须位于正运动学的可达范围之内,数学上等价于 r_d² + h_d² 必须介于 (L1 - L2)² 和 (L1 + L2)² 之间。如果不满足,逆解会算出虚数(Matlab 里表现为复数或 NaN),这时候仿真画面会飞出奇怪的点。我在代码里显式检查这个条件,并返回一个错误标识,而不是继续计算。
第二是关节角度限位约束。即使目标点在可达范围内,解出来的 θ2、θ3 也可能超出关节机械限位。我的做法是在逆解函数里加一个饱和判断,超过限位的部分截断并打警告,同时调整目标点的横滚角来尽量规避。
第三是多解选择。由于膝关节有“正膝”和“反膝”两种构型,同一个足端位置会对应两组合理解。四足机器人四腿结构决定了反膝(膝关节向后凸)是自然姿态,因此代码里统一取 θ3 为负值的那个解。
function theta = ik_leg(pos, L1, L2) x = pos(1); y = pos(2); z = pos(3); % 反解横滚角 theta1 = atan2(-z, x); % 投影到腿部平面 r_plane = sqrt(x^2 + z^2); R = r_plane; % 旋转后等效径向距离 h = y; % 高度不变 % 二连杆逆解 D = (R^2 + h^2 - L1^2 - L2^2) / (2 * L1 * L2); D = max(min(D, 1), -1); % 防止数值越界 theta3 = -acos(D); % 反膝构型取负角 % 大腿角求解 phi = atan2(h, R); psi = atan2(L2 * sin(-theta3), L1 + L2 * cos(-theta3)); theta2 = phi - psi; theta = [theta1, theta2, theta3]; end数学生成后,我建议至少做一轮闭环验证:对每个随机关节角,用正解算出足端位置,再用逆解反算关节角,对比两者是否一致。我测试下来最大误差在 1e-12 量级,完全满足仿真精度要求。这个闭环验证脚本值得保留,后面改腿长参数或换构型时还能继续用。
3.3 逆解的数值鲁棒性
用 Matlab 实操时有两个细节要避坑。第一个是acos的输入越界问题,由于浮点误差,理论上在可达边界上的点,D 值可能算出 1.0000000001,超过acos的定义域,直接返回 NaN。我在代码里手动 clamp 到 [-1, 1],这个细节帮我挡掉了很多离奇 bug。
第二个细节是横滚角很大时,腿部平面几乎平行于水平面,此时 x 和 z 方向的分量都趋近于 0,θ1 的反正切结算变得病态。这种情况下我会切换到基于四元数的方向反解,或者在步态规划时限制横滚角不过大。常规四足行走步态里横滚角只在 ±0.3 rad 以内波动,基本碰不到这个问题,但如果后面加入复杂地形适应算法,就必须考虑这个病态情况。
4. 步态设计:让四条腿按节奏走起来
4.1 步态时序与支撑相摆动相切换逻辑
运动学解决的是单腿的轨迹问题,步态要解决的是四条腿之间“谁撑地、谁迈腿”的时序问题。四足机器人最常用的步态之一是 Trot 步态:对角腿两两一组,一组支撑、一组摆动,交替进行。Trot 的优点是对角支撑线近似经过机身中心,天然具备较好的静定性,而且实现简单、速度覆盖范围宽,适合多数场合。
我把步态周期一个 T 内划分为四个阶段:左前+右后支撑、右前+左后摆动;然后右前+左后支撑、左前+右后摆动。在一个周期里每条腿经历一次完整的支撑相(stance,占周期约 60%)和摆动相(swing,占周期约 40%),但四条腿的相位不是同步的,而是对角两两同步、相邻腿相差半个周期。这个相位关系用代码实现时就是一条腿的相位偏移量:
% 四腿相位偏移,顺序为 左前 LF、右前 RF、左后 LH、右后 RH phase_offset = [0, pi, pi, 0]; % rad,LF和RH同步,RF和LH同步,两组相差pi phase = mod(2*pi*t/T + phase_offset, 2*pi); swing_mask = phase < 2*pi*0.4; % 摆动相占40%这里的关键在于,phase计算必须用周期性调制函数,不能用简单的线性增长,否则长时间仿真后浮点误差会导致相位漂移。用mod或wrapTo2Pi都能规避这个隐患。
4.2 足端轨迹规划:摆线过渡与多项式修正
支撑相和摆动相的足端轨迹性质完全不同。支撑相时足端相对地面静止,但相对机身反向移动,产生推动力;摆动相时足端要抬起来从后往前运动,高度还要平滑地先升后降,避免砸地。
支撑相的轨迹简单,目标点从初始位置匀速移到身后,与机身速度相反即可。摆动相我用了修正摆线轨迹,这是足式机器人领域最经典的方案,公式如下:
- x(t) = x_start + S * (t/T_sw - sin(2pit/T_sw) / (2*pi))
- z(t) = H * (1 - cos(2pit/T_sw)) / 2
其中 S 是步长,H 是抬腿高度。摆线的特点在于,x 方向的加速度在起点和终点处都为零,因此足端接触地面和离开地面的瞬间没有水平向冲击;z 方向用余弦修正,起落时速度也为零,落地冲击大幅下降。相比简单的高斯轨迹或正弦轨迹,摆线的效率和平顺性都更优。
实际代码里我把轨迹离散成一圈 50 个点,每个控制周期(假设 5ms)按时间插值取出目标位置,送进逆解函数:
% 摆动相轨迹生成 t_sw_ratio = linspace(0, 1, 50); swing_x = step_length * (t_sw_ratio - sin(2*pi*t_sw_ratio) / (2*pi)); swing_z = swing_height * (1 - cos(2*pi*t_sw_ratio)) / 2; % 逆解得到关节角度序列 for k = 1:length(t_sw_ratio) pos_cmd = [x_start + swing_x(k), init_height + swing_z(k), lateral_offset]; joint_pos(k, :) = ik_leg(pos_cmd, L1, L2); end4.3 步态参数调节技巧
步的四个核心参数是步长 S、抬腿高度 H、步态周期 T、机身高度 H_body。它们之间有明显的耦合关系:步长太大而步频太低,等效速度过高,支撑相容易打滑;抬腿高度太高而周期太短,摆动相中段可能碰到机体其他部件;机身高度太低,膝关节容易过伸展。
我给一组调试起点,适合 L1 = L2 = 0.25 m、体重约 15 kg 的模拟样机:步长 0.12 m、抬腿高度 0.08 m、周期 0.5 s、机身高度 0.45 m。这组参数跑出来的姿态自然、速度适中(约 0.24 m/s),可以在这个基准上按比例缩放。我的一个经验是,调节参数时一次只动一个变量,记录下每次调整的姿态视频和关节力矩变化曲线,比对后选择最优参数。
4.4 三角步态与爬行步态的扩展思考
Trot 步态之外,静态爬行步态(walk 步态)也值得关注,尤其是在复杂地形和不平整路面。Walk 步态的特点是任意时刻至少有三条腿支撑,稳定性大幅提高,但速度相对较慢。实现方式与 Trot 几乎一样,只需把相位偏移改成各腿依次相差 90 度(四步相位)。支撑相与摆动相的轨迹生成函数可以完全复用。这种模块化设计的好处现在就体现出来了:改一个相位表,就成了另一种完全不同的步态。
我实际测试过从 Trot 切到 Walk 的效果,只需在主循环里切换相位偏移数组,同时把周期调长、步长调短,不需要改运动学函数和轨迹函数。这块的扩展成本很低,强烈建议读者在基本步态跑通后尝试一下。
5. 仿真验证与常见问题排查
5.1 仿真验证与参数闭环
整机仿真做完之后,最重要的一步是验证所有模块协同工作的正确性。我把仿真分成三个递进层次。第一层是单腿轨迹回放,把期望足端轨迹和实际正解算出的足端轨迹画在一张图上,观察跟随误差,这一步能快速定位逆解或轨迹规划的 bug。第二层是整机姿态回放,四条腿同时按步态运动,检查机身是否自然起伏、腿部是否交叉碰撞。第三层是速度闭环验证,把机身理论位移速度与步态参数计算值对比,判断是否存在滑步现象。
这里我建议给每条腿标上不同的颜色,特别是两条后腿,因为后腿和前腿的朝向不同,正解函数里的横滚方向可能相反,容易画出来不对称。我的做法是给后腿的横滚角加一个 π 的偏移,让四条腿姿态统一朝向前方。
5.2 常见问题速查表
| 症状 | 可能原因 | 解决办法 |
|---|---|---|
| 逆解出现 NaN 或虚数 | 目标点超出工作空间 | 在 ik_leg 里显式检查可达性,限制足端轨迹范围 |
| 腿部姿态不对称,前后腿方向不一致 | 后腿与参考坐标系方向不一致 | 按腿的位置翻转横滚角方向或坐标轴 |
| 足端轨迹抖动,呈锯齿状 | 摆动相和支撑相切换时速度不连续 | 改用修正摆线,并在切换点强制对齐速度 |
| 机身整体漂移严重,像在冰面上滑 | 步态相位关系错误,支撑腿数量和时间不对 | 检查 phase_offset 是否正确对角绑定 |
| 抬腿时膝关节反向弯曲,姿态诡异 | 逆解多解选择错误,取了正膝解 | 确定 θ3 符号规则,反膝构型统一取负值 |
| 仿真画面一卡一卡,帧率不稳定 | 没有固定运行频率,或 drawnow 占用过多资源 | 固定控制循环时间,改用精简绘制方式 |
| 足端位置与期望轨迹偏差较大 | 机身高度与腿长不匹配,或轨迹参数不合理 | 用正解验证腿部工作空间,调整机身高度或步长 |
其中第一个问题是最常见的,几乎每个做逆解的人都会遇到。我的建议不是避免出界,而是在步态轨迹生成时就保证目标点始终在可达空间内。具体做法是在规划完一条轨迹后,先遍历所有目标点,过滤掉不可达的点,并适当减小步长或调低机身高度。
5.3 调试顺序与个人心得
调试顺序上,我的经验是严格“从单腿到整机、从站立到行走”。不要一上来就整机跑 Trot 步态,那样出问题根本定位不到是哪条腿的哪个环节。先用单腿的正解画几何模型,确认 DH 参数和坐标系没错;再对单腿做逆解闭环验证,确认正逆解互为反函数;然后给单腿加摆动轨迹,观察平滑性和工作空间;最后才扩展到四条腿的整机步态。
踩过几次坑之后,我最大的体会是:仿真炸掉,几乎从来不因为某个独立模块的问题,而是模块之间的接口约束没对齐。比如轨迹目标在可达空间内,但逆解函数没有显式处理边界;比如支撑相的目标点用了机身绝对坐标而不是相对坐标;比如后腿的横滚方向忘了翻转。这些问题全部可以在“分模块验证 + 接口检查”的流程里拦住。
另外一个小技巧,控制主循环里用固定的时间步长,比如 0.005 秒,然后记录每一步的关节角度和足端轨迹,跑完之后用plot一次性绘制耗时曲线。这样做比实时可视化更利于精确分析,也不容易受电脑性能影响。我建议把实时显示和离线记录分离——实时显示用来表演和观察,离线记录用来定位细节问题。
按照这套流程,我最终在仿真环境里复现了四足机器人的稳定 Trot 步态行走,机身姿态平滑,足端轨迹圆润,验证周期和步长参数匹配良好。如果你也在搭四足机器人的运动学和步态系统,希望这篇整理能帮你少走一些弯路,把时间花在真正有趣的算法和硬件调试上。