路径跟踪模拟器:纯跟踪与 Stanley
用纯跟踪或 Stanley 跑完一条赛道,并带上真实的转向延迟。拖动前视距离,整趟轨迹立即重画——包括 1 Hz GPS 定位让你付出的代价。
- 类别
- 自主机器人
- 时长
- 20–40 分钟
- 平台
- 浏览器 · Arduino · Raspberry Pi
01 / 从这里开始
简介
规划器交给你一条路径,但路径里没有任何东西告诉轮子该怎么做。这个实验台补上的正是这缺失的一环。纯跟踪和 Stanley 在同一条航点路线上转向,并带有一阶转向响应和感知延迟,因为一个没有滞后的模型会让错误的整定看起来像是最优的。拖动一个航点或前视距离,整趟运行都会重新计算。
Live lab / Path following
Path following simulator
Pure pursuit and Stanley steering the same course, with the lag a real robot has. Drag the lookahead and the whole run replots — too short oscillates, too long cuts corners, and the best value moves with speed.
The dashed line with dots is the course you asked for; the solid line is where the robot went. The faint line is the whole run at the current settings, computed the moment you change one. Below, cross-track error along the path — dotted verticals are corners. Drag a waypoint to rebuild the course.
- Commanded path
- Driven
- Full run preview
- GPS fix
- RMS error
- —
- Worst error
- —
- Corner cut
- —
- Steering effort
- —
- Progress
- 0%
- Lap time
- —
Keyboard: focus the course, then Space to run/pause, N to step, R to reset, C for a new course, F for full screen. Press 1–8 to pick a waypoint and the arrow keys to move it.
控件
控制器用来在纯跟踪和 Stanley 之间切换。前视距离是纯跟踪唯一的旋钮, 对 Stanley 则是禁用的,因为它并不使用前视距离——这本身就是重点。
速度与前视距离会相互影响,这是最值得动手玩的部分: 先设成 1 m/s 找到最好的前视距离,再设成 3 m/s 重新找一次。
位置来源可以把完美的里程计换成一个 1 Hz、带米级噪声的定位结果, 并在两次更新之间保持不变。误差始终对照真值评分,所以这个惩罚是真实的, 而不是被藏起来的。
拖动任意航点,或者按 1–8 选中一个再用方向键移动。 拖动时整趟运行都会重新计算。
原理
两个控制器回答的是同一个问题——已知我在哪里、路径在哪里,转向角应该是多少?—— 而它们的回答方式完全不同。
纯跟踪是几何。找出路径上在前视距离 L 之前那个点,然后开过它的圆弧:
κ = 2y / L_d² δ = atan(2 b sin α / L_d)
其中 y 是目标点在机器人坐标系下的横向偏移,b 是轴距。它只有一个参数,
而且是一个距离而不是一个增益——所以它可以在机器人之间迁移。
Stanley是控制。以前轴为参考,加上两项:
δ = θ_e + atan(k · e / v)
航向误差加上横向误差的反正切。除以速度,就是让一个增益能跨越一段
速度范围的原因。k 是一个真正的控制增益,不迁移。
实验台补上了教科书推导里略去的东西:总共 0.4 s 的滞后, 由 0.25 s 的一阶转向响应加上 0.15 s 的感知与计算延迟构成。 没有它,纯跟踪会随着前视距离缩小而单调变好,整个整定问题就消失了。
算法
每一步,对两个控制器都适用:
- 投影到路径上,在“上次到达的弧长”附近的一个窗口内搜索,而不是整条路径。 全局搜索会匹配到最近的那一段,所以一条折返的赛道会把机器人的进度 瞬移到它一分钟前刚经过的某个拐角。
- **在顶点处把平局解决到出边那一段。**过了拐角之后,两条相邻线段会投影到 同一个点、且距离相同;保留入边那一段,会递给控制器一个航向误差和 一个横向偏移——两者都接近零——于是它悄无声息地径直开出路径。
- 计算转向角,按控制器自己的规则来,并把它限制在机械极限内。
- 施加滞后,然后积分自行车模型。
- 对照真值评分,永远不要对照估计值。
第 2 步不是一个优化项。它就是 Stanley 能用和 Stanley 每次都恰好 在 78% 的地方自信地开出赛道之间的区别。
源代码
完整的纯跟踪,以它在真实机器人上呈现的形式:
float lastS = 0; // arc length last reached — state, and it only moves forward
float pursue(float x, float y, float heading, float speed) {
// The lookahead is scheduled on speed, with a hard floor: at a standstill a
// proportional schedule asks for zero, which is a division by zero in disguise.
float lookahead = constrain(0.7f * speed + 0.4f, 0.4f, 3.0f);
float s = projectOntoPath(x, y, lastS); // windowed around lastS
lastS = max(lastS, s);
Point goal = pointAtArcLength(lastS + lookahead);
float dx = goal.x - x, dy = goal.y - y;
float lateral = -sinf(heading) * dx + cosf(heading) * dy;
float ld = max(0.3f, hypotf(dx, dy)); // clamp, or curvature blows up
float curvature = 2.0f * lateral / (ld * ld);
return curvature; // omega = v * curvature
}
真正要紧的是三行:调度下限、lastS 的单调性,以及 ld 的钳位。
其余的就是公式。
假设与硬件差异
实验台给了机器人一张完美的路径地图、一个完全已知的轴距、没有轮子打滑, 以及一个干净的一阶滞后模型。真实机器人一样都没有。
轮子打滑会让位置估计以一种
任何控制器都无法察觉的方式出错。减速箱背隙
在每次转向换向时都会加上空行程,它表现得像额外的滞后,会把最优前视距离
往上推。而差速驱动根本没有转向角——它有一个被指令的转速,
所以 ω = v κ 取代了 atan,而轴距只影响它能转得多紧。
在这一切之后仍然存活下来的是那个形状:一个内部最优解、随速度向右移动, 以及在该最优解处的误差无论如何都随速度增长。
电路图
控制器是便宜的部分。它从机器人其余部分需要的东西,才是贵的部分。
**位置。**两个轮子上的正交编码器, 以及在回路速率上对它们做积分的差速里程计。 在室内,这足以应付几十米的距离。
**航向。**短期用陀螺仪,绝对参考用磁力计,或者两者都要。航向误差是两个 控制器都赋予最高权重的项,也正是里程计最先丢失的那一项。
户外加一个绝对修正。GPS 模块要融合进估计里, 而不是直接跟随它——差别是 0.09 m 的均方根误差对 1.25。
硬件清单
元器件
- 一个能直接指令转向或轮速的底盘
- 一个位置估计——最少要有编码器,在户外还要与 GPS 融合
- 一个在整个任务期间都不会漂移的航向参考
- 一个足够快的回路,使它自身的滞后小于你的前视距离
探索关联图谱
哪里用到这个模拟器
以这个实验台为基础的项目、学习路线和教程。
继续搭建
下载资源
完成项目时可以参考本页上的这些资料。可下载的项目包只会在其源文件和版本发布之后才会添加。
常见问题
常见问题解答
为什么前视距离更短,并不总能跟得更好?
在没有滞后的模型里确实如此,这正是许多教科书推导具有误导性的原因。真实机器人需要时间才能达到被指令的转向角,而且它据以行动的位姿已经是几十毫秒之前的了。这个实验台模拟了 0.25 秒的转向时间常数和 0.15 秒的感知延迟。有了这些滞后,误差曲线就变成了 U 形:短前视距离发出的修正,要等机器人已经越过误差之后才生效,于是下一次指令就会过度修正。一个比自身执行器还快的控制器会产生振荡。
如何为我的机器人选择前视距离?
测出你的总控制滞后,乘以你的速度,然后从这个距离的一到两倍开始。在这个实验台里,滞后是 0.4 秒,实测的最优值在 1 m/s 时为 0.9 米,到 3 m/s 时升至 1.4 米——是滞后期间所走距离的 1.2 到 2.3 倍。注意,最优值随速度增长,但增长得比正比例慢,所以按固定的行驶秒数来取值很接近,却并不准确。实际使用时,把它做成一个随速度变化的简单线性调度,并设一个硬性下限,因为在静止时这个调度会要求零。
纯跟踪和 Stanley,哪个更好?
它们失效的方式不同,这才是有用的答案。在这条路线上以 2 m/s 行驶时,纯跟踪会切弯,走完的路程比指令路径短 0.8%;Stanley 则不肯离开线路,转弯时甩得更宽,多走了 2.2%。Stanley 在关键之处能守住更紧的线路,但花掉的转向量是 18.5 弧度,而纯跟踪只有 4.3——执行器的动作、电流和轮胎磨损都是四倍。当路径只是一个建议时用纯跟踪,当路径是一个约束时用 Stanley。
为什么误差是对照真实位置、而不是估计值来测量的?
因为一台以为自己在路径上的机器人,按其构造就会报告零误差。把位置来源切换成 GPS,控制器就开始依据一个带噪声、滞后一秒的定位结果来转向,而实验台依然对照模型实际积分出的位姿来评分。这是 GPS 的惩罚能以一个数字显现出来的唯一原因:0.09 米的均方根误差变成了 1.25 米,转向量也增加到四倍以上。
那条淡色的线表示什么?
它是在当前设置下的完整运行,在你改动任何一个设置的那一刻就计算出来。每拖动一次滑块,整条路线都会在后台用大约二十毫秒重新跑一遍,所以拖动前视距离时,你看到的是它实际产生的轨迹,而不是对轨迹的某种承诺。那条粗线则是你按下开始后,机器人沿同一趟运行播放的动画。
为什么机器人在那个非常急的拐角处总是转个不停?
两个控制器都有一个由轴距和最大转向角决定的最小转弯半径,比这更急的拐角,无论怎么整定都跟不上。真正的解决办法在上游:用倒圆角或圆弧把路径变得平缓,或者在拐角前减速,而这正是运动曲线的用途。任何转向控制器都无法开出车辆本身不具备的几何形状。
延伸阅读
参考资料
权威资料,帮助你越过本模拟器有限的教学模型,进一步深入学习。