尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

无人驾驶Frenet坐标系:从数学原理到工程落地全解析

无人驾驶Frenet坐标系:从数学原理到工程落地全解析 接触自动驾驶规划控制第一个绕不开的概念就是坐标。说实话我刚开始看到“Frenet坐标系”这个词的时候还以为是某个法国数学家的名字后来真正上手做路径规划才发现这套坐标系几乎贯穿了无人驾驶的感知、规划、控制全链路。如果只用笛卡尔坐标系描述车辆和道路的关系弯道场景里的距离计算、变道轨迹生成、速度规划都会变得极其别扭。这篇内容就把“无人驾驶frenet坐标系”这件事从头到尾聊透包括数学定义、坐标转换、在规划控制里的实际用法以及我在工程落地时踩过的坑。不知道你有没有遇到过这种情况明明车就在车道中心但用一个全局坐标 (x, y) 表达时怎么判断它“偏离中心多少”用欧氏距离硬算不仅繁琐而且在弯道上根本算不准。Frenet坐标系解决的就是这个问题——它把车辆运动拆解成沿道路方向的纵向运动 s 和偏离道路中心线的横向运动 d让路径规划、速度规划、横向控制都变得直观且解耦。这篇文章适合正在学自动驾驶规划控制的同学、刚入行做相关项目的工程师以及想搞明白“为什么业界都在用Frenet”的好奇读者。1. 为什么无人驾驶偏偏要用Frenet坐标系1.1 笛卡尔坐标系在行车场景中的尴尬笛卡尔坐标系是我们在数学课上学得最熟的坐标系用 (x, y) 描述平面上的点用航向角 θ 描述朝向。在测绘、地图、全局定位这些场景里它确实是基础。但一旦到了路径规划和运动控制层面笛卡尔坐标就暴露出一个很尴尬的问题它完全无法自然地表达“车辆和道路的相对关系”。举个弯道例子。一条半径 50 米的圆弧车道车在某个位置想计算“车离车道中心线偏了多少”。在笛卡尔坐标系里你得先找参考线上的最近点然后计算两点之间的欧氏距离同时还要判断车在参考线的左侧还是右侧。这种计算每帧都要做而且弯道曲率越复杂最近点投影的稳定性就越差。更麻烦的是生成一条变道轨迹时如果直接在笛卡尔坐标系里写目标点和约束你很难直观地告诉规划器“车身应该在道路左侧偏移 1.5 米”你只能说一堆 (x, y) 坐标语义全丢了。1.2 Frenet坐标系的定义与直觉Frenet坐标系也叫SL坐标系的核心思路是换一个观察角度先把道路中心线或者你定义的参考线展开成一条带方向的曲线然后用两个量来描述车辆状态s 表示车辆沿着参考线走了多远d 表示车辆相对参考线的横向偏移d 带正负号通常约定参考线左侧为正、右侧为负。这样一看车辆在道路上的位置就变成了“里程碑里程 左右偏移量”的组合。用生活化的类比就像高德地图上你开车走高速导航不关心你在平面地图上的直角坐标它只关心你距离上次服务区多远、你在当前车道的哪一侧。这种描述方式和驾驶员对环境的直觉完全一致所以规划算法里用它来生成轨迹特别顺手。1.3 Frenet如何解耦问题Frenet坐标系最大的工程价值是让路径规划和速度规划彻底解耦。笛卡尔坐标系下横向和纵向运动是耦合在一起的你变道时既要考虑横向位移又要考虑纵向速度曲线写法很绕。但在Frenet坐标系下横向规划只需要关注 d(s) 这条曲线也就是“在哪些里程位置完成多少横向偏移”纵向规划只需要关注 s(t) 这条曲线也就是“什么时间到达哪个里程位置”。规划模块先并行生成横向候选曲线和纵向候选曲线然后把两者组合成完整的轨迹最后再转换回笛卡尔坐标系交给控制模块执行。这个“横纵解耦”的设计思想在当下主流的采样规划框架、模型预测控制框架里都能看到影子是Frenet坐标系能成为无人驾驶领域标准配置的根本原因。2. Frenet坐标系的数学基础2.1 s和d到底怎么算从笛卡尔坐标转到Frenet坐标第一步要找到参考线上离当前车辆位置最近的点也叫匹配点。这个点就是投影基准它的累积弧长就是 s 的值它到车辆位置的带符号距离就是 d 的值。s 的计算流程一般是参考线被离散成一系列点每个点有累积距离表比如第 i 个点的累积距离是 s_i。找到最近点之后如果需要更精细的 s可以在相邻两个参考点之间做插值。d 的计算则需要用向量叉积判断符号连接匹配点到车辆位置如果这个向量指向匹配点切线的左侧d 取正指向右侧则取负。2.2 坐标正反变换的核心公式Frenet转笛卡尔是实际工程里用得最频繁的操作因为采样规划生成的是 (s, d) 序列但最终发给控制模块的轨迹必须是笛卡尔坐标点。核心公式如下x x_r - d * sin(theta_r) y y_r d * cos(theta_r)其中 (x_r, y_r, theta_r) 是匹配点的笛卡尔坐标和航向角。这个公式是从参考点出发沿法线方向偏移 d 得到目标点。反过来笛卡尔转Frenet并没有一个完美的闭式解工程上普遍采用“找最近点 投影”的方式完成在参考线上找最近点得到匹配点索引。用匹配点的累积弧长作为 s 的近似值有需要再做细分插值。计算车辆位置到匹配点的向量投影到匹配点的法向量上得到带符号的 d。2.3 速度、加速度在Frenet下的表达坐标位置只是第一步规划控制还需要速度、加速度。把笛卡尔速度 v 分解到Frenet框架下会得到两个方向的分量沿参考线方向的 s 方向速度和横向偏移变化率 d 方向速度。一个常用的近似关系是s v * cos(theta - theta_r) / (1 - k_r * d)这里 k_r 是参考线在匹配点处的曲率。这个公式直观上很好理解车辆航向和参考线夹角越小沿参考线方向的速度贡献越大参考线弯得越急k_r 越大、偏移越远d 越大同样的车速在“道路里程”意义上走得越慢因为你在绕弯。d 的一阶导 d 表示横向偏移随里程的变化率工程上常把它叫做“横向速度沿路的表达”。在生成平滑变道曲线时我们经常要求起点和终点的 d 为 0意思就是变道前后车辆和参考线方向保持一致不出现“斜着切入”的突兀感。加速度层面s 和 d 分别对应纵向加加速度和横向加加速度舒适性评估和碰撞检测都会用到。3. 路径规划中的Frenet坐标系使用3.1 横向规划变道与避障变道规划是理解Frenet横向规划最好的入门案例。假设车辆当前在车道中心d 0需要变到相邻车道目标 d 3.5 米取决于车道宽度。我们不仅关心终点位置还关心起终点的横向速度 d 和横向加速度 d这个过程通常用五次多项式来表示 d(s)。为什么是五次多项式因为五次多项式有六个系数刚好能约束 d(s) 的边界条件起点 s0 处给 d0、d0、d0终点 ss_end 处给 d1、d1、d1。这样生成的曲线不仅在位置上连续在速度和加速度上也连续车辆执行起来不会出现瞬时的横向冲击。实际采样规划会做更多不只是生成一条 d(s)而是生成多组不同终点距离、不同终点偏移量的候选曲线然后用代价函数评估每条曲线的舒适性、偏移风险和碰撞风险最后挑最优解。Frenet坐标系在这里的优势是代价函数可以直接写成 d 的函数比如“偏离道路中心越远代价越大”逻辑非常清晰。3.2 纵向规划ST图与速度决策纵向规划关心的是“什么时间到达哪个里程位置”工程上最常见的表达工具是 ST 图。横轴是时间 t纵轴是参考线上的里程 s。静态障碍物在ST图上会变成固定的矩形区域因为它在某个里程区间内一直存在动态障碍物则会变成斜的平行四边形因为它随着时间在移动。规划器需要在ST图里生成一条从起点到终点的 s(t) 曲线避开所有障碍物区域同时满足速度限制、加速度限制和舒适性要求。比如前方 60 米处有静止障碍物那 s(t) 曲线必须在某个时间点之前把速度降到零且最终停在障碍物前。在Frenet坐标系下横向规划和纵向规划是独立完成的最后只需要把两个结果组合横向得到 d(s)纵向得到 s(t)用 s 作为中间变量拼接就能得到一条完整的时空轨迹。这种组合方式让算法框架非常灵活横向和纵向的采样器可以各自独立升级互不干扰。3.3 采样加评估的典型方案我接触到的很多开源规划框架其实都是采用“横纵采样 代价评估”的套路。横向采样器会生成一组终点偏移量、终点里程不同的候选横向曲线纵向采样器会生成一组目标速度、决策行为跟车、停车、通过不同的候选纵向曲线。横纵两两组合就得到一张候选轨迹网。每条轨迹在预测模块的输出中都会被送到代价评估器里打分。评估维度通常包括碰撞风险、平均偏移量、曲率变化率、纵向加速度、和当前参考轨迹的一致性等等。Frenet坐标系的优势在这时候体现得最明显多数代价项可以直接在 (s, d, s, d) 里计算不需要反复变换坐标系数值上更稳定也更容易调试。我记得第一次把横向候选d曲线和纵向候选s曲线打印出来看的时候整个规划逻辑一目了然比在笛卡尔坐标里追踪一堆 x、y 点不知道清爽多少。4. 控制模块里的Frenet坐标系使用4.1 横向跟踪误差与航向误差规划器输出轨迹后控制模块要做的就是把车稳定地跟踪上去。控制模块里最核心的误差量有两个横向跟踪误差和航向误差。横向跟踪误差就是当前车辆位置到参考轨迹最近点的横向偏移也就是在Frenet框架下的 d 值航向误差则是车辆航向角与参考轨迹匹配点航向角之差。计算横向跟踪误差的时候控制模块会把车辆位置投影到参考轨迹上找到最近点然后计算带符号的横向距离。这一步本质上就是笛卡尔到Frenet的转换只是控制模块对实时性要求更高通常用上一时刻的最近点索引作为搜索起点限定一个小窗口搜索而不需要从头到尾遍历。4.2 基于误差的横向控制器经典的横向控制器比如 Stanley 控制器利用的就是Frenet框架下的误差概念。控制器的输出是前轮转角由两部分叠加delta theta_e atan2(k * d, v)theta_e 是航向误差负责把车的朝向掰正atan2(k * d, v) 是横向偏移修正项d 越大或者 v 越小修正转角就越大。这个公式之所以能简洁优美地工作正是因为 d 就是Frenet坐标系下面的横向误差可以直接从投影计算中获得。在 MPC 类的控制器里Frenet坐标系的作用同样重要。状态方程里如果直接使用笛卡尔位置误差参考点变化引起的非线性特别强而把模型在Frenet误差框架下线性化之后横向误差和纵向误差的动力学就变得相对解耦控制器设计难度大幅下降。4.3 纵向速度控制在Frenet下的含义纵向控制虽然看起来只是在控制车速但放到Frenet坐标系里看其实是在控制 s(t)也就是车辆沿参考线方向的速度分量。巡航控制、跟车控制、红灯停车这些决策最终都会转成一系列 (s, v) 目标点。比如自动驾驶要在一个设定的距离点前停下来纵向控制器首先需要根据当前位置算出 s然后规划一条减速曲线再通过PID或串级控制实现目标速度。如果完全不引入Frenet坐标想要表达“距离停止线还有 50 米”这种语义每次都要重新求一堆几何距离和角度不仅慢而且容易出错。控制模块和规划模块都统一在Frenet坐标系下描述纵向运动之后整个系统的语义就完全对齐了。5. 工程实现中的坑与排查5.1 参考线的平滑和准备Frenet坐标系的一切运算都建立在参考线之上参考线不平滑后面全白搭。高精地图直接抽取的车道中心线往往包含大量锯齿状噪声点距离不匀、角度跳变。如果不做平滑就拿来算曲率、算投影后果就是 d 值抖动、s 计算异常、控制量来回摆动。我的经验是在生成参考线之后、供规划控制使用之前至少要经过两道处理第一是点位重采样保证相邻点间距均匀第二是平滑滤波可以用B样条拟合、滑动窗口平均或者更严格一点的二次规划平滑把曲率变化约束住。平滑参考线和原始参考线的偏差要控制在一个很小的阈值内因为偏差太大会改变道路语义车辆会“越线”。5.2 最近点匹配与高曲率场景笛卡尔转Frenet时最近点匹配是最容易出问题的环节。正常情况下车辆在参考线一侧最近点只有一个。但在高曲率场景比如发卡弯、盘桥匝道参考线弯道半径很小可能出现同一个点离参考线上多个点的距离相近的情况最近点选择的不稳定性会导致 s 和 d 发生跳变。我踩过的一个比较典型的坑是车辆位于大曲率弯道内测时直接全局搜索最近点偶尔会匹配到参考线上的“下一个弯”位置导致 s 瞬间跳变几十米规划器以为车辆瞬移了直接触发急刹车。解决办法是引入上一时刻匹配点的索引约束只在当前索引附近一段窗口里搜索最近点同时增加匹配距离阈值超过阈值就做异常处理。5.3 d符号、s累积误差等细节d 的正负约定一定要在项目启动第一天就定死并且所有模块统一。有的团队约定左侧为正、右侧为负有的团队反过来这本身没有对错但一旦不统一横向误差的符号就会在转换过程中被翻转车辆会在车道线附近反复蛇形。最好的做法是把“符号约定”写进公共常量或者代码注释的第一行并且用大量可视化日志实测验证。s 的累积误差来自参考线离散化步长和累积距离计算的精度。离散点太稀插值出来的 s 误差就大累积距离计算公式虽然简单但如果参考线是临时拼接而成的相邻段之间的累计起点没对齐s 也会莫名其妙跳变。我在实际开发里会给参考线的每个离散点保存一个累积距离数组并在插值函数里返回置信度标记方便上层模块感知精度问题。5.4 坐标系反复转换带来的bug一个完整系统里Frenet和笛卡尔的转换可能出现在定位、规划、控制等多个模块每个模块都写一遍转换逻辑很容易出现“这半边用新公式、那半边用旧公式”的分裂状态。我见过最隐蔽的bug是规划模块在Frenet系下生成轨迹转换回笛卡尔时用了参考线的法向量的方向搞反生成的轨迹正好偏移到对向车道而单元测试因为只测了直道根本没发现问题。解决方式是收敛转换函数的唯一实现。全系统只保留一份坐标转换库所有模块必须调用同一个函数不允许多份拷贝。转换函数必须配套单测测试用例要覆盖直道、弯道、大偏移、反向偏移这几类典型场景。Frenet转笛卡尔这个函数的公式很简单但真正让它变得可靠的是把边界情况都测透。5.5 采样规划中的s范围依赖在采样规划里横向采样往往基于 s 范围进行比如在 s ∈ [当前s, 当前s80米] 区间里生成候选终点。但 s 范围如果写死在慢速工况或者拥堵场景下车辆 80 米内根本走不完候选轨迹的终点分布就会严重不合理导致规划器频繁放弃采样结果。我的习惯是让采样范围与当前速度相关车速高时 s 范围拉长车速低时缩短。比如 s_end v * T_max s_offset其中 T_max 是最大规划时域这样低速场景也能规划出合理的候选轨迹不会因为采样范围过大导致计算浪费或者候选轨迹全是无效轨迹。6. 一些想留给你的实操建议最后再分享几个我用下来觉得非常值得养成的习惯。第一开发阶段一定要把参考线、车辆的Frenet坐标点、横向候选曲线、纵向候选曲线全部可视化出来不要只看最终轨迹中间表示能暴露绝大多数问题。第二任何一次坐标转换改动后都要跑一遍离线数据回放对比转换前后的轨迹差异这一点在重构代码时尤其有用。第三调试时多打印 s 和 d 的原始值不要只在笛卡尔坐标下看效果。因为很多诡异现象比如横向震荡、纵向急加速根因都在Frenet域里直接看 s/d 曲线往往一眼就能找到问题。第四如果团队里有人问“为什么不用其他坐标系”你可以先让他跑一个高曲率路段的轨迹对比实验用数据说话比解释理论高效得多。Frenet坐标系不是银弹它也有最近点匹配不稳定、曲率定义繁琐这些局限但在无人驾驶的规划控制框架里它依然是那个让问题变得清晰、让模块边界变得干净的核心工具。理解它的原理不算难真正难的是在工程里把每一个转换细节、每一处符号约定都处理得滴水不漏。希望这篇文章能帮你少走一些弯路。
返回列表