ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AGV项目实战:从运动控制到多车调度的避坑心得

AGV项目实战:从运动控制到多车调度的避坑心得 AGV小车这个项目做下来最深的感受是网上能搜到的A*算法教程一大堆但真正让AGV在车间里稳定跑起来、不撞人不撞车、不把货物送错工位靠的从来不是算法本身多漂亮而是工程上那些没人爱写进文章里的细节。这篇心得不聊空话就把我从底盘搭建、运动控制、路径规划到多车调度一步步踩过的坑和验证过的方案摊开说给准备入坑AGV或者正在被AGV折磨的朋友一个参照。1. 立项前先回答三个问题再谈选型很多人做AGV项目上来就研究导航算法、选激光雷达我觉得顺序反了。AGV本质上是给业务流程服务的运输工具技术上的所有选择都应该由使用场景倒推出来。我在项目启动阶段只问三个问题这三个问题的答案直接决定了后面所有技术选型。第一个问题运输路线未来会不会频繁调整。如果产线工位半年挪一次磁条导航基本可以不考虑贴磁条好贴但撕磁条重贴能把人烦死而且磁条区域地面灰尘多了容易丢信号现场维护成本比你想象的高很多。如果路线基本固定磁条反而是最稳的方案之一。第二个问题对停靠精度的要求到底是几厘米。对接充电桩和对接机床上下料对精度的要求完全不是一个量级前者正负一两厘米足够后者经常要求正负五毫米以内这直接影响是选二维码还是选激光SLAM。第三个问题现场有没有稳定的环境特征。激光SLAM听起来高级但要是车间里全是玻璃墙、大面积白墙、堆料区天天变激光雷达扫出来的特征点飘得你怀疑人生。这三个问题不确定后面都是瞎忙。我见过有人为了上激光SLAM硬改产线布局最后成本翻倍效果还没磁条好纯粹是拿技术方案倒逼业务需求方向反了。技术选型上我把主流的几类方案拉了张对比表实际测试的数据填进去差别就很直观了方案典型精度路线柔性现场改造环境敏感度单机成本量级磁条导航±10mm无需重贴高低但怕灰尘压痕低二维码导航±5mm中需贴码中中码脏了就丢中激光SLAM±10mm~±50mm高软件改即可低高动态环境容易飘高视觉SLAM±20mm~±50mm高低高光照影响大中高磁条方案精度看着还行但那是理想条件下的。我实测在环氧树脂地面上磁条用半年后边缘起翘读头偶发误判直线还好转弯处经常把车头甩偏。二维码方案精度最高但产线灰尘大的地方码片一个月不擦就开始丢帧。激光SLAM室内静态环境能用动态环境装完还得花大力气调参数。选哪个完全取决于你愿意为哪一种缺点买单。1.1 运动学模型决定底盘下限底盘运动学模型是最容易被低估的环节。很多入门资料默认AGV是差速驱动左右两轮独立驱动就能转能走但真到现场你会发现差速模型在地下停车场那种大平面好使在窄巷道货架区就不太够看了。差速底盘转弯半径为零可以原地转但转的时候扫过的面积大巷道宽度不够就蹭货架。舵轮底盘比差速底盘灵活性和直线循迹能力更好但机械结构和控制复杂度上了一个台阶。舵轮要同时控制转向角和驱动速度两个自由度的协调一旦没做好低速走直线都会画龙。我做第一版的时候为了省成本用了差速底盘结果货架间距只有一米二AGV宽度八十厘米原地转向时车尾扫到货架边角最后硬是把几个转角处的货架挪了位置才解决。选运动学模型之前先拿CAD把AGV的最小转弯半径、车体扫掠区域、巷道宽度三个参数对着场地排一遍这一步省不了。2. 底盘搭建与运动控制直行不偏才是第一道坎底盘装完第一个拦路虎不是导航是让车走直线。AGV动不动就要求走二十米不偏五厘米但车本身是两侧电机各自驱动左右轮的实际轮径差、电机的转速差、地面的滑移差异任何一个不匹配都会让车跑出弧线。我第一版用的是两个直流减速电机加霍尔编码器开环控制下走十米偏了快半米完全不能看。闭环之后好很多但PID参数一开始是照着网上示例填的结果车走起来要么抖动要么响应迟钝。后来自己写了个分段测量脚本让车以固定PWM跑十秒记录编码器数据换算成左右轮实际线速度发现问题出在左右减速比出厂一致性不行左边轮子实际直径比右边小了接近百分之三这个误差在PID里是作为持续扰动存在的比例项一直要顶着修正稍微有点延迟就画龙。处理办法很简单在控制逻辑里加了一个轮径补偿系数以右轮为基准左轮速度乘以0.97二十米直线偏差直接从三十厘米压到五厘米以内。这个系数看起来不起眼但对直线稳定性贡献比调PID参数大多了。2.1 PID参数不能照搬必须现场实测PID整定这块说句得罪人的话网上那些“通用参数”基本只能用来启动不能用来上线。AGV的运动控制本质上是在跟踪一条期望的速度曲线电机本身的响应延迟、减速箱的齿隙、地面摩擦变化都会影响整个回路的动态响应。我用的是工程上最快的方法先只加比例项从小到大逐步加等车开始出现轻微震荡再把P往回退百分之二十然后加一点积分项消除稳态误差微分项在电机编码器噪声比较大的时候不要贪多加多了反而放大振动。实测下来一组可以参考的初始值差速底盘直行速度1.2m/s时速度环Kp在0.8~1.2之间Ki在0.05~0.1之间Kd先设为零起步。注意这个数值换了底盘、换了轮子、甚至换了地面摩擦环境都可能要重新调。现场调PID要有耐心每次只改一个参数改完跑一组直线记录数据别指望一步到位。2.2 里程计标定与轮胎打滑问题里程计是AGV定位的底座航向角短期靠陀螺仪位置增量就靠编码器。但编码器测出来的是轮子转了多少圈不是车实际走了多远中间差一个轮径参数而这个参数会随着胎压、磨损、载重变化。我做过一次实验满载和空载状态下同一条路径跑下来里程计累计误差能差出百分之二左右十米就偏二十厘米这还没算打滑。标定里程计的方法不复杂让AGV沿一条已知长度的直线跑比如二十米记录编码器累计脉冲数算出一个实际的“每米脉冲数”替换掉出厂理论值。重点是要做往返双向各一次取平均值因为地面摩擦力在不同方向上有微小差异。不过标定只能解决静态误差打滑是动态的AGV急加速急减速的时候轮子跟地面之间会有滑移编码器照样转但车没动那么多。所以运动控制上要加加速度约束不要让AGV突然冲起来我设的默认加速度上限是0.5m/s²转弯的时候进一步降到0.2m/s²虽然慢一点但定位数据干净很多。3. A*算法从理论到AGV实车真正落地时在调什么A*算法本身不多讲了栅格地图上加启发式搜索目标函数是g(n)h(n)。但理论到实车之间有四个坎每一个都能让跑得好好的Demo在车间里翻车。3.1 栅格地图精度与膨胀半径怎么定栅格大小是个充满诱惑力的参数。格子设小了地图分辨率高路径精度好但搜索节点数翻倍暴涨格子设大了路径计算快但AGV实际走线会受到量化误差影响。我最后选的栅格尺寸是5厘米和AGV自身定位精度一个数量级再小意义不大。但真正影响安全的不是栅格大小是膨胀半径。A*规划出来的是理想路径如果直接把车体当成一个点在地图上搜搜出来的路径会贴着障碍物边缘走车体实际扫掠区域直接撞上去。膨胀半径至少是车体最大外接圆半径加5厘米安全余量我的车半宽35厘米膨胀半径一开始设了40厘米结果在窄巷道里根本搜不出路径因为两侧同时膨胀之后中间可行宽度变成了零。调试就是把膨胀半径和实际巷道宽度对着算在可通行和安全之间取平衡。3.2 启发函数对搜索效率的影响实测启发函数选曼哈顿距离还是欧氏距离网上争论很多我的实测结论是栅格地图四连通就走曼哈顿八连通就走欧氏或切比雪夫因为启发函数必须和实际移动代价一致才不会过度低估。曼哈顿距离在八连通地图下会高估代价导致A*虽然不会搜索出错误路径但扩展节点更多、更慢。我在一张两百乘两百的栅格地图上做过对比同样起点终点四连通用曼哈顿距离扩展节点数大约三千个用欧氏距离扩展了五千多个八连通反过来欧氏距离约两千曼哈顿要三千五。搜索时间差异在单机上只有几十毫秒但如果你搞的是多AGV在线重规划这个差异会累积能省则省。还有一个小技巧双向A在这个场景下能用但收益有限除非地图特别大一般单AGV规划用双向搜索容易引入额外调参成本收益不明显。我把更多精力放在了分级规划上全局用A找一条可行路径局部用DWA做避障。全局路径不需要每帧重算局部动态避障才需要高频更新这个分工实测下来既稳又省算力。3.3 路径平滑与拐角减速A*搜出来的是栅格中心点的折线路径车是按这个路径走的但折线拐角处如果不做平滑AGV到拐点需要原地调整航向又慢又丑还容易把货物甩歪。我的做法是做二次贝塞尔平滑控制点取折线角点两端各一个栅格长度的偏移平滑后的轨迹在仿真里看着很自然但要注意平滑轨迹可能切进障碍物所以平滑后要做一次碰撞检测过不了就在拐点处加大转折半径。更工程化的处理是给每个拐点标注一个期望过弯速度直线段跑1.2m/s曲率大的弯道降到0.3m/s曲率小的弯道0.6m/s。这样既保护了定位精度又不会让货物在托盘上滑移。速度规划表和路径本身一起下发给运动控制模块算是我这个项目里性价比最高的一项投入。4. 三辆AGV协同调度让A*路线真正跑起来一开始做多车调度的时候我天真地以为每台车各自跑各自的A就行反正地图一样、起点终点不一样路径自然不一样。结果是三台车在交叉口附近频繁互相赌住两个A各自认为自己的路径最优但在物理世界里路径共享路段谁走谁不走必须有个仲裁机制。这个“多条AGV各自A规划”的场景正是网上说的“三条AGV基本A算法”刷屏背后的真实需求。4.1 多车共享地图时的资源分配我的做法是把地图分成若干路段和路口节点每段路在任意时刻只允许一台AGV占用这就是最简单的资源锁。AGV在请求路径前先把规划路径映射成一系列路段资源向调度中心申请调度中心检查这些路段状态空闲则分配给该车占用则让该车等待或重新规划绕行。这个方案实现简单但有个问题如果两台车在交叉路口同时申请对方占用的路段互相等对方释放直接死锁。我的解法是给所有路段加一个全局唯一编号AGV申请资源时必须按编号从小到大按顺序申请如果申请不到就释放已占用的所有资源退回到安全点重新规划。这个策略牺牲了一点效率但彻底消除了循环等待多车系统里安全永远在效率前面。资源锁的粒度也值得琢磨。一开始我按整条路径锁两车起点终点相近的时候第二台车要等第一台车完全跑完才能出发效率太差。改成按路段粒度锁之后一台车用过的路段可以立即释放给后面的车重叠路径短的时候吞吐量提升非常明显。具体路段划分要根据现场路网的拓扑结构来交叉口和窄巷必须独立成段长直道可以整段锁。4.2 动态绕障先停再绕别急着重规划AGV跑着跑着前面冒出来一个人或者一个托盘是现场最常见的情况。运动控制层的避障雷达检测到障碍物先把车刹停然后才轮到路径规划层做决策这个顺序一定要固定下来。我见过反着做的系统规划层还在算绕行路径车还在往前冲障碍物越来越近最后急刹刹得托盘上的料都歪了。停车之后怎么处理也分等级如果障碍物在几秒内消失比如行人路过在原地等待然后继续原路径就行超过设定阈值比如十秒还没消失才触发全局重规划。重规划有两种策略一是把障碍物区域加入代价地图让A*绕过去二是查一下当前点和目标点之间有没有备选路径缓存用备选路径直接换线。我实际用的是代价地图方案灵活但有个坑障碍物消失之后一定记得从代价地图里移除不然过一会儿你会发现AGV对着空气绕了个大圈。4.3 死锁案例与超时看门狗多车调度上线之后死锁就是迟早的事。我遇到过一次典型情况A车要从东到西B车从西到东两条路径在一个狭窄巷子里交汇巷子窄到两车无法错车A车锁了巷子东端B车锁了巷子西端谁也不让谁。调度中心的锁策略是“一次性申请全部通过才分配”导致A车持有东端等西端B车持有西端等东端完美循环等待。解决死锁不能全指望算法层面预防现场还要加看门狗。我给每台AGV的每个任务加了最大执行时间超过时间没有完成就触发任务重启、释放所有锁回到最近的避让点重新规划。那次死锁之后我又在调度逻辑里加了路径方向标识同一巷子双向路径不允许同时存在规划路径实际是通过把巷道变成单行线的方式规避了这类问题。5. 定位与导航方案现场实测对比定位方案我前面提过一嘴这里说细一点。AGV的定位大概分三层全局定位我在哪、局部定位我在路段的哪个位置、停靠定位是否到了工位。不同层用不同传感器不要指望一个传感器通吃所有场景。激光SLAM做全局定位很自然雷达扫描环境特征和预先建好的地图做匹配。但车间这种场景最大的敌人不是精度是“环境一致性”。上午和下午阳光照进来的角度不同堆料区位置一变激光点云匹配就可能出偏差。我碰到过一次很邪门的问题车走过一段玻璃幕墙旁边时定位突然跳变了几十厘米分析半天是玻璃反射造成虚假点云地图匹配把假特征当真了。解决办法是给激光点云加一个反射强度过滤器把反光异常强的点直接剔除然后定位才稳定下来。另外雷达安装高度也会影响太低了会扫到地面杂物太高了会扫不到货架低矮部位我装在35厘米左右刚好。二维码导航是另一种思路地面贴码摄像头识别码的编号和位姿偏差来修正定位。它的优势是确定性强看到码就知道自己在哪没有累积误差。劣势也明显码脏了、被叉车压变形了、被托盘挡住了就抓瞎。我的建议是二维码用于工位停靠和走廊关键点的修正不要让AGV全程依赖二维码跑中间路段里程计加陀螺仪推算到码附近再修正一次这样既能保证精度又减少二维码维护频率。视觉SLAM我也测过一轮优点是硬件便宜一个摄像头就行但车间光照变化、反光地面、货物纹理干扰都会影响特征点提取稳定性不如激光。视觉方案在仓储场景能用的前提是光照可控、货架特征丰富达不到这个条件还是老实上激光加二维码结合。6. 项目复盘哪些模块值得深做哪些是过度设计项目收尾回头复盘有几件事如果重新来我会做得更早也有几个模块是纯粹浪费时间的过度设计这里都列出来供大家参考。6.1 真正扛住现场运行的东西稳定性和可复现性才是现场运行的关键。我把项目的核心模块按“抗不抗造”打分得分最高的是轮径补偿加分段速度规划的底盘控制、带超时看门狗的资源锁调度、反射强度过滤后的激光定位。这三个模块没有特别花哨的技术但每一个都在现场被摩擦过几百小时修修补补之后才稳定下来。项目做到后期新功能上线顺序我都会排一下凡是动这三个核心模块的改动必须走完整回归测试不测宁可不放。这三个模块在仿真环境的验收结果很好但真正让它们可靠的是现场追溯日志。6.2 过度设计清单反思一下有几块设计属于过度投入。第一是仿真环境搭建花了两周时间在仿真里做了各种极限工况模拟结果现场工况的复杂度远超仿真很多问题根本是机械摩擦、地面不平、通讯延迟这种仿真近乎完美的东西仿真做得再漂亮对现场帮助有限。第二是自研调度算法一开始想着做一个基于时间窗的完美调度算每条路径的时间窗冲突结果车辆多了之后计算量暴涨调度器成了瓶颈。后来换成简单的锁实现系统反而更稳更易排查。不是说时间窗高级算法不好而是小规模场景用不着。第三是语音提示和指示灯联动这部分花哨但没有产生实际价值工人根本不会看灯他们只关心车走没走对路。有这个功夫不如给AGV加一套好用的电池管理系统电量少于百分之二十能自己回充电桩这比什么提示都实在。6.3 日志系统是后期调试的命根子AGV项目的软硬件耦合很深问题往往是“这次没复现”“重启又好了”没有一套扎实的日志系统根本没法排查。我做的日志系统记录五个维度的内容时间戳统一用毫秒级单调时钟不能跨系统存在偏差位置状态是X、Y、Theta、当前路径点和目标路径点控制指令是期望速度、实际速度、PWM输出、PID各环节值传感器状态是激光雷达、二维码、超声波的当前读数和健康状态事件记录是路径切换、锁申请与释放、障碍物触法和看门狗重启。每条日志都带编号压到本地SD卡断电不丢失后面再上传服务器。有一次AGV在过弯时突然偏离路线撞到货架排查时靠日志还原了现场陀螺仪数据在过弯前两百毫秒出现异常抖动里程计速度曲线正常但航向角突变对比日志才发现是电机驱动板的PWM频率干扰了陀螺仪的I2C通信。没有这套日志系统这个问题想排查出来基本靠猜。写在最后AGV项目做得越久越觉得这个行业的技术门槛不在某单个算法或者某一个硬件上而是把机械、控制、感知、调度、现场工程全部捏合在一起的能力。A*算法三天能看懂底盘调通要三星期多车稳定跑三个月。如果你正准备做AGV我的建议是先从单机走直线调到稳再做精确停靠然后加避障最后才碰多车调度每一步都验证扎实再往下走不然出了问题你根本不知道该怀疑哪一层。最后分享一个我踩过几次坑才记住的小技巧AGV项目的问题复现率低所以在任何一次现场调试之前先把日志系统和录屏打开。一个问题如果第一次出现时你没留下数据后面大概率要花三倍的时间去重现它。数据比直觉可靠日志比记忆可靠。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进