TRACE 的赛道包含没有引导标记的直线和带黑线的圆弧。这个条件决定了控制器不能始终依赖同一个观测:直线上,灰度阵列可能看不见任何线;圆弧上,单纯保持航向又会把车带离曲线。任务首先是判断当前该相信哪一种参考。
真实工程使用 TI MSPM0G3507。现有源码把 MPU6050 航向、八路灰度和双轮编码器放进同一条控制链,但它们回答的问题不同:车朝哪里、黑线偏在哪里、两只轮子实际转得怎样。将这些问题分开,调参时才不至于只盯着电机输出。
方向可以换参考,速度保留共同反馈。
直线段根据目标航向与当前偏航的差形成方向修正,圆弧段改用灰度偏差。外环输出分配到左右轮目标速度,再由各自编码器速度 PID 产生电机输出。两种方向模式共享速度内环,便于区分“方向判断不对”和“轮子没有跟上目标”。
先知道有没有线,再讨论线偏了多少。
八路灰度先按白底、黑线参考归一化,再用左右权重求偏差中心,权重为 −40、−25、−12、−4、4、12、25、40。PID 误差计算在总信号不足时进入保护,节点在线条件另看数字通道位。两种判断有关联,却不是同一个门限。
校准同样是控制结构的一部分。当前流程每路采 32 轮,剔除两端各 4 个值,用剩余 24 个值求均值。它帮助处理通道差异,但仍依赖实际地面、光照与安装高度,不能让一组默认值适用于所有场地。
路线走到哪,和当前怎样控制,是两件事。
Car.c 用 car_mode 与 car_node 组织任务和节点,再用 pid_control_mode 选择航向、循迹或纯速度控制。节点切换还伴随距离、PID 和丢线计数复位。这样路径次序与控制器选择可以分别阅读,也能解释停车和丢线阶段为什么改变输出方式。
下面只压缩控制来源的选择,是根据工程整理的 JavaScript 示意,不是原样固件,不能直接烧录。真实状态机包含不同任务分支、距离门限、连续丢线判断与圈数逻辑,不能用这几行替换。
// 整理示意;不输出 PWM,不包含完整路线状态机。
function directionSource(segment, lineValid) {
if (segment === 'straight') return 'heading';
if (segment === 'arc' && lineValid) return 'line';
return 'task-specific-transition';
}切换的不只是一个标志,也包括上一段留下的控制状态。
写给实践时的自己
把切换边界单独拿出来观察。
弧线出口附近可能短暂丢线,源码用连续计数避免一次读数就切换;某些末段丢线时先切纯速度环减速。不同分支有不同处理,因此“丢线就保持上一输出”或“丢线立即换到航向”都不足以概括整份工程。
- 单模块:核对电机与编码器方向、IMU 与灰度数据。
- 单路段:观察航向误差或灰度偏差,以及两轮跟随。
- 切换处:记录节点条件、复位动作和短暂丢线。
- 整圈:再看停车、多圈漂移与重复性。
设计报告的实车结果表仍待补充,现有源码只能说明框架与策略,不能推出停车误差或比赛成绩。本文没有重新构建、烧录和跑车。后续记录应把版本、校准、场地与每次现象放在一起,让调参能够回到具体路段,而不只剩一组最终数字。
写下来,是为了下一次更快找到线索。
返回文章列表