滚球控制系统从零到稳定:视觉、机械与PID控制的完整实践解析
简介这套开源项目面向2017年全国大学生电子设计大赛B题提供完整的滚球控制系统板球系统设计方案适合电子竞赛备赛者、嵌入式系统学习者以及需要快速搭建球体平衡控制原型的工程师。项目基于嵌入式平台开发核心代码覆盖PWM电机控制、外部中断响应、超声波/激光测距、SPI通信、编码器测速、定时器调度等模块并包含硬件接口与底层驱动能够帮助理解从传感器采样到执行器输出的完整控制链路。资源包共190个文件主要类型为C源码.c/.h和Keil工程配置.uvprojx等另有大量.bak备份文件、若干图片、说明文档和文本资料便于对照工程逐步调试整体压缩包约5.96MB。当前已有1356人学习对于需要参考真实赛题工程、研究嵌入式外设驱动或扩展板球控制算法的开发者这是一份有实际参考价值的开源资料。1. 一道看着简单、上手才知水深的题目2017年国赛B题「滚球控制系统」也就是大家常说的板球系统、Ball on Plate在电赛圈里的口碑相当两极分化。单看外观它不过是一块平板、一个球、两个舵机很多人第一天看到题目时都会觉得这有什么难的但真正组队做起来才明白整个系统是视觉、机械、控制三个子系统的串联任何一环出问题球就是停不下来、走不准甚至直接滚出板面。这道题的核心任务一句话就能说完通过控制平板的俯仰角和翻滚角让小球在板面上移动到指定坐标点并稳定停留发挥部分通常还会要求小球沿着给定直线、圆或者自定义轨迹运动。听上去很简单但实际做的时候问题全部集中在稳定两个字上——小球在平板上是一个典型的双积分不稳定对象如果没有合理的控制策略它要么不动要么冲过头要么在目标点附近来回震荡。1.1 题目要求与真正的难点先看基本盘。题目会给一块可以倾斜的平板板上放一颗小球要求系统能够通过控制板的倾斜角度把小球送到任意指定的坐标位置并且稳定停留。这个任意指定意味着你没法靠机械限位或者固定滑道来偷懒必须做闭环反馈。难点在于三个环节同时在线视觉环节要知道小球当前在板面的哪个位置通常是实时的、连续的坐标信息控制环节根据当前位置和目标位置的误差计算出板子应该倾斜多少、往哪个方向倾斜执行环节舵机响应要够快够准把计算出的角度指令真实作用到平板上。这三个环节任何一个出问题整个环路都会断开。尤其是视觉→控制之间的延迟和噪声会在后期的联调阶段被无限放大这也是为什么很多队伍基本功能能跑通但一进入发挥部分就翻车。1.2 三条技术路线怎么选当年主流做法大致分三类。第一类是摄像头视觉方案用俯拍相机识别小球位置反馈给控制器这是最多队伍采用的做法通用性强后期扩展轨迹跟踪也比较容易第二类是在板面下方做触摸或光电感应阵列直接用传感器矩阵测小球位置精度高但板子要做得非常精细而且小球走哪条轨迹都会受阵列密度限制第三类是极少数队伍尝试过的激光测距、惯性导航等方案难度大、成本高并不适合四天三夜的比赛节奏。我们当时选了摄像头方案。现在回头看这个选择是对的摄像头方案把难点集中在了软件侧而软件侧的调试迭代速度远快于硬件改板子。这套思路后来也成了很多同学做视觉伺服入门的第一课。接下来我就把这个系统的完整实现拆开讲从机械结构到视觉标定从PID整定到联调踩坑希望能帮后来的人少走一半弯路。2. 机械结构平板不稳控制写得再好都是白搭先说结论板球系统能不能做出来机械至少占四成。很多人一上来就写视觉和控制结果板子装完有虚位、有共振、重心不稳后面调PID调到头秃也救不回来。2.1 两自由度结构怎么选板球系统需要两个旋转自由度分别控制平板绕X轴和绕Y轴的倾角。常见结构有两种。球铰/万向节方案平板中心下方用一颗万向球铰支撑两个舵机通过连杆分别推平板的两条边或两个角。优点是结构简单、摩擦小、响应快缺点是球铰中心必须与板面几何中心对齐否则平板的转动会附加平移分量小球坐标会漂移。十字万向架方案外框绕一个轴转内框绕另一个轴转两个舵机分别驱动两个框。优点是转动解耦更干净标定方便缺点是整体结构更重、更高转动惯量变大舵机负载也更大。我们当时选的是球铰式因为加工量小一对亚克力板加几根铜柱就能搭起来。关键点是球铰一定要锁紧别让板子有上下方向的窜动。如果有虚位小球在静止时会出现低频抖动而且这个扰动的方向是随机的PID无法预判只能靠加大阻尼硬压效果很有限。2.2 舵机、平板和球怎么选执行机构用舵机是最省事的。两个MG996R金属齿舵机就够了扭矩大概在9.4kg·cm6V用5V或6V稳压供电。千万别用9g舵机平板稍微有点倾斜阻力就带不动一旦堵转还会烧。如果预算够用总线舵机或大扭矩数字舵机也可以控制精度会稍微好一点但普通PWM舵机加反馈闭环完全够用。平板材料建议用轻质、平整的亚克力板或轻木板尺寸按题目要求来。表面处理是很多人忽略的点表面太光滑小球滚动过快控制每次都要跟它赛跑表面太粗糙小球启动时需要更大的倾角容易出现静摩擦死区也就是给了角度但球不动等角度累积大了突然一窜。最稳妥的做法是用600目砂纸把亚克力板表面轻轻打一遍或者贴一层薄薄的磨砂贴膜让小球滚动起来既有阻力又不至于卡顿。小球一般用直径20mm到40mm的实心钢球。钢球质量大惯性大对控制算法来说反而更友好因为它不会因为舵机瞬间抖动就乱跳。另外球的颜色最好和板面形成强烈对比比如红球配白板这会给后面的视觉识别减少很多麻烦。2.3 装配里最容易忽略的两个细节一个是舵机摇臂与推杆之间的连接尽量用球头拉杆不要用那种硬性插入的塑料件。球头拉杆能消除舵机旋转到连杆之间的空程空程一旦超过两度视觉上就会表现为小球位置在目标点附近随机跳不管你控制周期多短都压不掉。另一个是整体重心。平板加球加支架的重心越低越好否则舵机在高速来回转动时整机会跟着抖摄像头拍到的是晃动画面视觉坐标自然不稳定。我们当时把舵机固定在底座上用拉杆传动就是不想让舵机本身成为平板上的运动质量。这个细节看起来不起眼但对稳定性的提升非常明显。3. 视觉识别与坐标标定摄像头看到的只有像素机械装好以后接下来就是整个系统里最容易让人心态爆炸的部分——视觉。摄像头采集到的图像里只有一行行像素而控制算法需要的是小球在板面上的物理坐标单位是毫米。这两者之间的转换精度直接决定了小球能不能停在目标点上。3.1 摄像头怎么装方案选择上固定支架从上往下俯拍是最省心的视角越大覆盖板面越完整。支架要足够稳固最好直接用型材架或三脚架别用细木棍绑在板子旁边——一旦相机位置被舵机振动震偏整个标定就废了。安装时让镜头光轴尽量垂直于板面这样透视畸变最小标定也会更好做。摄像头本身用普通的USB摄像头就行。关键指标不是分辨率而是帧率和快门。30fps是底线能上60fps最好因为控制周期受帧率限制30fps意味着最快只能每33ms拿到一次新位置对小球这种跑起来很快的对象来说稍微有点紧张。另外要手动把摄像头曝光调低、关掉自动白平衡否则小球颜色在画面里会因为环境光变化而漂移识别阈值也会跟着失效。3.2 小球识别HSV阈值加形态学就够了识别小球用OpenCV的HSV颜色空间别用RGB。HSV把色相和亮度分开了对光照变化更鲁棒。以红色小球为例处理步骤是把BGR图像转换到HSV空间用cv2.inRange提取红色区间。注意红色在HSV里是双区间需要同时取H值在[0, 10]和[160, 180]两个范围对二值图做一次开运算先腐蚀后膨胀去掉散点噪声找轮廓取面积最大的那个用cv2.moments求质心像素坐标。这里最容易踩的坑是光照。板面如果有反光小球会在画面里出现亮斑质心会被带偏如果环境光变化阈值就会失效。解决办法是尽量在固定光源下使用每次开机时自动采样一次背景色来校准阈值范围别指望同一组H/S/V阈值能在不同时间通用。3.3 像素坐标到物理坐标的标定拿到小球质心像素坐标之后需要映射到板面物理坐标。理想情况下摄像头垂直俯拍可以假设板面是一个平面用单应性矩阵或仿射变换来做转换。最实用的标定方法在板面上贴一张打印好的标定纸比如3×3的点阵记录每个点在图像中的像素坐标和它在板上已知的实际坐标然后用cv2.findHomography求出单应矩阵H。之后任意像素坐标左乘H就能得到物理坐标。如果不想打印标定纸也可以手动把小球放到板面上几个已知位置获取对应像素坐标来拟合但要保证这些点尽量覆盖整个板面尤其是边缘区域。只标定中心三个点的话边缘误差会非常大因为镜头畸变和透视畸变在边缘最明显。另外提醒一下别忽略镜头的非线性畸变。如果板面较大而摄像头离得比较近边缘像素误差可能达到好几个毫米。解决方法是先用cv2.calibrateCamera做一次相机畸变校正再计算单应矩阵。对于电赛级别的精度要求这一步不是必须但如果你的球总是到了边缘就停不准多半就是这个原因。4. 控制核心小球不是你想停就能停的视觉把小球的位置告诉控制器接下来就是整个系统的灵魂——控制算法。如果只凭直觉写控制这一步会因为小球的物理特性而变得非常痛苦。4.1 先理解小球为什么这么难控把平板倾角记为θ简化成单轴分析另一轴同理小球沿板面方向的运动方程近似为m·x m·g·sin(θ)在角度不大的情况下约等于x ≈ g·θ。也就是说小球的加速度直接由倾角决定而我们控制的是倾角不是位置也不是速度。这是一个典型的双重积分系统位置是速度的积分速度又是倾角的积分。这样的对象天生不稳定——你给小球的每一个倾角它都会一直加速下去直到你反方向再给一个倾角才能慢慢拉回来但这时候球已经冲过头了。所以用位置误差直接驱动舵机的方案也就是最朴素的P控制完全不可行。位置误差大时给大倾角球冲得飞快等球到了目标点它已经有了很大的速度根本停不下来于是冲到另一边来回震荡甚至滚出板面。4.2 从PD到串级控制最简单有效的是PD控制器θ_cmd Kp·e Kd·e_dot位置误差e负责把球往目标点拉误差变化率e_dot也就是速度相关项负责踩刹车。速度项是关键它相当于阻尼让小球靠近目标点时减速。但纯PD有个软肋稳态精度不够。如果平板有静摩擦或者机械虚位小球会停在离目标几个毫米的地方动不了这时需要加积分项也就是PIDθ_cmd Kp·e Ki·∫e dt Kd·e_dot不过积分项不能给太大而且要加积分限幅防止积分饱和导致球在目标点附近持续超调。我的经验是积分限幅设在角度输出的10%左右超过就截断等误差反向后积分自然回退。更稳定一些的做法是把速度也拉进来形成串级控制外环位置误差 → 目标速度用P控制器内环目标速度与实际速度的误差 → 倾角指令用PD或PI控制器。速度可以由位置差分得到。串级的好处是外环只管多快能到目标内环专门负责实际速度要和期望速度一致两个环各自整定系统稳定裕度更充足。我们在实测中发现同样的位置环参数换成串级之后过冲明显变小收敛时间也更快。4.3 参数整定的实际经验数字PID的控制周期建议设在20ms到50ms之间。参数整定我建议按这个顺序来先设积分和微分都为0只给一个不大的P让小球能在目标点附近形成振荡观察振荡周期和振幅逐步加大P直到振荡明显加快但还没发散这时候再开始加DD会让振荡平息下来小球稳定但离目标点还有几毫米误差时一点点加II要非常小通常只有P的百分之几。这里有一个容易犯的错一上来就同时调三个参数结果系统一旦发散你根本不知道是谁导致的。每次只动一个参数并且每调一次就把位置曲线画出来看有数据才能做判断。还有一个细节控制输出也就是倾角指令一定要限幅。比如最大给4度到6度。如果输出的倾角上限太大小球会像坐过山车一样在板面上狂奔限幅后虽然移动慢一些但系统稳定性和可控性会大幅提升小球反而能更快到达目标。5. 联调阶段最容易翻车的三个细节机械、视觉、控制单独跑都没问题不代表合在一起就能工作。联调阶段我们踩过的坑每一个都值得单独拿出来说。5.1 视觉噪声如何毒杀微分项摄像头识别的质心坐标本身就有抖动通常是一两个像素的随机噪声。位置信号看起来没问题但差分求速度之后噪声会被放大很多倍微分项产生高频抖动舵机跟着滋滋响小球反而更不稳定。解决方法是对位置信号做一次轻量级滤波比如滑动平均窗口取3到5帧或者用一阶低通滤波。但滤波会带来延迟所以滤波强度要适度。我的经验是滤波后位移曲线依然能看到清晰趋势就行不要追求完全平滑。另一个办法是只在速度计算时用滤波后的位置位置控制仍用原始值这样能在抑制噪声的同时减少相位滞后。5.2 延迟引起的震荡从摄像头采集到输出舵机PWM整条链路里面有图像传输延迟、图像处理耗时、舵机响应延迟。这些延迟累加起来如果超过一个控制周期PID实际上在控制一个过去的状态相位滞后会让系统更容易震荡。处理办法有两个方向。一是压缩图像处理时间用640×480分辨率正式跑任务时关掉调试画框把处理耗时控制在10ms以内。二是控制周期不要盲目追求短。如果摄像头只有30fps每33ms才能出一次位置数据你硬把控制周期设成10ms反馈还是33ms一次反而会让控制指令在两次反馈之间空转增加噪声干扰。把前两点做好比在算法上加各种预估器更实际。5.3 小球丢失或跑到板边缘时怎么办小球滚出视野、或者被支架遮挡的瞬间质心检测会失败。如果不处理上一帧的位置会被沿用控制器以为球还在原地继续输出倾角等球重新出现时位置已经偏了一大截。我们的处理策略是维护一个最后有效位置和一个丢失计时器。连续超过3帧没有检测到小球就认为小球处于丢失状态这时候不再对当前误差做PID而是让平板缓慢恢复到水平状态。这样球即使滚到边缘也会因为重力分力消失而减速大概率能救回来。实测下来这个策略非常有效至少不会出现球丢了板子还在乱晃的失控场面。5.4 轨迹跟踪与其精细控制不如提前规划基础部分做完以后发挥部分一般会要求小球画直线或画圆。这里我强烈建议不要只靠PID硬跟目标点——也就是让目标点沿轨迹逐帧移动因为PID有惯性每个目标点还没跟上就跳到下一个轨迹会变成一截一截的折线。更好的做法是给目标轨迹做预规划。比如画圆时让目标点按恒定角速度沿圆走而不是每帧更新一个位置同时根据小球当前速度预测它下一时刻的位置用更前瞻的目标误差去控制。这样虽然单点误差可能大一点但曲线的连续性远比逐点硬跟要好。我们当时用了一个简单的速度前馈位置校正方案根据圆轨迹的切线方向算一个前馈倾角再叠加PD位置校正效果立竿见影轨迹从锯齿状变成了平滑的弧形。6. 从这道题里能带走的通用经验最后聊一些题外但很实在的经验。第一个是时间分配。四天三夜的比赛很多人前三天都在调视觉最后一天才开始写控制这是最大的错误。合理的时间分配应该是第一天上半天搭机械下半天把摄像头和图像处理跑起来第二天做标定和基本的位置PID第三天做稳定性优化和发挥部分第四天留一整天联调、测各种边界情况。控制和视觉必须并行推进不能等所有前置工作做完再开始。第二个是调试方法论。板球系统最大的特点是全链路耦合——图像抖动会导致控制震荡机械虚位会加剧图像噪声表面上看是视觉问题实际根源可能是机械问题。遇到问题不要靠猜要把变量隔离出来用录好的视频离线跑图像处理确认视觉单独工作是否稳定把PID输出直接打印出来看控制量是否在合理范围用手把球推到某个位置观察系统响应方向是否和预期一致。每一次只验证一个环节。第三个是重视数据。我们队当时做了一个简单的上位机实时绘制小球位置曲线、目标位置和控制输出三路信号。很多诡异的问题比如小球在某个特定位置总是偏几毫米光看板面是看不出来的但曲线上一眼就能看出是那个位置的光照导致质心系统性偏移。没有数据你只能靠手感调效率和成功率都很低。第四个是这道题的通用价值。板球系统虽然只是一道电赛题目但它覆盖的感知、决策、执行闭环链路和很多实际工程项目是完全同构的。摄像头标定、位姿估计、串级PID、滤波、前馈补偿这些在无人机、机械臂、自动驾驶小车里都是基础能力。把这道题的整条链路吃透后面做任何视觉伺服类项目都会轻松很多。至少对我来说这道题带来的收获远比一张证书要实在。本文还有配套的精品资源点击获取