循迹机器人模拟器:在浏览器里调校机器人
在交互式的浏览器机器人模拟器里搭一台虚拟循迹机器人,把它各路传感器的读数可视化,再动手整定它的 PID 控制器。
- 类别
- Arduino
- 时长
- 45–90 分钟
- 平台
- 浏览器 · Arduino
01 / 从这里开始
简介
循迹机器人把传感器读数转换成转向修正。在这个项目里,你可以画一条赛道,改变机器人和传感器的几何布局,然后实时观察一个确定性的 PID 控制器如何作出响应。用它把控制理论与你在实体赛道上看到的 Arduino 机器人的行为联系起来。
Live lab / Deterministic 60 Hz model
Line follower simulator
Run the starter track, tune the controller, or pause and draw a course of your own.
Bright nodes are sensors currently detecting the track. The lavender heading line shows steering output. Drawing pauses the robot automatically.
- Elapsed
- 0.0 s
- Distance
- 0 units
- Line error
- 0.000
- Steering
- 0.000
- Track contact
- 100%
Keyboard: focus the course, then use Space to run/pause, N to step, R to reset, D to draw, and F for full screen.
控件
用赛道预设建立一个基线,或者暂停运行、直接在赛道上画线。机器人速度决定底盘每次更新前进多远。传感器数量和间距改变视场。P、I 和 D 控件改变转向响应;单步在暂停状态下推进一次确定性的更新。
从中等速度、五个传感器和默认增益开始。一次只改一个变量,然后比较误差、单圈时间和在轨时间这几个指标。
原理
传感器条在机器人前部横向采样反射率。每个处于激活状态的传感器都把它带符号的位置贡献给一个加权平均。传感器条的中心是误差零点;中心左右两侧的读数分别产生负误差和正误差。
控制器把三项组合起来:
$$u(t) = K_p e(t) + K_i \int e(t)dt + K_d \frac{de(t)}{dt}$$
修正量 $u(t)$ 让一个轮子加速、另一个轮子减速。比例控制对当前的偏移作出反应,积分控制修正持续存在的偏置,微分控制则抑制快速的变化。
算法
- 以固定间隔对每个传感器采样。
- 计算加权线位置,并围绕中心做归一化。
- 当所有传感器都丢失赛道时,复用上一次观测到的线方向。
- 用同一个固定时间步更新积分项和微分项。
- 把修正量限幅,算出左右电机指令,并对机器人位姿做积分。
先把比例增益整定到机器人能跟上缓弯,再加微分增益直到振荡平息,最后只引入刚好足以消除可重复偏差的积分增益。
源代码
浏览器模拟器和单片机用的是同一种控制结构。一个紧凑的 Arduino 风格循环长这样:
float integral = 0.0f;
float previousError = 0.0f;
void controlStep(float dt) {
float error = readWeightedLinePosition();
integral = constrain(integral + error * dt, -2.0f, 2.0f);
float derivative = (error - previousError) / dt;
float correction = kp * error + ki * integral + kd * derivative;
setMotorSpeeds(baseSpeed - correction, baseSpeed + correction);
previousError = error;
}
真实的控制间隔要保持稳定。可变的延迟即使在增益不变的情况下,也会改变微分项和积分项。
假设与硬件差异
这是一个教学模型,不是硬件的复刻。赛道是一张平整、高对比度的二值掩膜,
没有环境光变化,所以传感器条看到的是完美的黑白——而在真实的胶带上、
房间照明、表面反光和传感器高度都会改变读数,你必须按接线说明里的步骤
逐项标定。时序是理想的:控制器以固定间隔运行,没有 delay() 抖动,
而真实的 Arduino 回路会随其他工作而变化,那种抖动会重塑 PID 响应。
底盘是运动学的:轮子从不打滑,电机瞬时响应,电池电压不塌陷。
把在这里找到的增益当作一个接近的起点,标定之后再到真实机器人上重新整定。
电路图
把传感器输出接到支持模拟输入的引脚上,各模块之间共地,并且通过 H 桥 而不是直接用控制器引脚来驱动电机。
确认电机电源的额定值,并在控制器和驱动器附近加上局部去耦。 绝不要让电机电流流经开发板的逻辑稳压器。
引导实验
下面每一个都只隔离一个变量——而在真实硬件上所有东西同时变化, 这正是真正困难的地方。
1. 找出临界增益,然后减半
把积分增益和微分增益设为零,提高比例增益直到机器人在直道上 稳定地振荡——以恒定的幅度左右蛇行摆动,而不是越来越大或越来越小。 把这个数值减半。
现在你手上有了一个来自测量、而不是猜测的起始 Kp,而且它会很接近。
从那里开始加微分,直到这种摆动被压掉。
2. 证明增益依赖于速度
先把机器人整定到在低基础速度下能干净地跟踪。现在把速度提高一半, 什么都不改,用同样的增益跑一遍。
它会左右摆动、会切弯、或者会丢线。控制器一个字都没变——但同一个 转向修正现在每单位赛道产生更大的航向变化,所以有效增益随速度上升了。 每一组整定都是在某个特定速度下的整定,这正是竞赛机器人 在弯道前减速、而不是全程用一个增益的原因。
3. 观察传感器数量如何改变可能性
用三个、五个和八个传感器,在同一条赛道、同一组增益下各跑一次。
| 传感器数量 | 位置信号 | 对整定的影响 |
|---|---|---|
| 3 | 粗略,实际上只有三个区域 | 能跟线,但没法整定得很紧——误差被量化了 |
| 5 | 足够平滑,可以做比例转向 | 通常的甜蜜点 |
| 8 | 精细 | 允许在振荡之前用更高的增益和更高的速度 |
有意思的结果是:更多的传感器抬高的是上限,而不是改善下限。 在低速下三个传感器就够了。多出来的分辨率只有在那些“粗糙误差信号 成为限制因素”的速度上才开始回报。
4. 在急弯处故意把它弄坏
把速度提上去,直到机器人在最紧的弯上丢掉线。看看它接下来做什么。 然后想想真实机器人应该做什么:径直往前开是最差的选择,因为 线正在拐弯离开。
这就是丢线时保持上一次误差而不归零背后的推理——零意味着“居中”, 那会指令全速直行。保持上一次的误差,会让机器人继续朝它已经在转的 方向转,而那正是线去的方向。
你应该观察到什么
| 图上的现象 | 原因 | 修法 |
|---|---|---|
| 直道上稳定左右摆动 | Kp 太大,或 Kd 太小 |
把 Kp 减半,再加大 Kd |
| 摆动不断变大 | Kp 超过了临界增益 |
调小它 |
| 又宽又慢地切弯 | 对传感器的提前量而言速度太快 | 减速,或把传感器阵列前移 |
| 控制输出参差不齐 | Kd 作用在带噪声的位置上 |
滤波,或减小 Kd |
| 跟踪总是略微偏心 | 各传感器标定不均 | 用每一路自己的量程做归一化 |
| 丢线后径直开出去 | 丢线时把误差归零了 | 保持上一次的误差 |
硬件落地
| 这个实验台 | 真实机器人 |
|---|---|
| 完美周期的回路 | 除非测量 dt,否则会有抖动;一个 delay() 就能彻底废掉 Kd |
| 理想的标定 | 必须每次都在实际路面上重做 |
| 二值高对比度赛道 | 反光的胶带、灰尘和环境红外都会降低对比度 |
| 轮子不打滑 | 高速时会打滑,而且两个电机的死区不同 |
| 电机瞬时响应 | 两个轮子在不同占空比下才起转 |
| 电池电压恒定 | 电压会塌陷,所以同样占空比随着比赛进行产生的速度会变小 |
在这里找到的增益可以作为一个接近的起点迁移,而整定流程则是完全迁移的。 预计你得在自己的胶带赛道上重新整定——也预计硬件上最大的一项单独改进 不会来自增益,而会来自回路速率,因为第一版通常只跑 20–50 Hz, 而仅仅去掉阻塞调用就能提到几百 Hz。完整制作见 制作一台循迹机器人。
硬件清单
元器件
- Arduino Uno 或兼容控制器
- 三到九个红外反射式传感器
- 两个减速直流电机及车轮
- 双 H 桥电机驱动
- 电池组、底盘和万向轮
探索关联图谱
哪里用到这个模拟器
以这个实验台为基础的项目、学习路线和教程。
继续搭建
下载资源
完成项目时可以参考本页上的这些资料。可下载的项目包只会在其源文件和版本发布之后才会添加。
常见问题
常见问题解答
为什么机器人会围绕线左右摆动?
振荡通常意味着比例增益太高、微分阻尼太低,或者机器人移动的速度超出了传感器更新速率所能支撑的范围。先降低速度,再整定 P 和 D。在真实机器人上,回路里一个很长的 delay() 是常见的隐藏原因:它引入的死区时间会让微分项失效,无论你把它设得多高。
循迹机器人应该用多少个传感器?
五个传感器是一个很好的起点——它们既能反映误差的方向和大小,又能让加权位置的计算便于检查。三个传感器在低速下可以工作,而竞赛机器人通常用八个,以便在高速下获得更精细的位置分辨率。
为什么我的循迹机器人在急弯处会丢线?
底盘移动的速度超过了传感器条分辨弯道的能力,所以在控制器作出反应之前,线就已经离开了传感器阵列。可以降低速度、加宽传感器条,或者提高传感器的更新速率。一个好的控制器还会在所有传感器都丢失赛道时复用上一次已知的线方向,这样它会转回线所在的方向,而不是径直开出去。
循迹应该用模拟还是数字红外传感器?
模拟反射式传感器输出的是一个连续值,这让你能计算出平滑的加权线位置,并按比例转向。数字传感器经过内部阈值判断后只输出开或关,这更简单,但给出的位置信息更粗糙。本模拟器模拟的是模拟量加权位置的方案。
如何标定红外传感器阵列?
在运行之前,让传感器扫过线和背景,记录每个传感器的最小和最大读数,然后用这个范围对实时读数做归一化。标定之所以重要,是因为传感器高度、表面反射率和环境光都会改变原始读数,而未经标定的阵列会让加权位置产生偏差。
Arduino 循迹机器人有哪些好的 PID 初始值?
把网上公布的增益当作起点,而不是可以直接照抄的答案:电机响应、传感器高度、电池电压、表面反射率和回路时序,都会改变真实机器人所需的增益。先只用比例项,把它调大到机器人能以轻微的摆动跟住缓弯,然后加入微分项消除摆动;只有在仍然存在可重复的偏差时,才加入非常小的积分项。
延伸阅读
参考资料
权威资料,帮助你越过本模拟器有限的教学模型,进一步深入学习。