先说结论:这次浙江省轮腿机器人赛项,我们队伍最终排在第四名,成绩是省二等奖。看到结果那一刻确实不甘心,因为前三名和我们的分差并不在硬件代差上,更多差在准备细节和现场容错。这篇文章不写情绪复盘,把我们从方案选型、机械设计、控制算法到现场调试踩过的坑完整写一遍,给后面打轮腿赛项的队伍省点弯路。
轮腿机器人这几年在工程类竞赛里出现频率越来越高。它的优势很明显:比双足好控制,比普通轮式平台更灵活,既能跑速度类任务,也能做姿态展示和越障动作,评分点覆盖范围很大。但“能跑”和“稳定跑完全程”是两码事。我们这次就是栽在稳定性和现场应变上。
下面直接进入正题,按技术方案、控制实现、现场策略和赛后复盘四个大块展开。
1. 核心能力速览
先给一张总表,方便你快速判断这套方案适不适合自己的比赛场景。
| 能力项 | 说明 |
|---|---|
| 项目类型 | 竞赛级轮腿平衡机器人 |
| 运动形式 | 双轮自平衡、差速转向、可扩展原地转向 |
| 控制核心 | 姿态内环 + 速度外环的串级 PID,可替换为 LQR 或 MPC |
| 核心传感器 | IMU(六轴/九轴)、轮侧编码器 |
| 可选扩展 | 摄像头、TOF 测距模块、蓝牙/WiFi 上位机 |
| 调试方式 | 串口上位机、无线遥控器、在线参数整定 |
| 竞赛成绩 | 浙江省级二等奖 / 第四名(按题干) |
| 适用场景 | 高校机器人竞赛、课程设计、控制算法验证平台 |
| 主要难点 | 机械重心控制、姿态解算噪声处理、现场抗扰动 |
从材料来看,这套方案的定位不是科研级平台,而是以“稳定完赛 + 拿分”为目标的工程实践项目。它能支撑三到五个月备赛周期内完成从零搭建到上场,适合本科阶段竞赛队伍。
2. 为什么选轮腿而不是轮式或双足
这是方案阶段最纠结的问题。我们对比过三种平台,最终选了轮腿,原因很直接。
普通轮式平台例如麦克纳姆轮小车,控制简单,移动速度快,调试时间短。但它在偏机械类的赛项里评分天花板低,因为缺少“动态平衡”这类技术看点。双足机器人视觉冲击力强,但稳定性要求高,一旦重心控制没做好,现场走两步就摔,调试周期很长。轮腿正好卡在中间——既有轮式的高效率移动,又有类似腿式机器人的姿态控制和越障潜力,在答辩展示和任务完成度上都有优势。
从比赛规则看,轮腿结构可以参加速度竞赛类任务,也能完成障碍跨越、坡道行走、原地旋转等技巧类动作。这意味着同一套机械平台能覆盖多个评分点,不用为不同任务搭好几台车。
不过轮腿对机械精度和装配质量的要求比普通轮式高很多。我们这次队伍里,机械设计和控制调试由两组人负责,前期没有充分对齐,导致改了一次重心位置后整套控制参数需要重新调。这个坑后面细说。
3. 系统架构与硬件方案
3.1 整车机械结构
轮腿机器人的核心结构就三块:车架、轮组、重心配重。
车架建议用碳纤维板或者轻量化铝合金板,强度够就行,不用太复杂。我们用的是 CNC 切出来的板件加铜柱堆叠方案,优点是改起来快,缺点是整机刚性一般,高速运行时会有轻微共振。如果你准备参赛,建议在第二轮迭代时把车架做成一体化设计,减少螺丝连接点。
轮组是另一个容易被低估的部分。竞赛地面可能有瓷砖、地毯、木板桥、减速带,轮子必须耐磨且有一定弹性。纯硬质轮在瓷砖上容易打滑,软质 PU 轮在高速急停时形变较大,会让平衡控制器感知到额外的角度扰动。我们最后用的是中等硬度 PU 轮,直径在 80mm 左右,比较均衡。
重心位置决定平衡控制的难易程度。理想情况是整车重心落在轮轴正上方附近,略高于轮轴。重心太低,车体响应迟钝;重心太高,平衡控制会变得很敏感,稍微有一点 IMU 噪声就会抖动。我们第一次装配时把电池竖着固定在车架后部,重心靠后,结果车一启动就向后倒,后来改成水平放置并尽量靠近轮轴才稳定下来。
3.2 主控与驱动方案
竞赛级轮腿机器人常见的控制方案是“STM32 主控 + 编码器电机 + 电机驱动模块 + IMU”。我们队伍没有用树莓派做底层控制,因为实时性不够,现场干扰环境下容易卡顿。STM32F4 系列或者更高主频的 F7/H7 系列足够跑控制环。
电机选择上,建议使用带霍尔编码器的直流减速电机,或者带 FOC 驱动的无刷电机。减速比不能太小,否则扭矩不够,车体稍微倾斜就拉不回来;也不能太大,否则极速受限。常见做法是 30:1 到 50:1 之间,需要根据你的车重和轮径实际计算。
这里给出一个经验公式思路:电机峰值扭矩乘以减速比,再除以轮子半径,得到轮上推力,至少要大于整车重力的三分之一到二分之一,才能在姿态偏移较大时拉回车体。我们这次选的是 35:1 减速比、带 512 线编码器的电机,在瓷砖地面上表现不错,但在地毯上极速和加速度都有下降。
IMU 安装位置很关键。尽量装到车体中间、靠近质心的位置,用减震泡沫双面胶固定,避免螺丝刚性连接引入高频振动噪声。IMU 的 X 轴对准前进方向,Z 轴竖直向上,装完之后要重新标定零偏,别在代码里加固定修正值。
3.3 供电与功耗
电池我们用的是 3S 锂聚合物电池,电压 11.1V,通过 DC-DC 模块给主控和电机驱动分别供电。这里有个容易忽略的问题:电机急加速时电流瞬间拉高,会把电池电压拉低,导致主控复位或者 IMU 读数波动。所以主控电源一定要和电机驱动电源隔离,或者在主控入口加一个大电容。
现场比赛通常会持续几个小时,建议准备至少两块电池,一块比赛用,一块备用。电压下降对电机输出影响很大,到后面电量低于 3.7V 每节的时候,同样的 PID 参数会出现明显性能下降。可以在代码里做电压补偿,或者直接采用电压归一化处理。
4. 控制算法设计
控制算法是轮腿机器人的核心。我们采用的是经典的串级 PID 结构:内环是角速度环,中环是角度环,外环是速度环。这个结构实现简单、调参路径清晰,适合竞赛场景。
4.1 姿态解算
控制的前提是拿到准确的当前角度。我们用的是六轴 IMU,陀螺仪提供角速度,加速度计提供重力方向参考。单独用陀螺仪积分会漂移,单独用加速度计会受振动干扰,所以必须做数据融合。
最简单可靠的方法是互补滤波:
// 互补滤波姿态解算,angle 单位为度 float complementary_filter(float gyro_rate, float acc_angle, float dt) { float alpha = 0.98f; // 陀螺仪权重,根据实际传感器噪声调整 fused_angle = alpha * (fused_angle + gyro_rate * dt) + (1.0f - alpha) * acc_angle; return fused_angle; }如果主控性能足够,也可以上 Mahony 或 Madgwick 四元数解算,角度精度更高,对旋转和高速运动的适应性更好。但竞赛场景下互补滤波够用,关键是滤波系数不能拍脑袋定,要通过静态和动态测试数据来确定。
4.2 串级 PID 控制
控制流程是:目标速度经过速度环输出目标角度,目标角度经过角度环输出目标角速度,角速度环再输出 PWM 占空比给电机。这个结构的物理意义很明确——角度环负责“站直”,角速度环负责“站得稳”,速度环负责“往前走”。
伪代码如下:
// 轮腿平衡控制主循环,运行频率建议 500Hz 以上 float speed_output = speed_pid(target_speed, current_speed, dt); float target_angle = speed_output; // 角度目标来自速度环 float angle_output = angle_pid(target_angle, current_angle, dt); float target_gyro = angle_output; float gyro_output = gyro_pid(target_gyro, current_gyro, dt); float pwm_output = gyro_output; // 根据左右轮编码器速度差做转向控制 float turn_output = turn_pid(target_turn_rate, current_turn_rate, dt); set_motor_left(pwm_output + turn_output); set_motor_right(pwm_output - turn_output);调参顺序非常关键,一定要从内往外调:
- 先调角速度环,只加 P,让车体能快速响应外部扰动。
- 再加角度环 P,让车体能够直立回正。
- 最后加速度环 P 和 I,让车体能前进和后退而不倒。
- 转向环放到最后,车体已经能稳定直立后再调。
我们这次在现场因为时间紧,跳过了速度环的完整整定,直接用了一组训练时的参数,结果在比赛场地上起步就出现低频振荡,导致后续动作不敢加速,直接影响了任务完成分。
4.3 转向控制
轮腿机器人的转向和普通轮式小车不太一样,因为转向时左右轮速差会引入额外的侧倾扰动,所以转向增益不能太大。我们用的是基于编码器速度差的闭环 PID,外加一个目标转向角速度的遥控通道。
转向调参注意一点:要在地面材质变化后重新验证。我们在光滑瓷砖上调好的转向参数,到了比赛用的粗纹理地胶上会变得迟钝,因为轮子与地面的摩擦特性变了。
5. 软件框架与调试工具
5.1 主控程序结构
我们的主控代码没有用 RTOS,直接前台循环 + 定时器中断。控制环放在 1ms 定时器中断里,保证固定频率;LED 显示、遥控器读取、串口打印放在主循环里。
结构大致如下:
// 定时器中断,1ms 执行一次 void TIM_IRQHandler(void) { imu_read(); // 读取 IMU 原始数据 encoder_read(); // 读取编码器数据 attitude_solve(); // 姿态解算 balance_control(); // 串级 PID 控制 motor_output(); // 输出 PWM }没有用 RTOS 是考虑到竞赛项目代码规模不大,中断优先级的确定性比任务调度更容易控制。但如果你的机器要同时跑视觉识别、路径规划、语音播报等任务,建议还是上 RTOS,或者加一块树莓派/ Jetson 做上层感知,把底层控制独立出来。
5.2 串口调试协议
竞赛现场最痛苦的事就是“车倒了不知道是参数问题还是机械问题”。所以一定要把调试数据实时传到上位机看波形。
最简单的方案是定义一套串口协议帧:
// 帧头 + 数据长度 + 数据 + 校验 void send_debug_frame(float target_angle, float current_angle, float target_speed, float current_speed) { uint8_t frame[32]; frame[0] = 0xAA; frame[1] = 0x55; frame[2] = 16; memcpy(&frame[3], &target_angle, 4); memcpy(&frame[7], ¤t_angle, 4); memcpy(&frame[11], &target_speed, 4); memcpy(&frame[15], ¤t_speed, 4); // 校验和发送,具体实现略 }上位机用串口助手或者简单的 Python PyQt 脚本都能做波形显示。现场调参时,如果能看到“目标角度”和“实际角度”的曲线重叠情况,判断 PID 参数是否合适会比盲调快很多。
6. 赛前调试与现场策略
6.1 赛前两周的调试重点
赛前两周不要大改机械结构,所有改动都应该是参数级别和策略级别的。我们这次最大的失误就是在赛前五天还换了轮子,导致所有标定和参数全部作废,现场花了大量时间重新调直立。
赛前两周应该做这些事:
- 建立至少三组完整可用的参数档位,分别对应低电量、高电量、不同地面材质。
- 每天做至少 20 次完整任务流程模拟,记录失败次数和失败点。
- 把遥控器、充电器、备用电机、备用轮子、螺丝刀、热熔胶全部整理成独立工具箱。
- 编写一页纸的“现场调试手册”,写清楚常见现象对应的参数调整方向。
6.2 现场时间规划
竞赛现场的可用调试时间往往比想象中少得多。我们这次上午到达场地,下午比赛,中间只有两个小时的适应时间。这两个小时里,我们花了一个半小时在调直立平衡,剩下的时间只够跑一遍完整流程,远不够做多组地面测试。
如果再来一次,我会把现场时间这样分配:
| 时间段 | 任务 |
|---|---|
| 前 30 分钟 | 检查机械连接、电池电压、传感器安装、遥控器对频 |
| 接下来 30 分钟 | 用训练参数跑一遍完整流程,先求“能完赛” |
| 再 30 分钟 | 根据地面材质微调参数,切换参数档位验证 |
| 最后 30 分钟 | 专门做稳定性和抗扰测试,包括急停、原地转向、坡道 |
“先求完赛,再求高分”是竞赛现场的铁律。我们在训练中已经验证过高分路线,但现场没有时间做完整参数适配,结果选择了激进路线最终失误,得分反而更低。
6.3 低电量策略
这个坑我们赛前没充分准备。电池从满电 4.2V 每节降到 3.8V 每节的时候,电机输出能力明显下降,同样的 PID 输出对应的实际力矩变小,车体会变得“软”。如果比赛时间靠后,一定要准备满电状态的电池,同时代码里做电压补偿。
最简单的电压补偿是缩放到标称电压:
float voltage_compensate(float pwm, float battery_voltage) { const float nominal_voltage = 11.1f; float scale = nominal_voltage / battery_voltage; return pwm * scale; }注意这个补偿不要过度,否则低电量时 PWM 会超限,反而让控制输出失真。更稳妥的方法是根据实际电压分档切换 PID 参数,而不是线性缩放。
7. 常见问题与排查方法
竞赛调试过程中我们遇到了一堆问题,这里整理成表格,后面参赛的队伍可以直接对着查。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 启动后车体高频抖动 | PID 增益过高、IMU 安装松动、编码器噪声 | 把 PID 增益降到最低,逐步加大观察 | 降低角度环 P,或增加 IMU 滤波强度 |
| 车体向前后快速跑飞 | 电机极性接反、角度符号反了、速度环积分饱和 | 用测试模式检查电机转向和传感器读数 | 反接电机线,或修正代码中的符号逻辑 |
| 启动后直接倒向一边 | 车体初始角度偏差过大、重心位置偏移 | 把车体放平后观察 IMU 角度读数 | 校准零点,重新调整电池配重位置 |
| 速度环响应过慢 | 速度环 P 太小,积分过慢 | 观察目标速度和实际速度曲线 | 先加 P 再加 I,避免积分饱和 |
| 转弯时车身侧倾严重 | 转向增益过大、轮距过窄 | 降低转向 PID,检查轮距是否过窄 | 限制最大转向角速度,或加宽轮距 |
| 地面材质变化后性能下降 | 摩擦系数变化导致轮子打滑 | 更换轮子材质或胎压 | 切换参数档位,保留多组地面参数 |
| 电量下降后车体变软 | 电压补偿策略缺失 | 观察电池电压和控制输出 | 增加电压补偿或分级切换 PID |
| 遥控器断联 | 干扰、天线位置不对 | 检查接收机天线方向 | 更换频率,或者改用有线通信调试 |
| 现场突发断电崩溃 | 线束松动、电池接触不良 | 检查XT60插头和焊点 | 所有连接点打热熔胶固定 |
| 姿态数据跳动 | IMU 安装在振动源附近 | 通过上位机查看姿态波形 | 重新安装减震,增大滤波器平滑度 |
8. 这次止步省二的失误复盘
这部分是我们最想和后来者分享的,因为技术方案没有大问题,但工程化准备和现场决策确实有差距。
8.1 失误一:机械改动拖累控制调试
赛前五天更换了轮子,表面上看只是轮径变小了一点,实际上导致整车重心高度和轮轴与地面的关系都变了,之前标定的 IMU 安装位置和 PID 参数全部失效。我们在现场浪费了大量时间重新做直立调试,留给任务流程验证的时间被压缩到几乎没有。
如果赛前要换轮子,至少要在比赛一周前完成,并且换完之后要完整跑一遍全套任务流程,而不是只测直立。
8.2 失误二:参数切换机制没有做完善
我们训练时在不同地面、不同电量下积累了很多参数,但没有做成快速切换的档位。现场都是靠电脑重刷参数,每次改参数至少要两分钟,而且改完还要重启确认。这导致现场“试一组参数—跑一次—再改一组”的迭代速度非常慢。
正确做法是在主控里预置至少三组参数,通过遥控器通道随时切换:
// 遥控器通道 6 切换参数档位 if (rc_channel6 > 1500) { use_parameter_set(2); // 高抓地力地面 } else if (rc_channel6 < 1000) { use_parameter_set(1); // 低抓地力地面 } else { use_parameter_set(0); // 默认 }这样现场适应不同地面只需要按一下遥控器,而不是打开电脑刷固件。
8.3 失误三:策略选择过于激进
我们训练时的最高分路线包含一个快速坡道冲刺加急停动作。这个动作在训练场地成功率大约 80%,我们觉得够高,就选了这条路线。但训练场地和比赛场地的地面摩擦系数、光照、观众围观造成的心理压力都不一样,实际成功率可能只有一半。
比赛时急停点没掐准,车体越过了坡道缓冲线,被判罚扣分,后续节奏全乱。更稳妥的策略是先跑一条 100% 能完成的路线保住基础分,再根据剩余时间决定要不要挑战加分动作。
8.4 失误四:数据记录和复盘不足
我们平时训练时很少完整记录每次运行的调试数据。出了问题只能靠肉眼观察车体姿态,很难判断是速度环的积分饱和还是角度环响应不够。如果赛前两周就开始给每次运行做日志记录,包括电机 PWM、目标角度、实际角度、电池电压,决赛前的调参会高效得多。
现场比赛最大的感受是:技术能力只是入场券,工程化能力决定你能走多远。
9. 从省二到省一:下一步技术升级路线
9.1 控制算法升级
串级 PID 优点是调参直观,缺点是参数多、适应能力有限。如果想冲击省一,建议升级到 LQR 或 MPC。
LQR 把系统状态统一建模,通过调整权重矩阵 Q 和 R 来平衡“站得直”和“耗能少”,调参维度比串级 PID 更少,控制效果更平滑。
MPC 则能显式处理约束,比如电机最大输出、车身最大倾角,适合做含障碍和坡道的复杂任务。
不过升级算法前一定要把传感器噪声和机械间隙处理好,否则再强的算法也会被物理系统的非线性吃掉。
9.2 感知系统扩展
如果赛项包含路径规划或目标识别,可以考虑加视觉模块。轮腿机器人的上层感知可以参考这样的架构:
# 上层感知示例,使用摄像头进行赛道识别 import cv2 def detect_track(frame): hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) lower = (0, 0, 0) upper = (180, 255, 80) mask = cv2.inRange(hsv, lower, upper) contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) return contours视觉模块的输出可以直接通过串口或 ROS 话题传给底层控制板,将视觉识别到的路径角度转换为目标转向角速度。
9.3 仿真环境建设
我们这次完全没有做仿真,大量时间花在实体调试上。如果你的赛项允许使用仿真验证算法,建议配置 Webots 或基于 MuJoCo 的仿真环境。仿真可以先验证控制逻辑是否正确,再迁移到实物上。
仿真环境搭建注意:
- 仿真环境的物理参数(轮子摩擦、电机扭矩、重心位置)必须和实物尽量接近,否则仿真调好的参数在实物上不适用。
- 仿真主要用于验证算法逻辑和安全性,最后的参数整定还是要靠实物测试。
- 可以先用仿真跑通一套 LQR 或 MPC,再迁移到实物微调,能节省大量迭代时间。
9.4 团队工程化管理
第四名的成绩说明我们的机械、电控、控制算法三块单独看都不差,但组合起来就暴露了协作问题。下一届队伍建议做三件事:
- 用 Git 管理代码和配置文件,机械图纸、参数文件、固件版本全部打标签。
- 每周做一次完整的联合调试,机械组、电控组、算法组必须同时在场,不允许各调各的。
- 建立“故障日志表”,每次出现跑飞、抖动、断电都要记录原因和解决方案,避免同一问题反复踩坑。
10. 总结与建议
如果你们准备组队打轮腿机器人赛项,我最想提醒的是:把目标定成“稳定完赛”,而不是“冲击高分”。稳定完赛基础上的高分才有意义,激进策略带来的高风险大概率会在现场反噬。
正式比赛前的最后一周,机械结构必须冻结,所有改动只允许在参数层面完成。一组完整的 PID 参数切档机制、一份一页纸的现场调试手册、一套备份电池和轮子,比任何花哨的算法都更值钱。
省二的成绩说明这条路走得通,但离省一只差“工程化”这一步。先从调好一组参数开始,再谈技术升级,下次赛场见。