RDP 算法是自动驾驶和地图处理中最基础、最常用的算法之一。
你可以把它理解为**“给轨迹做瘦身”或者“去噪滤镜”**。
RDP抽稀(减少直线段冗余点)
1. 为什么需要“抽稀”?(痛点)
想象一下,地图里的车道中心线(Reference Line)原本是由无数个密密麻麻的点组成的。
原始数据:假设一条100米长的笔直大马路。
如果地图做得太细,每隔 10厘米 就有一个点。
那你就会收到1000个点:(x_1, y_1), (x_2, y_2) ... (x_{1000}, y_{1000})。
问题:
传不动:
Navigation发给Planning的消息包太大了。算不动:你的
Planning节点拿到这 1000 个点,OSQP 求解器会算得很慢。没必要:对于一条直线,我其实只需要起点和终点两个点就够了,中间那 998 个点都是**“冗余点”**。
RDP 算法的作用,就是把这 998 个没用的点扔掉,只保留关键的拐弯点。
2. RDP 算法是怎么工作的?(原理)
全称:Ramer-Douglas-Peucker Algorithm (拉默-道格拉斯-普克算法)
它的核心思想是:设置一个容忍度(阈值 $\epsilon$),如果一条线上的点离“直线”的偏差很小,就把这些点当成直线的一部分忽略掉。
傻瓜式步骤演示:
连线:先把轨迹的起点 A和终点 B连一条直线(虚线)。
找刺头:在 A 和 B 之间的所有点里,找出一个离这条虚线最远的点 C(距离为 d)。
判断:
情况 1(很直):如果这个最大距离 d 小于你设定的阈值 \epsilon(比如 0.1米)。
结论:说明 A 到 B 之间基本是直的。
操作:扔掉 A 和 B 之间所有的点。保留 A, B。
情况 2(有弯):如果这个最大距离 d 大于阈值 epsilon。
结论:说明 C 点是一个显著的拐弯,不能扔。
操作:保留 C 点。把原本的线段切成两段:A到C和C到B。
递归:对A到C和C到B这两段路,重复上面的步骤,直到所有剩下的点都足够“直”。
3. 那个神秘参数 epsilon
我在之前的回答里让你关注这个参数,它决定了你的路径是“精细”还是“粗糙”。
epsilon 设得很大(比如 5米):
效果:只有超级急的大弯才会被保留。
结果:路径变成了僵硬的折线,像用尺子画的。
风险:车子可能会切弯(Cut Corner),压到路沿石。
epsilon 设得很小(比如 0.01米):
效果:几乎保留了所有细节。
结果:点还是很多,起不到“瘦身”的效果。
epsilon 适中(通常 0.1米 - 0.5米):
效果:直路上只留两端,弯道上保留几个关键点。既省资源,又保真。
4. 对你的代码(Planning Node)意味着什么?
既然上游用了 RDP 算法,那你收到的MapTrajectory就有以下特征:
直路点很少:车在直行时,你收到的路径点可能相隔几十米才有一个。
注意:你的局部规划器如果依赖密集点来计算曲率,可能会出错。你可能需要在局部规划里自己做插值(Interpolation),把稀疏点重新加密。
弯道点较多:在转弯处,点会密集起来,为了拟合弯道的形状。
它是折线:严格来说,RDP 输出的是一段段首尾相连的直线段,不是平滑曲线。你的 OSQP 优化器的一个重要工作,就是把这些生硬的折线磨圆(Smoothing),让车开起来顺滑。
一句话总结
RDP 就是一个“去直存弯”的过滤器。它告诉 Planning 节点:“别管那些细枝末节,我只告诉你哪里该转弯,剩下的直路你自己看着办。”