“浙江轮腿第四,含泪止步省二”——看到这句话,我第一反应不是惋惜,而是想起了自己当年比赛结束的晚上,一个人蹲在酒店走廊里反复看录像,越看越气,越气越看。不是气裁判,不是气队友,是气自己:明明每个模块单独测试都好好的,怎么一上场就全变样了?
如果你也准备打轮腿机器人赛项,或者正在带团队备赛,那我要先给你一个明确的判断:轮腿机器人比赛,真正难的不是“让它动”,而是“让它稳定地用同一个性能跑完三次”。你能站住,能走,能绕障碍,都不算本事;连续三轮不失误、排名还能往上走,这才是区分省二和省一、国赛资格的分水岭。
这篇文章不写鸡汤,不写“我们明年再来”这种空话。我会从这次比赛暴露出的技术问题出发,把轮腿赛项从机械选型、运动学建模、控制调参、传感器调试到现场策略做一个完整复盘。把你可能遇到的坑,先替你踩一遍。
1. 先说说这次比赛:轮腿赛项到底比什么
很多人以为轮腿机器人大赛比的是“谁跑得快”,这是最大的误解。
从比赛规则和实际项目来看,轮腿赛项通常考核的是几个固定任务组合:直线行驶、S形绕桩、过减速带/坡道、定点停止、避障或者搬运物料。裁判打分的核心依据,是完成时间、压线次数、是否碰到障碍物、是否倒地。听起来不复杂,但它是把“机器人工程”的完整闭环压缩进一个赛题里:机械结构要够刚性,电机响应要够快,算法要同时处理好平衡、定位和路径跟踪,还要有一个不会被现场灯光干扰的传感器方案。
所以轮腿赛项的难点从来不是单项技术,而是系统集成稳定性。每个团队都能让轮腿机器人跑起来,但跑二十次不摔、不飘、不跑偏,就淘汰了一大批队伍。
再说“第四名止步省二”这个结果本身。在多数赛项中,奖项数量是按比例划分的,通常第一梯队拿省一,后面按排名落到省二。第四名这个位置很特殊——如果是前二进省一,那第四就是“差一点”;如果前三进,也是“差一点”。但不管哪种情况,第四名都说明一个问题:技术储备已经够了,损失的是细节分和稳定性分。
换句话说,止步省二不是运气差,是有一两个隐性问题在比赛时恰好被放大。下面我会从技术栈的角度,逐个拆解这些“恰好被放大”的点。
2. 轮腿机器人的技术地图:从结构选型开始
轮腿机器人在结构上并不是一个标准答案,常见的方案大致分为三类:
| 结构方案 | 典型特征 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|---|
| 两轮自平衡 | 两个驱动轮,车身靠主动平衡保持直立 | 结构简单,转向灵活,机动性强 | 容易振荡,对IMU和控制频率要求高,负载能力弱 | 室内平地竞速、小场地绕桩 |
| 四轮轮腿摆臂 | 四个轮子加摆臂/大腿结构 | 稳定性好,能翻越一定障碍,承载强 | 机构复杂,控制联动难度大,调参工作量翻倍 | 越障、台阶、复杂场地 |
| 三轮全向 | 三个全向轮,可平面内平移 | 控制模型简单,全向移动方便 | 对地面平整度极度敏感,过减速带容易打滑 | 物流搬运、轨迹精度高但地形平坦的项目 |
这次我们用的是两轮自平衡 + 上部结构集成路障检测与抬腿越障的复合方案,也就是在保留轮式移动效率的同时,利用摆腿机构实现过减速带。这个方案的优势是速度上限高,劣势也很明显:系统中同时存在平衡环和摆腿环,两者之间的耦合非常容易在高速运行时引发共振。
从工程设计角度,选型时最需要盯住的是三个参数:
- 重心高度与轮距之比。比值越大,越容易“栽头”,对平衡控制器的响应要求越高。
- 电机最大转速和扭矩的关系。比赛用的轮腿机器人通常要在 2~3 秒内完成急加速和急停,如果电机峰值扭矩不够,控制环给的输出再大也无法落地。
- 结构刚度。轮腿系统的结构件如果存在微小形变,会在高频控制时等效成相位延迟,导致原本稳定的控制器出现极限环振荡。这也是为什么有人换一整块碳纤维板后,同样的PID参数突然就能用了。
选型建议:如果你是第一次打比赛,优先做两轮自平衡,因为算法资料最多、调试手段最成熟。不要一上来就挑战四轮摆臂,否则你会同时面对机械加工周期、电机同步、控制解耦三座大山。
3. 运动学建模:轮腿不是“会动就行”
很多参赛队把运动学当成一个“内置函数”,直接用现成库去解算,结果出了问题连排查入口都没有。
两轮自平衡轮腿机器人的运动学其实不难,但要对三个坐标系有清晰认知:世界坐标系、机器人坐标系、轮子坐标系。做路径跟踪时,我们先要把目标轨迹从世界坐标转换到机器人坐标系,然后分解成前进速度v和转向角速度ω,再通过左右轮逆运动学计算出两个轮子的目标转速。
如果机器人行驶方向与世界坐标X轴的夹角为θ,那么正运动学可以写成:
v = (v_r + v_l) / 2 ω = (v_r - v_l) / L其中v_r、v_l是左右轮线速度,L是轮距。
逆运动学则正好反过来:
v_r = v + (ω * L) / 2 v_l = v - (ω * L) / 2在代码里,这就是一个非常核心的模块。下面给一个最小可用的Python逆解示例:
# 文件路径:kinematics/inverse_kinematics.py import math class TwoWheelKinematics: def __init__(self, wheel_radius: float, wheel_base: float): """ :param wheel_radius: 轮子半径,单位米 :param wheel_base: 轮距(左右轮中心距),单位米 """ self.wheel_radius = wheel_radius self.wheel_base = wheel_base def velocity_to_wheel_speed(self, v: float, omega: float): """ 将机器人前进速度和转向角速度转换为左右轮角速度 :param v: 前进线速度,单位 m/s :param omega: 转向角速度,单位 rad/s :return: (left_wheel_rad_s, right_wheel_rad_s) """ v_r = v + (omega * self.wheel_base) / 2.0 v_l = v - (omega * self.wheel_base) / 2.0 # 线速度转轮子角速度 omega_r = v_r / self.wheel_radius omega_l = v_l / self.wheel_radius return omega_l, omega_r def wheel_speed_to_velocity(self, omega_l: float, omega_r: float): """ 由左右轮角速度反推机器人实际速度,用于闭环反馈 """ v_r = omega_r * self.wheel_radius v_l = omega_l * self.wheel_radius v = (v_r + v_l) / 2.0 omega = (v_r - v_l) / self.wheel_base return v, omega这里真正容易踩坑的点是符号约定。很多队伍的转向角速度正负号反了,或者左右轮顺序写反,最后表现就是:明明路径规划是对的,机器人却总是往目标的反方向转弯。
另一个容易被忽略的问题是轮子打滑。两轮自平衡机器人在急加速时,轮子与地面的接触点会发生微小滑动,这时编码器反馈的速度不等于真实速度。如果控制器还在按编码器速度做积分定位,位置误差会越来越大。因此,比赛项目里更推荐用里程计 + IMU 做融合定位,而不是单纯依赖轮子转了多少圈。
运动学模块做完之后,一定要单独写一个测试脚本,让机器人原地转 90 度,看实际转角和目标角度的误差。这个测试能在一天内帮你排除掉大量底层问题。
4. 平衡与运动控制:从“站得住”到“跑得稳”
轮腿机器人控制的核心,是让机器人始终保持动态平衡。动态平衡的意思是:允许车身有一定的前后倾角,但必须让这个倾角始终处在一个“可纠正”的范围内。什么情况下不可纠正?倾角太大,轮子加速也追不上重心投影时,就倒了。
4.1 控制框架:串级PID是最稳的入门方案
单个PID控制轮腿机器人不是不行,但存在明显的响应滞后。通常推荐使用串级PID结构:
- 内环(角度环):控制车身倾角,输出期望角速度。
- 外环(速度环):控制机器人前进速度,输出期望倾角,作为内环的目标值。
为什么这样做?因为轮腿机器人本质上是一个“self-balancing inverted pendulum”,对倾角的控制需要极高的实时性。速度环可以低频运行(比如 50~100Hz),负责慢速纠正位置;角度环必须高频运行(200Hz 以上),负责快速维持平衡。
下面是一个基于 Python 伪代码的串级PID平衡控制器示例,可以直接套用到大部分微控制器上:
# 文件路径:control/balance_controller.py class BalanceController: def __init__(self, kp_angle, ki_angle, kd_angle, kp_speed, kd_speed): # 角度环 PID self.kp_angle = kp_angle self.ki_angle = ki_angle self.kd_angle = kd_angle # 速度外环 PD self.kp_speed = kp_speed self.kd_speed = kd_speed self.angle_integral = 0.0 self.last_angle_error = 0.0 self.last_speed_error = 0.0 def reset(self): self.angle_integral = 0.0 self.last_angle_error = 0.0 self.last_speed_error = 0.0 def update(self, target_speed: float, current_speed: float, target_angle: float, current_angle: float, dt: float): # 外环:速度环计算出目标倾角修正量 speed_error = target_speed - current_speed speed_deriv = (speed_error - self.last_speed_error) / dt if dt > 0 else 0.0 angle_target = target_angle + self.kp_speed * speed_error + self.kd_speed * speed_deriv self.last_speed_error = speed_error # 内环:角度环计算电机输出 angle_error = angle_target - current_angle self.angle_integral += angle_error * dt angle_deriv = (angle_error - self.last_angle_error) / dt if dt > 0 else 0.0 output = (self.kp_angle * angle_error + self.ki_angle * self.angle_integral + self.kd_angle * angle_deriv) self.last_angle_error = angle_error return output4.2 调参顺序:先内环后外环
新手最容易犯的错误是:先调速度环,再调角度环。结果不管怎么调,机器人都在原地疯狂振荡。
正确的顺序是:
- 先让角度环单独工作。给一个固定的目标倾角(比如 0 度),机器人不倒下,说明角度环的参数能“站住”。
- 再加入速度环。推动机器人,观察它能否回到目标速度并保持平衡。
- 再加入路径规划。先跑直线,再跑S形,最后才跑完整任务。
从这次比赛的经验看,最浪费时间的不是调参本身,而是每次调参都只凭感觉。建议做一个简单的参数记录脚本,把每次修改的kp、ki、kd、运行现象、是否恢复到稳定状态记录下来。比赛前两天你会感激这个习惯。
4.3 LQR 和 MPC 值得追吗
如果你的队伍已经能熟练使用串级PID,并且有时间精力,可以考虑LQR(线性二次型调节器)。LQR 的优势是可以显式地对倾角、角速度、位置、速度四个状态做权重设计,通过解 Riccati 方程得到状态反馈矩阵,稳定性有理论保证。但LQR对模型参数比较敏感,如果重心高度、车轮半径标得不准,实际效果未必比调好的PID强。
MPC(模型预测控制)在轮腿机器人中的应用越来越多,但它的计算量大,对微控制器的算力要求高,更适合参赛队伍中有人专门负责上层算法、底层控制已经稳定的情况。比赛场景下我不建议用 MPC 做内环,风险大于收益。
5. 传感器与状态估计:为什么你的车突然抽风
轮腿机器人的传感器方案,直接决定系统在大赛环境下的鲁棒性。这里说的“抽风”,通常不是程序逻辑错误,而是传感器数据本身出了问题。
5.1 IMU:唯一不可妥协的核心传感器
对两轮自平衡轮腿机器人来说,IMU(惯性测量单元)就是它的“前庭系统”。没有IMU,机器人连站都站不起来。IMU包含加速度计和陀螺仪,关键是把两者融合成可靠的姿态角。
- 加速度计:长期稳定,但受振动干扰大。轮腿机器人在高速行驶时,电机振动会让加速度计输出高频噪声。
- 陀螺仪:短时准确,但存在积分漂移。长时间使用后角度会缓慢偏离真实值。
所以要用互补滤波或卡尔曼滤波结合两者。互补滤波实现简单、计算量小,在单片机上表现不错:
# 文件路径:sensor/complementary_filter.py class ComplementaryFilter: def __init__(self, alpha=0.98): """ alpha 越接近1,越信任陀螺仪;越接近0,越信任加速度计 """ self.alpha = alpha self.angle = 0.0 def update(self, gyro_rate: float, accel_angle: float, dt: float): # 陀螺仪积分 gyro_angle = self.angle + gyro_rate * dt # 互补融合 self.angle = self.alpha * gyro_angle + (1 - self.alpha) * accel_angle return self.angle实际比赛中,如果你的机器人突然在某个角度开始疯狂抖,很可能是alpha设置过大,陀螺仪漂移没有被及时纠正。
5.2 编码器与里程计
轮子电机内置的编码器,能够提供左右轮转速,进而推算行驶距离和速度。但要注意编码器分辨率:如果选用的电机编码器分辨率过低,低速时会出现“一顿一顿”的感觉,平衡环没法得到一个平滑的速度反馈。
5.3 视觉传感器的坑
很多队伍会加入摄像头做赛道识别或红绿灯识别。视觉传感器的最大问题不是算法准不准,而是受环境光影响大。比赛现场灯光复杂,同一套画面在教室调好了,到现场可能完全失效。稳妥的做法是:
- 视觉只做红绿灯、标志物等辅助任务。
- 轨迹跟踪还是优先靠 IMU + 编码器融合的里程计。
- 如果必须用视觉,提前到场调白平衡和曝光,不要留到比赛前十分钟才改参数。
6. 比赛现场的隐藏变量:规则、场地、心态
比赛最容易翻车的地方,恰恰是平时不会测到的地方。
6.1 规则细节一定要抠到字面
比如“绕桩时不能碰到桩桶”,有些队伍理解为“不压到桩桶”,但规则写的是“触碰即扣分”。这意味着车体哪怕只是擦到桩桶边缘,就会被扣掉时间分。
从这次比赛的报名材料看,很多队伍在规则理解上吃了大亏。建议拿到规则后,把每一条评分标准抄到白板上,逐行讨论,特别是扣分项。不要觉得“差不多就行”,裁判是按规则逐项打分的。
6.2 场地摩擦系数和教室完全不同
比赛场地经常是地胶或磨砂地面,与实验室瓷砖地面差异巨大。摩擦系数变低最直接的影响是:急加速时轮子严重打滑,编码器里程计失真,平衡控制器输出被迫加大,最终车身剧烈振荡。
解决办法有两个:
- 比赛前用一个便携式摩擦测试块(一个小木板上面放砝码,用测力计拉)快速测出场地摩擦系数,然后预估打滑风险。
- 程序里对电机输出做限幅,并对轮速做低通滤波,降低打滑时的高频抖动影响。
6.3 电池电压是隐藏的“第三方变量”
电池电压下降后,电机可输出的最大扭矩会下降。同一个PID参数,满电时跑得很稳,电量降到 70% 后就会开始抖甚至追不上角度误差。
建议:
- 比赛前统一充满电,并记录多组不同电压下的表现。
- 调试用满电状态,但保留一组“低压应急参数”。
- 如果比赛规则允许,多用一块小降压模块稳住控制板供电,避免逻辑电路因为电机压降复位。
7. 赛后复盘:为什么第四名会止步省二
第四名和省二这个结果,如果只看技术排名,确实很可惜;但站在备赛角度,几乎没有哪个第四名是“纯运气差”。
我们赛后花了三个小时做数据复盘,把所有录像按帧拆开,对齐时间轴,逐段分析。最后找出了几个关键问题:
第一,绕桩路径存在明显的“外抛”现象。车在高速转弯时,因为速度环响应不够快,实际轨迹比目标轨迹更靠外,虽然没有碰桩,但增加了行驶距离。累计下来,比前几名慢了 0.4 秒左右。
第二,过减速带前后速度控制不平滑。在过减速带瞬间,轮子短暂离地,编码器反馈速度跳变,速度环产生了一个反向修正,导致车身出现明显点头。虽然没倒,但视觉上很难看,而且恢复稳定多花了两秒。
第三,检录后没有重新跑完整流程。这是最致命的。比赛现场我们在检录后只测试了单步动作,没有完整跑一次赛道。结果真正比赛时,现场地面摩擦系数和教室不同,路径参数没有更新,第一轮跑出了备赛以来最差的成绩。
这三点,每一项单独看都很小,但在同一轮比赛里叠加起来,就是“省二”和“省一”的差距。
8. 常见问题与排查清单
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 机器人启动后立刻倒下 | IMU 姿态初始化失败或倾角符号反了 | 查看串口打印的IMU角度,用手动扶正测试方向 | 检查IMU安装方向,校准零点,统一符号约定 |
| 静止时车身左右高频振荡 | 角度环 P 值过大,或 IMU 数据噪声大 | 降低 P 值测试,观察串口波形 | 减小角度环 P,增加IMU低通滤波 |
| 前进时频繁“栽头” | 速度环参数过强,角度环响应跟不上 | 单独测试角度环,确认能站住后加速度环 | 降低速度环 P,或增加速度环 D |
| 过减速带后无法恢复平衡 | 轮子离地导致编码器速度跳变 | 打印轮速和IMU倾角,看跳变时刻 | 对轮速做滑动窗口滤波,过障碍时切换至位置模式 |
| 同一程序上午稳定下午发抖 | 电池电压下降或场地摩擦系数变化 | 记录电压和运行状态 | 低压应急参数,赛前重新标定摩擦 |
| 路径跟踪误差越来越大 | 轮子打滑导致里程计积分漂移 | 对比里程计和实际位移 | 融合IMU,使用视觉/激光辅助定位 |
| 现场灯光下视觉识别失效 | 曝光和白平衡异常 | 提前到场测试不同曝光参数 | 固定曝光时间,关闭自动白平衡 |
9. 给下一届选手的建议
如果你准备参加下一届省赛或国赛,下面这五条建议,是我最想让你提前知道的:
第一,不要在最后一个星期换大件。机械结构、电机、驱动板、IMU 类型,任何一项大改都需要至少两周的重新调试期。到了最后一周,只做微调,不做革命。
第二,建立“一轮到底”的测试习惯。从启动到完成所有任务,最终只认完整流程时间。平时不要只测单块功能,因为单块通过不代表组合能通过,组合通过也不代表连续多轮稳定。
第三,给参数做版本管理。把每次调参的数值、现象、场地条件、电池电压都写进一个表格里,不要只靠代码注释。好的参数版本管理,能让赛前 48 小时的高压调试变得高效。
第四,备好“应急预案包”。包括:备用电池、备用轮子、备用IMU、一根短接线、带串口打印的调试线。比赛现场最怕的不是技术问题,而是找不到配件。
第五,更早去适应临场压力。比赛时的紧张会让操作变形。建议赛前一周做两次完整模拟赛,包括检录、排队、等待、上场的完整流程,让队员习惯从“安静调试”切换到“比赛模式”的节奏。
10. 总结
轮腿第四名,含泪止步省二。这个结果听起来遗憾,但它其实是比赛送给你的一份礼物。因为第四名意味着你已经具备了冲进第一梯队的技术基础,差的不是方向,是细节和稳定性。
从这次复盘里,我学到的最重要的一件事是:比赛拼的不是你最好的一次表现,而是你最差的一次不失误。轮腿机器人也好,其他智能车赛项也好,都是同一个道理。技术问题的坑是可以提前踩完的,只要你在赛前愿意一遍一遍地跑完整流程。
下一届,建议你把“求稳”写进队训,把“完整跑完每一条可能的轨迹”当成每日必修课。省一不是等到比赛那天才争取的,而是从今天每一次调参、每一轮测试、每一份记录里攒出来的。