ARTICLE DETAIL

资讯详情

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

从零搭建四足蜘蛛机器人:运动学与三角步态实战指南

从零搭建四足蜘蛛机器人:运动学与三角步态实战指南 1. 从零搭建四足蜘蛛机器人为什么运动学是绕不开的第一道坎很多人第一次看到四足蜘蛛机器人脑子里冒出来的第一个念头是“买十二个舵机拼个架子写个循环让它动起来”。我当初也是这么想的结果第一版机器人在桌上抽搐了整整一个下午腿像喝醉了一样乱蹬别说走路连站都站不稳。后来才明白四足机器人的核心难点从来不是硬件拼装而是运动学算法和步态实现这两件事。硬件只是骨架运动学才是让它“知道自己的脚在哪”的神经系统步态则是让它“知道什么时候抬哪只脚”的小脑。这篇内容面向的是已经玩过Arduino、能点亮LED、能驱动舵机但还没真正做过足式机器人的朋友。我会把四足蜘蛛机器人从坐标变换到步态调度的完整链路拆开讲包括每条腿的逆运动学推导、舵机角度的换算、三角步态的相位设计以及我在调试过程中踩过的那些坑。你不需要有很深的数学背景只要记得高中那点三角函数剩下的我用生活化的方式给你讲清楚。先说说四足蜘蛛机器人的基本构型。常见的方案是每条腿三个自由度一个负责腿部前后摆动我们叫它髋关节的yaw一个负责腿的上下抬落髋关节的pitch还有一个负责小腿的伸展膝关节的pitch。三个舵机串起来就形成了一个可以在三维空间里定位足端的机械臂。四条腿就是四个三自由度机械臂只不过它们共享同一个身体坐标系。这个“共享坐标系”的概念非常关键因为步态的本质就是身体在移动但足端要相对地面保持不动所以每条腿的足端坐标必须随着身体位姿的变化而实时更新。我用的硬件配置是Arduino Uno R3加一块PCA9685十六路舵机驱动板舵机是MG996R腿部结构用3D打印件。选PCA9685的原因很简单Arduino Uno本身的定时器资源有限用Servo.h库直接驱动十二个舵机抖动会非常明显而且一旦你开始做浮点运算PWM输出就会不稳定。PCA9685是I2C接口独立供电输出频率稳定在50Hz十二路舵机各占一个通道互不干扰。这个选型在后面讲步态调度的时候你会体会到它的好处。提示舵机供电一定要和Arduino分开。MG996R堵转电流能到2.5A十二个舵机同时动作瞬间电流轻松超过10A。我用的是一个5V 20A的开关电源单独给PCA9685供电Arduino只用USB供电共地即可。第一版我就是共用电源结果机器人一抬腿Arduino就复位查了半天以为是代码问题其实是电压被拉垮了。2. 四足机器人运动学核心从身体坐标到舵机角度的完整推导2.1 坐标系定义与单腿几何模型在动手写代码之前必须先把坐标系定清楚。我采用的是身体坐标系原点在机器人身体的几何中心X轴指向正前方Y轴指向左侧Z轴指向上方。每条腿的髋关节安装点在这个坐标系里有一个固定的偏移量比如右前腿的髋关节在(Lx, -Ly, 0)左前腿在(Lx, Ly, 0)以此类推。这个偏移量由你的机械结构决定拿卡尺量一下就行。单腿的几何模型是一个典型的RRR三个旋转关节串联结构。从髋关节开始第一段是髋部偏航连杆长度很短主要是让腿能左右摆动第二段是大腿连杆长度记为L1第三段是小腿连杆长度记为L2。足端相对于髋关节的位置可以分解成三个关节角度的函数。这里我用的是解析法求逆解因为四足机器人的腿只有三个自由度解析解存在且计算量小Arduino Uno完全扛得住。具体推导过程是这样的设足端在髋关节坐标系下的目标位置为(x, y, z)其中x是前后方向y是左右方向z是上下方向。第一步先求髋部偏航角θ0它只跟x和y有关θ0 atan2(y, x)这个角度的物理意义是腿在水平面上要转到哪个方向才能让足端落在目标点的正下方。第二步把问题降维到二维平面。设水平距离r sqrt(x² y²)那么足端在这个平面内的坐标就是(r, z)。接下来就是经典的两连杆逆运动学D (r² z² - L1² - L2²) / (2 * L1 * L2) θ2 atan2(-sqrt(1 - D²), D) // 膝关节角度 θ1 atan2(z, r) - atan2(L2 * sin(θ2), L1 L2 * cos(θ2)) // 髋部俯仰角这里有个细节要注意D必须落在[-1, 1]区间内否则说明目标点超出了腿的可达范围。我在代码里加了一个钳位处理如果D超界就把它拉回边界同时通过串口打印一个警告。这个警告在调试步态的时候非常有用因为步态参数设得不合理足端目标点很容易跑到可达空间外面去。2.2 舵机角度换算与机械零位标定算出来的θ0、θ1、θ2是数学角度但舵机需要的是PWM脉宽。中间差了一个机械零位标定。所谓机械零位就是舵机在安装时它的输出轴不一定正好对着你想要的几何方向。我的做法是先把所有舵机装好然后写一个简单的标定程序让每个舵机依次转到1500微秒中位观察腿的实际姿态记录下每条腿每个关节的偏差角。标定的时候有个技巧不要一次性标定所有腿而是一条腿一条腿来。先把机器人架起来让腿悬空然后给单条腿发送一组已知的角度用尺子量足端的实际位置反推偏差。我一开始图省事四条腿一起标结果调好一条腿另一条又歪了来回折腾了两个晚上。后来改成单腿标定每条腿记录三个偏差值存到数组里代码里统一补偿效率高了很多。换算公式大概是这样的pulse 1500 (angle - offset) * pulse_per_degreepulse_per_degree这个系数跟舵机型号有关MG996R大概是11.1微秒每度500到2500微秒对应180度。但不同批次的舵机这个系数会有差异所以我在代码里把它做成了可配置的宏方便微调。注意舵机的角度范围是有限的标准舵机只有180度。如果你的逆运动学算出来的角度超过了这个范围要么是目标点不合理要么是机械结构设计有问题。我在第一版结构上就遇到过这个问题大腿连杆太长导致膝关节角度经常超过170度舵机直接顶死。后来把连杆缩短了15%问题才解决。2.3 身体位姿与足端坐标的联动关系四足机器人走路的时候身体是在动的但足端要相对地面保持不动。这意味着足端在身体坐标系里的坐标是实时变化的。假设身体在全局坐标系里的位置是(X, Y, Z)姿态是(roll, pitch, yaw)那么足端在身体坐标系里的目标位置就是P_body R^T * (P_global - T)其中R是旋转矩阵T是平移向量。这个变换在Arduino上做完整矩阵运算有点吃力所以我用了一个简化方案只考虑平移和yaw旋转roll和pitch在小幅度步态下影响不大可以忽略。这样计算量就降到了几次乘加Uno跑起来毫无压力。这个简化方案在实际测试中效果很好机器人走直线的时候身体晃动很小。但如果你要做爬坡或者越障roll和pitch就不能忽略了那时候建议换ESP32运算能力强很多而且可以用WiFi做远程调试非常方便。3. 三角步态实现让四条腿协调起来的调度逻辑3.1 步态相位设计与占空比选择四足机器人的步态有很多种常见的有三角步态、对角步态、波浪步态。我选择三角步态作为入门实现原因是它稳定性好任意时刻至少有三条腿着地支撑三角形面积大机器人不容易翻。三角步态的核心思想是把四条腿分成两组一组是右前腿和左后腿另一组是左前腿和右后腿。两组交替抬起和落下就像人走路时左右脚交替一样。步态的相位设计用一个周期函数来描述。设步态周期为T每条腿的相位偏移为φ。对于三角步态右前腿和左后腿的相位是0左前腿和右后腿的相位是0.5。每条腿在一个周期内分为两个阶段支撑相和摆动相。支撑相占空比设为0.75摆动相占0.25。这意味着任意时刻只有一条腿在摆动另外三条腿在支撑稳定性非常好。占空比的选择是有讲究的。占空比太高摆动时间太短腿抬不起来容易拖地占空比太低支撑时间太短机器人会不稳。我试过0.5、0.6、0.75、0.8几个值最后发现0.75在MG996R的响应速度下表现最好。如果你的舵机速度更快可以适当降低占空比让机器人走得更快。3.2 足端轨迹规划抬腿与落腿的曲线设计摆动相的足端轨迹直接决定了机器人走路的流畅度。最简单的做法是让足端沿直线从起点移动到终点但这样抬腿和落腿的瞬间会有冲击机器人会“跺脚”。我采用的是椭圆轨迹在水平方向做线性插值在垂直方向做正弦抬升。具体公式是x x_start (x_end - x_start) * t z z_ground height * sin(π * t)其中t从0到1变化height是抬腿高度。这个轨迹的好处是抬腿和落腿的速度在两端自然减速冲击小。抬腿高度我设的是30毫米实测下来既能越过大部分小障碍又不会让机器人重心偏移太大。支撑相的轨迹就简单了足端相对地面不动但在身体坐标系里它要随着身体的移动而反向移动。假设身体前进速度为v那么支撑相的足端在身体坐标系里的x坐标就是x x_start - v * t这个反向移动的量必须和摆动相的位移量匹配否则机器人会“滑步”。我在代码里用一个全局变量记录每条腿的步长摆动相和支撑相共用这个值保证一致性。3.3 步态调度器的代码结构与实时性保障步态调度器的核心是一个状态机。我用millis()做时间基准每个周期计算一次当前相位然后根据相位决定每条腿处于支撑相还是摆动相再调用逆运动学算出舵机角度。整个流程在loop()里循环执行没有用任何阻塞式延时。代码结构大致是这样的void loop() { unsigned long now millis(); float phase fmod((now - start_time) / (float)period, 1.0); for (int leg 0; leg 4; leg) { float leg_phase fmod(phase phase_offset[leg], 1.0); if (leg_phase swing_ratio) { // 摆动相 computeSwingTrajectory(leg, leg_phase / swing_ratio); } else { // 支撑相 computeStanceTrajectory(leg, (leg_phase - swing_ratio) / (1 - swing_ratio)); } solveIK(leg); updateServo(leg); } }这里有个关键点solveIK和updateServo的计算量不能太大否则loop()的周期会不稳定步态就会抖动。我实测下来Uno在16MHz下十二个舵机的逆运动学加I2C通信单次循环大概需要3到4毫秒。步态周期设为800毫秒每个周期有200次循环完全够用。但如果你加了超声波避障或者MPU6050姿态解算循环时间会拉长这时候要么降低步态频率要么换ESP32。实操心得调试步态的时候先把机器人架起来让腿悬空用串口打印每条腿的足端坐标和舵机角度。观察一个完整周期内的数据变化确认轨迹平滑、没有跳变。然后再放到地上跑。我一开始直接放地上调机器人摔了好几次舵机都摔坏了一个。架起来调虽然麻烦但安全得多。4. 调试与优化那些文档里不会写的实战经验4.1 舵机抖动与电源干扰的排查舵机抖动是四足机器人最常见的毛病。表现是机器人站着不动的时候腿会轻微颤动或者走起来的时候某个关节突然抽一下。原因通常有三个电源功率不够、I2C通信受干扰、逆运动学算出了非法角度。电源问题最好排查用万用表量一下PCA9685的供电电压如果低于4.8V基本就是电源功率不够。我第一版用的是一个5V 3A的电源空载电压正常但十二个舵机同时动作时电压掉到4.2V舵机就开始抖。换成20A电源后电压稳定在5.1V抖动消失。I2C干扰比较隐蔽。PCA9685的I2C线如果和舵机电源线捆在一起舵机换向时产生的电磁干扰会导致I2C通信出错表现是某个舵机突然转到错误角度。我的解决办法是把I2C线单独走线远离电源线并且在SDA和SCL上各加一个4.7kΩ的上拉电阻。这个改动成本很低但效果立竿见影。非法角度的问题前面提过主要是逆运动学的D值超界。我在solveIK函数里加了一个检查如果D超界就把足端目标点往可达空间内拉同时通过串口打印警告。调试阶段我盯着串口看发现警告频繁出现说明步态参数设得太激进了把步长从80毫米降到60毫米后警告就很少了。4.2 步态参数整定步长、周期、抬腿高度的权衡步态参数没有标准答案得根据你的机械结构和舵机性能来调。我整理了一个参数整定的优先级先调抬腿高度再调步长最后调周期。抬腿高度决定了机器人能过多高的障碍但也影响稳定性。抬得越高重心偏移越大机器人越容易翻。我的经验值是腿长的15%到20%。我的机器人腿长200毫米抬腿高度设30毫米能过15毫米的障碍稳定性也够。步长决定了机器人的速度但步长太大会导致足端超出可达空间。我的经验值是腿长的30%到40%。腿长200毫米步长设60到80毫米。超过80毫米逆运动学就开始频繁报警了。周期决定了机器人的步频。周期太短舵机跟不上动作会变形周期太长机器人走起来一顿一顿的。MG996R的响应速度大概是0.17秒每60度一个摆动相要转大概90度需要0.25秒。所以周期不能低于1秒否则摆动相时间不够。我最后设的是1.2秒走起来比较从容。参数推荐值可调范围影响抬腿高度腿长的15%-20%10%-25%越高越容易翻但越障能力越强步长腿长的30%-40%20%-50%越大越快但可能超出可达空间步态周期1.0-1.5秒0.8-2.0秒越短越快但舵机可能跟不上支撑相占空比0.750.6-0.85越高越稳但速度越慢4.3 常见问题速查与避坑指南调试过程中我遇到了不少问题这里整理成一个速查表方便你遇到类似情况时快速定位。现象可能原因排查方法解决方案机器人站立时腿抖动电源功率不足万用表量PCA9685供电电压换更大功率电源舵机独立供电某个舵机突然乱转I2C通信受干扰检查I2C线是否靠近电源线I2C线单独走线加上拉电阻走路时腿拖地抬腿高度不够或占空比太高串口打印足端Z坐标增加抬腿高度降低占空比机器人走偏四条腿步长不一致分别测量每条腿的实际步长统一步长参数检查机械零位逆运动学频繁报警步长太大或抬腿太高串口打印D值减小步长降低抬腿高度舵机发热严重舵机长时间堵转用手摸舵机外壳检查机械结构是否卡涩减轻负载还有一个坑是舵机的机械零位会漂移。MG996R这种模拟舵机用久了齿轮会磨损零位会偏。我的机器人跑了大概两周后右前腿的膝关节零位偏了5度走路开始往右偏。解决办法是定期重新标定或者换数字舵机。数字舵机的零位稳定性好很多但价格也贵不少。提示如果你打算长期玩四足机器人建议直接上数字舵机比如DS3218或者LX-16A。模拟舵机的死区和零位漂移在四足这种需要精细控制的场景下真的很折磨人。我后来换了一套LX-16A串行总线舵机接线简单了很多角度反馈也准调试效率提升了一大截。5. 从能走到走好进阶优化方向与扩展思路5.1 加入IMU做姿态闭环开环步态在平地上走没问题但一遇到斜坡或者地面不平机器人就会歪。加入MPU6050做姿态反馈实时调整身体姿态能让机器人适应更复杂的地形。具体做法是用MPU6050读取roll和pitch然后通过PID控制器计算出身体需要补偿的高度和角度再把这个补偿量加到足端坐标上。这样机器人上坡时身体会自动前倾下坡时后仰走起来稳很多。这个改动需要把主控换成ESP32因为MPU6050的DMP解算和PID运算在Uno上跑不动。ESP32双核一个核跑步态调度一个核跑姿态解算互不干扰。而且ESP32自带WiFi可以做一个网页遥控器用手机就能控制机器人调试的时候非常方便。5.2 用Wokwi仿真平台快速验证算法如果你还没有搭好硬件或者想先验证运动学算法可以用Wokwi仿真平台。Wokwi支持Arduino Uno和ESP32可以拖拽舵机、传感器写代码直接仿真。我一开始就是在Wokwi上把逆运动学和步态调度跑通了确认逻辑没问题才动手焊板子的。这样省了很多硬件调试的时间也避免了因为代码bug烧舵机的风险。Wokwi上仿真舵机的时候注意它的舵机模型是理想模型没有死区和延迟所以仿真通过不代表硬件一定能跑。但用来验证运动学算法和步态相位逻辑是足够的。仿真里看到腿按照预期轨迹运动基本就成功了一半。5.3 扩展思路从三角步态到动态步态三角步态是静态步态稳定性好但速度慢。如果你想让机器人跑起来就得研究动态步态比如对角小跑trot。对角小跑只有两条腿着地需要靠身体的惯性来保持平衡控制难度大很多但速度能提升一倍以上。实现对角小跑需要更精确的足端轨迹规划和更快的控制频率建议在三角步态完全调通之后再尝试。另一个扩展方向是加入足端力反馈。在足端加一个压力传感器检测腿是否着地然后根据着地状态动态调整步态相位。这样机器人踩到障碍物时能自动调整不会硬踩过去导致翻车。这个方案在MIT Mini Cheetah上有应用虽然我们的Arduino版本做不到那么复杂但基本的力反馈逻辑是可以实现的。我个人在实际操作中的体会是四足机器人最难的不是写代码而是把机械、电子、算法这三件事协调好。机械结构决定了运动学的可达空间电子选型决定了控制频率的上限算法则是在这两个约束下找最优解。我踩过的坑大部分都是因为一开始没想清楚这三者的关系比如选了一个扭矩不够的舵机结果算法算得再好腿也抬不起来。所以如果你正准备做四足机器人建议先把机械结构和舵机选型确定下来再动手写运动学代码这样能少走很多弯路。
返回列表