ARTICLE DETAIL

资讯详情

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

平衡球机器人实战:OpenCV视觉定位与STM32级联PID控制

平衡球机器人实战:OpenCV视觉定位与STM32级联PID控制 折腾这个平衡球机器人之前我一直以为最难的部分是PID控制。实际把整套系统从视觉定位一路跑到PID闭环之后才发现真正的难点根本不在某一颗芯片、某一次控制运算上而是整条链路——摄像头怎么稳定锁定球的位置、像素坐标怎么换算成平台角度、级联PID在STM32裸机上怎么跑得又稳又快、以及最后调kp ki kd时候那种“看起来要稳了又突然抖起来”的玄学瞬间。这篇文章就把我踩过的坑和最终跑通的方案完整写出来给正在做或者准备做自主平衡球机器人的朋友一个可以直接参考的全流程解析。这个项目最终的形态是一块亚克力平板底下用两个金属齿轮舵机控制平台绕X轴和Y轴倾斜平板上放一个橙色乒乓球顶上一个USB摄像头实时拍摄小球位置上位机用OpenCV识别出球的坐标通过串口把坐标发给STM32F103单片机跑裸机级联PID把坐标误差换算成两个舵机的PWM角度增量让球自己滚回目标点并停稳。从摄像头拍下画面到舵机做出反应整条链路延迟控制在50ms以内实测在60×60cm平台上能把球稳定控制在目标点正负2cm范围内。这个项目做完一轮之后你对视觉传感器、控制系统和执行机构的配合会有非常立体的理解。1. 整机链路先搭对视觉、控制、执行三层怎么协作1.1 我先走的弯路先调PID还是先搭视觉我第一次做这个项目的时候脑子里的顺序是先调PID再补视觉。结果很尴尬我用手把球拨来拨去看着舵机跟着摆感觉“控制挺有劲儿”但完全不知道让球去哪因为没有目标坐标输入PID的外环实际上是个开环。后来才想明白一件事——平衡球机器人本质是一个闭环系统先有稳定的“眼睛”控制环才有意义。视觉定位不是锦上添花它是整个系统的测量前端没有它PID只能空转。所以正确顺序应该是先打通视觉链路确认每一步能拿到准确的球坐标再搭执行机构确认舵机方向正确、平台响应正常最后才把两者接起来调PID。每一步都单独验证过联调时才有底气。1.2 系统的数据链路一帧画面如何变成一次舵机动作整个系统从输入到输出大概可以拆成六个环节每个环节都会消耗时间我实测的延迟预算如下摄像头采集一帧分辨率640×48030fps约33ms一帧OpenCV检测小球、透视变换、计算坐标约10~20ms串口发送坐标数据115200波特率10个字节不到1msSTM32以100Hz周期执行级联PID运算一个控制周期10ms舵机响应角度指令约20~30ms平台倾斜球滚动进入下一轮检测整体从“看到球”到“平台发生变化”大约50ms左右。这个延迟对平衡球系统来说是可以接受的。如果延迟超过80ms球就会明显超调感觉像控制系统喝醉了一样怎么调参数都压不住振荡。所以在前期延迟不是一个笼统的概念而是要逐段测量、逐段优化的指标。1.3 硬件选型的关键考量硬件选型上我踩过不少坑这里给一套最省心的组合思路。主控方面我用的是STM32F103C8T6。这个项目里单片机只负责跑PID和生成PWM视觉在PC上处理所以F103的算力完全够用。如果你打算把视觉也移植到单片机上用OV2640或者OV7725摄像头模块直接接MCU那建议换STM32F407以上带DSP指令集和足够的RAM不然处理一帧图像会比较吃力。执行机构是很容易被低估的部分。一开始我用SG90舵机结果平台稍微不平舵机就喘不上气球根本稳不住。后来换成MG996R金属齿轮舵机扭矩上来了响应明显改善。结论是平衡球这类需要持续微小修正的场合舵机的扭矩和回程间隙比速度更重要。回程间隙大的舵机每次反向修正都有空程PID输出再精确也会被机械间隙吃掉。平台和球的搭配也很有讲究。平台我用的是亚克力板表面光滑但不要太打滑——太滑了球在中心附近停不住容易画圈太糙了球滚动不流畅舵机要出很大的力。球选橙色的标准乒乓球重量轻、表面漫反射均匀而且橙色在HSV颜色空间里跟常见的背景色区分度高视觉检测特别好做。1.4 通信协议怎么设计别用文本用二进制上位机和STM32之间我用串口通信波特率115200。协议设计上有一个务实建议不要用文本协议。一开始我图省事直接用“x12.5,y-3.2\n”这样的ASCII字符串。问题有两个一是包含小数格式化需要消耗时间二是解析时容易出错比如摄像头丢帧导致数据断裂解析就乱了。后来改成二进制协议帧头0xAA 0x55 || 数据长度1字节 || cmd0x01 || float32 X坐标 || float32 Y坐标 || 校验和1字节上位机每发一帧解析代码先用帧头对齐再校验长度和校验和错了就丢弃这帧不阻塞。实测这样处理起来干净利落坏数据直接扔掉不会把单片机的控制状态带偏。坐标用float32传输平台范围60×60cm精度到小数点后两位足够了。2. 视觉定位从像素坐标到小球真实位置的换算2.1 为什么选HSV颜色识别而不是深度学习方法视觉方案我一开始也纠结过要不要上YOLO搞个目标检测显得很高级后来被现实教育了——平台是固定场景小球是唯一明显的橙色物体用深度学习属于过度设计。我选用HSV颜色空间加形态学处理理由很直接零训练数据、单帧处理快、逻辑完全可控。RGB颜色空间的问题在于光照变化时三个通道一起变不容易划出稳定阈值。HSV把色相H、饱和度S、明度V分开了我们只需要锁定H通道的橙色范围对光照变化鲁棒得多。这里有个小经验阈值范围宁小勿大。很多人为了让“所有橙色”都被检测到把H范围拉得很宽结果把背景里的木纹、反光也当成了球。我的做法是先截一张画面在球上取几个点的HSV值再留20%的余量作为阈值。2.2 摄像头标定与畸变矫正边缘误差的隐形凶手很多教程只讲检测和PID不讲摄像头标定但实战中你会发现不标定的后果全都在调PID时还回来了。普通USB摄像头尤其是广角镜头画面边缘畸变很明显。球在平台中心时位置误差小一到边缘像素坐标和真实平台坐标的偏差会莫名变大PID在这时候特别容易失控。我用张正友标定法打一个棋盘格采集十几个角度用OpenCV的calibrateCamera拿到相机内参和畸变系数。处理环节加一步去畸变import cv2 import numpy as np # 假设已经通过标定得到 camera_matrix 和 dist_coeffs # new_camera_matrix 取合适的alpha值保留全部画面 new_camera_matrix, roi cv2.getOptimalNewCameraMatrix( camera_matrix, dist_coeffs, (640, 480), 1, (640, 480) ) def undistort_frame(frame): return cv2.undistort(frame, camera_matrix, dist_coeffs, None, new_camera_matrix)这一步做完平台四个角的像素坐标误差从原来的十几个像素降到两三个像素以内在60cm的实际尺寸上相当于毫米级的改善。这对后面PID有本质影响。2.3 小球检测阈值、形态学、轮廓与质心检测着色球的标准流程是“HSV阈值 形态学处理 最大轮廓 质心计算”。代码写出来并不长def detect_ball(frame): # 1. 转HSV并做阈值分割 hsv cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) mask cv2.inRange(hsv, lower_orange, upper_orange) # 2. 中值滤波去噪再开闭运算填补空洞 mask cv2.medianBlur(mask, 5) kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) mask cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) mask cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # 3. 找到所有轮廓取面积最大的 contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if not contours: return None, None largest max(contours, keycv2.contourArea) if cv2.contourArea(largest) 100: # 面积阈值剔除噪声 return None, None # 4. 用矩计算质心 M cv2.moments(largest) if M[m00] 0: return None, None cx int(M[m10] / M[m00]) cy int(M[m01] / M[m00]) return cx, cy**为什么要用质心而不是外接矩形的中心**因为球在被遮挡或者高光的时候轮廓可能不完整。cv2.moments算的是轮廓的几何重心对部分缺失的形状仍然能给出一个稳定的中心估计。这个细节在实战中救了我好几次——光照突变导致球的轮廓缺了一小块但质心依然稳定PID不会因此跳变。2.4 透视变换把倾斜视角变成“俯视图”畸变矫正是修正镜头的“桶形鼓包”但这还远远不够。摄像头通常装在平台斜上方不是垂直俯拍所以同样的球在画面左端和右端像素距离和实际距离的比例差很多。因此在检测到像素坐标之后还要做透视变换把图像映射成平台正上方的俯视图。操作方法是在平台上标记四个角点比如用四个A4纸小方块取它们的像素坐标作为源点src再指定它们对应的目标坐标dst比如(0,0)、(600,0)、(600,600)、(0,600)。调用cv2.getPerspectiveTransform得到变换矩阵再用cv2.warpPerspective把整张图映射成600×600的平台俯视图。之后在这个变换后的图上做小球检测得到的坐标就能直接当作平台坐标使用。这里要注意每次开机摄像头位置可能有轻微移动透视矩阵应该做成可标定的。我在上位机里写了一个“标定模式”按一个键进入自动检测四个角点并重新计算矩阵。切换场景后按一下一分钟内搞定非常实用。2.5 坐标滤波别把视觉噪声灌进PID检测出来的质心坐标并不是平滑的即使球静止不动坐标也会因为光影抖动、轮廓微小变化产生几个像素的噪声。这些噪声如果直接进PID微分项会被放大舵机会一直高频率微颤听起来就像蜜蜂叫时间长了舵机容易过热。我用了两层滤波先做中值滤波剔除离群点偶尔检测跳变再做滑动平均平滑轨迹。滑动窗口选5~7帧比较合适。窗口太小平滑效果差窗口太大带来相位延迟球已经开始减速了系统还按原来的速度算容易过冲。一个小技巧是对位置做滑动平均之后不要对同样的数据再做二阶滤波否则相位延迟会叠加。3. 控制策略设计为什么最终选择位置环速度环的级联PID3.1 单环PID的窘境对着位置使劲永远慢半拍一开始我只写了一个位置环——把球的坐标和目标点坐标做差误差乘上比例系数直接给舵机角度。逻辑上好像通球偏右了就让平台往左倾球就会滚回来。但实际跑起来发现球在目标点附近永远稳不住老是冲过去又冲回来形成很明显的往复振荡。原因不难理解平台倾斜角控制的是球的加速度不是位置更不是速度。位置误差大的时候如果倾角很大球会越滚越快等球接近目标点了误差小了倾角归零但球已经有很大的速度一定会冲过头。整个过程相当于一个人闭着眼睛跑步只看“还有多远到终点”却不知道自己速度有多快肯定跑过站。3.2 级联PID的物理直觉后来我改成位置环速度环的级联PID本质上是给系统加了“速度感知”。外环读懂位置误差把它换算成一个期望速度内环负责让球的真实速度跟上期望速度。如果球接近目标但速度还很快内环会提前给出反向倾角把球“刹车”刹住避免过冲。打个比方位置环是导航告诉你离目的地还有多远应该开多快速度环是司机脚下的油门和刹车负责把你的臆想速度变成实际加减速。导航看错距离会偏航司机刹车失灵会撞墙两者配合才能把车停稳。外环位置环输入是位置误差输出是期望速度内环速度环输入是期望速度和实际速度之差输出是平台倾角指令级联结构的另外一个好处是抗扰性。如果平台被外力碰了一下球的真实速度突然改变内环会立刻感知到并修正而不是等位置误差积累到一定量才反应。这比单环PID提前一拍。3.3 速度怎么估计差分必然噪声大关键是滤波到位速度信号从哪里来最自然的方式是对位置坐标做差分。vx (x_current - x_prev) / dt vy (y_current - y_prev) / dt位置坐标本身经过滑动平均之后已经偏平滑但差分是一个高通操作会把残留的高频噪声放大。实测差分出来的速度曲线毛刺很多直接送进内环会让舵机抖得厉害。我的处理是差分之后再做一次一阶低通滤波截止频率设在10Hz左右既保留速度变化的真实趋势又滤掉采样噪声。公式如下v_filtered alpha * v_raw (1 - alpha) * v_filtered_prevalpha取0.2~0.3左右记住一个原则——控制系统的灵敏度永远要低于传感器的噪声频段不然你在控制的是噪声而不是球。3.4 从PID输出到舵机角度坐标轴映射和方向修正很多人到这一步会卡住PID输出的是平台应该倾斜多少度但舵机怎么知道这个度是多少我的做法是先做机械标定。平台静止水平时记录两个舵机的PWM脉宽作为中位值。然后只动X轴舵机让平台向X方向倾斜记录小球静止时在平台上的真实位置变化方向。如果摄像头坐标系的X方向对应左侧而平台倾斜让球往右边滚那就说明方向反了需要在代码里加一个负号。方向反了是调PID阶段最常见的低级错误而且表现非常诡异——参数越大振荡越厉害怎么调都压不下去。坐标映射上我用了一个简化假设舵机转角和平台倾角近似线性。在±15度的摆动范围内这个假设误差很小。所以PID输出的角度误差直接乘一个“像素到脉宽”的比例系数再叠加到中位值上就是最终PWM比较寄存器的值。3.5 悬臂结构的非线性和死区为什么平台边缘比中心难控制如果平台是用两个舵机通过悬臂直接支撑的你会发现在平台中心附近控制非常灵敏边缘区域却有些“迟钝”。这是因为悬臂结构在水平附近力臂最长、最灵敏而倾斜角度大了之后力臂变短同样的舵机角度变化引起的平台坡度变化率下降了反映到控制上就是增益变小。解决思路有两个层面。机械层面尽量把平台的重心设计得低一点减少悬臂末端的形变控制层面我在代码里做了增益补偿根据球的当前位置距离平台中心的距离对外环Kp做了一个动态缩放。靠近中心用1.0倍靠近边缘降到0.7倍相当于提前把机械非线性掰回来。当然前提是球的坐标你得有这正是视觉系统给到的红利。4. STM32裸机PID实现代码结构与控制时序4.1 为什么用裸机不直接上RTOS这个项目也有人问我为什么不用FreeRTOS。我的理由很简单整条控制的逻辑就是“定时采样、算PID、输出PWM”单一任务周期固定裸机用定时器中断完全能跑出微秒级的确定性。RTOS适合多任务、需要阻塞等待的场景在这里只会引入优先级翻转和调度抖动纯属给自己找麻烦。裸机不是落后是匹配场景的简洁。4.2 控制时序用定时器中断做稳定的控制心跳我配置TIM2产生10ms的更新中断也就是100Hz的控制频率。每次中断里的工作流程是从串口DMA缓冲区取出最新的目标坐标如果有新数据用当前球坐标计算位置误差执行外环PD得到期望速度执行内环PID得到平台倾角指令将倾角指令换算成两个舵机的PWM脉宽更新TIM1的比较寄存器输出舵机PWM这个10ms的周期是所有控制运算的基准。注意同一周期内采样、计算、输出必须完成不能等到中断外再慢慢算否则下一次中断来时上次还没算完时序就乱了。4.3 位置式PID vs 增量式PID怎么选工程上最常见的是位置式和增量式两种。位置式PID直接算完整输出量适合做绝对位置控制增量式算的是输出变化量每次只是在当前值上叠加上一步的增量适合航模舵机这类“位置保持型”执行器。平衡球系统对舵机输出的是角度用位置式更加直观但必须做抗积分饱和。否则球停在目标点附近时因为有静差积分项会一直累加一旦累加值过大舵机就会狂转。很多“突然爆炸”的失控现象都是积分饱和造成的。关键代码骨架如下typedef struct { float kp; float ki; float kd; float integral; float last_error; float out_min; float out_max; float integral_limit; } PID_t; float PID_Update(PID_t *pid, float target, float measurement) { float error target - measurement; // 积分分离误差太大时不积累积分 if (fabs(error) pid-integral_limit) { pid-integral error; } else { pid-integral 0.0f; } // 积分限幅 if (pid-integral pid-out_max) pid-integral pid-out_max; if (pid-integral -pid-out_max) pid-integral -pid-out_max; float derivative error - pid-last_error; pid-last_error error; float output pid-kp * error pid-ki * pid-integral pid-kd * derivative; // 输出限幅 if (output pid-out_max) output pid-out_max; if (output -pid-out_max) output -pid-out_max; return output; }这版代码里有两个容易忽略的细节。一个是积分分离当误差超过设定的阈值时直接清零积分防止球离目标很远时积分猛涨一个是积分项单独限幅而不是等累加到输出限幅才截断。后者更精细能防止积分恢复时造成很大的冲击。4.4 串口调试没有实时曲线你就是在盲调裸机上的PID调参特别依赖调试通道。我强烈建议至少把以下数据周期性通过串口打印出来目标X、实际X、目标速度、实际速度、内环输出。用PC端一个简单的串口绘图工具画实时曲线。看着曲线调参数和只看舵机乱摆效率完全是两个层次。我的做法是每50ms输出一帧调试数据格式是t123 x12.3 vx1.2 out0.5这种纯文本方便PC端解析画波形。调参的时候看着“位置曲线”和“速度曲线”的形态对比远比单纯盯着球看更能判断系统状态。5. 参数整定与联调kp ki kd从拍脑袋到能用的方法5.1 调参前的准备工作先验证执行机构和方向参数整定之前先把一个前提确认掉舵机中位准确、方向正确、平台在零位时球不会自己跑。我一般先把球放在平台中心系统上电不启动PID只观察球是不是静止。如果球自己慢慢滑向一边说明平台水平没调好或者视觉零点偏移这个时候去调参数怎么调都不会稳。另一个步骤是手动验证执行机构。通过调试命令直接给舵机一个固定倾角比如“X轴10度”观察球向X正方向滚动然后再给“X轴-10度”球能反向滚回来。这是开环测试确认方向正确后再进入闭环调参。5.2 临界比例法起步先拿到一组能用的初值用齐格勒-尼科尔斯临界比例法可以快速拿到一组不离谱的初始参数。操作方法是先把内环的kd和ki设为0然后逐渐加大kp观察系统是否会开始等幅振荡。当球在目标点附近出现不会衰减的轻微振荡时记录此时的Kp_crit和振荡周期T_crit。根据这两个值查表得到初始PID参数控制器类型KpKiKdP0.5 × Kp_crit--PI0.45 × Kp_crit1.2 × Kp_crit / T_crit-PID0.6 × Kp_crit2 × Kp_crit / T_critKp_crit × T_crit / 8实测下来临界比例法给的值偏保守但作为初始值非常合适比拍脑袋强太多。在这个基础上微调比从零开始摸参数省一半时间。5.3 我的实际调试路径P - PD - PID 分步走我不建议一上来就三个参数一起调。我的路线是“先P、再加D、最后补I”。第一步只保留P。把kp从0慢慢往上加观察球在受到扰动后的响应。如果球缓慢爬回目标点但晃来晃去说明P能推动系统但阻尼不足。此时P大概在1.0~2.0之间。第二步加D。D的作用是“预测偏差变化趋势”偏差在减小时给一个反向修正抑制过冲。加到系统能够在2~3次衰减振荡内收敛。D不能加太多加了之后球反应变得迟钝感觉“黏黏的”那就是过头了。第三步补I。I用来消除静差。球停在目标点很近但就是差那么1cm不动就是积分不够。从很小的值比如0.01开始加加到球能缓缓爬完最后1cm且不会出现低频往复漂移为止。最终我这套机械结构上用的参数大致是外环Kp2.0、Kd0.3内环Kp1.2、Ki0.08、Kd0.15。再次提醒这个参数是特定机械结构下的结果不能照抄。换了舵机、换了球、换了平台尺寸都要重新整定。5.4 常见异常现象与处理一张表对号入座调参过程中最怕遇到“看起来不对劲但又说不清哪不对”的情况。我把常见现象列个表方便对号入座异常现象可能原因处理思路球在中心附近高频抖动Kd过大或视觉噪声太大降低Kd或加大坐标滤波球围绕中心低频往复振荡Kp过大或Ki过大先减Ki再减Kp球能回来但总是差一点停不住外环Kp偏小刹车不足增大外环Kp或Kd球停在目标点附近但始终有1cm静差Ki太小逐步增大Ki只在某一侧方向过冲明显平台不水平或透视标定偏差检查机械水平、重新标定角点突然失控舵机打满积分饱和或数据丢帧检查积分限幅和串口软错误处理5.5 一个容易忽略的细节控制周期与视觉更新周期不同步上位机以30fps发送坐标但STM32以100Hz运算PID。这意味着10ms内可能收到0帧到1帧不等的坐标数据。我的做法是STM32里维护一个“最新坐标”变量每次串口收到数据就更新它而PID计算永远只读这个变量的当前值。两次坐标更新之间控制系统用的是上一次的旧坐标相当于零阶保持。这个方案简单有效但也带来一个问题如果上位机卡顿或串口丢包超过一定时间没有新坐标旧坐标会让球“盲开”。我加了一个看门狗逻辑超过60ms没有新坐标就自动把平台回中防止球冲出平台摔下去。这是很朴素但很重要的安全保护。6. 联调实测与三个值得反复说的问题6.1 整机联调能跑出什么效果把整个系统接起来之后我把目标点设在平台中心让球从边缘释放测得的结果是球在大约1.5~2秒内回到中心会有一到两次衰减过冲最终稳定在目标点正负2cm以内。如果目标点设在一个偏移位置球也能稳定过去说明系统是可跟踪的。这时候的成就感很强但联调阶段暴露的三个问题才是最值得记下来的经验。6.2 坑一摄像头帧率与控制频率之间隔着一条延迟河最初我天真地认为OpenCV有30fps串口也在推STM32跑在100Hz整条链路应该很跟手。实际测试时发现从球滚动开始到舵机有反应中间有明显的“迟钝感”。逐段排查之后发现OpenCV处理一帧图像加上绘图、窗口显示等操作实际有效帧率只有15~20fps也就是说坐标更新间隔可能到50~60ms。这个延迟导致的问题是球已经滚出一段距离系统还拿半秒前的位置在算PID控制动作永远滞后。解决办法有两个层面。一是极简处理循环检测和标定之外不去做任何多余图像处理不保存视频、不实时显示窗口或者显示降采样后的图把有效帧率拉回30fps以上。二是在STM32端对坐标做一次轻量预测x_predict x_current vx * predict_timepredict_time我设成20ms相当于往前补偿一帧半的延迟。这个补偿明显减轻了滞后感系统收敛变得干脆很多。6.3 坑二光照变化让HSV阈值瞬间失效这个坑几乎每个人都会遇到。上午调好的阈值下午太阳从窗户侧面照进来球表面出现一条高光带高光区域的饱和度大幅下降不再落在HSV阈值范围内检测出来的轮廓变成两个月牙质心偏移到球的边缘。更麻烦的是质心偏移会导致PID认为球位置偏了平台会去修正一个实际不存在的误差。我的处理分三层检测轮廓时先做闭运算把小的高光空洞填上在平台外固定一个区域作为背景采样每隔一段时间动态刷新HSV阈值范围让阈值跟着环境光缓慢变化如果轮廓面积突然低于正常范围比如球的正常面积是5000像素现在只有800像素直接判为目标丢失进入安全模式回平而不是用残缺数据算PID。最根本的解决办法还是遮光。我给摄像头周围加了一个遮光罩并用了漫反射光源照明整套系统的光照环境稳定之后视觉的可靠性大幅提升。视觉检测稳定永远是PID能调好的前提。6.4 坑三PID参数在平台不同区域表现不一致联调后期我发现目标点设在平台中心球很听话但把目标点设到平台角落球老是回不去或者回去后明显更抖。排查之后发现两个原因。第一是透视变换的边缘区域虽然校准过但球在这个区域运动时像素坐标的噪声天然比中心区域大——因为同样的实际距离边缘区域的像素分辨率更密还是更疏取决于镜头和变换的插值方式。第二是悬臂结构在倾斜角度大时增益下降同样的PID输出边缘区域产生的加速度小于中心区域。我没有追求在全平台范围都用同一组参数而是做了简单的增益调度。根据球的实时坐标计算它到平台中心的距离r然后用一个系数去缩放外环的Kpfactor 1.0 - 0.3 * min(r / R_max, 1.0) Kp_effective Kp_base * factor也就是说离中心越远外环增益越小。这看起来和常理相反但在悬臂结构下实测有效——它抵消了机械非线性带来的“边缘过敏感”倾向。如果未来换用步进电机或者直线驱动结构这个调度可能就不需要了但理解这种非线性的来源是玩好这个项目的关键。6.5 后续还能怎么扩展平衡球机器人跑通之后往上扩展的方向非常丰富。我自己的路线图是先加轨迹跟踪让目标点按圆形或者8字轨迹缓慢移动球能跟着走这对系统带宽和相位裕量的要求更高然后尝试把视觉移植到MCU端用摄像头模块直接输出坐标彻底摆脱PC和串口再往后可以换成更高精度的步进电机或者把平台换成球碗结构玩法又会不一样。每一步都会逼你去更深地理解视觉和控制之间的配合。最后分享一个个人小技巧调参的时候永远把目标点设成上一次调的参数不太容易稳定的位置而不是只放在平台中心。中心区域是最容易“骗人”的很多参数在中心看起来完美换到角落就露馅。你先在困难区域把参数调到能稳定再回到中心验证这样得到的参数在全平台都有更好的鲁棒性。
返回列表