4. 路径表示方法:参数化曲线(B样条、贝塞尔曲线)、路径点序列、Frenet坐标系

说到路径表示,这其实是轨迹优化的「地基」。你想想看,如果连路径怎么描述都没搞清楚,后面的平滑、约束、优化全都白搭。我在项目里见过不少同学,一上来就猛调优化参数,结果路径还是抖得跟心电图似的——问题往往出在表示方法上。

今天咱们就把这块彻底捋清楚。我个人习惯把路径表示分成三大类:参数化曲线、路径点序列、以及Frenet坐标系下的表达。每种都有它的脾气,选对了事半功倍。

4.1 参数化曲线:贝塞尔与B样条

参数化曲线,说白了就是用数学公式把路径「捏」出来。你给几个控制点,曲线就乖乖地从起点跑到终点,中间还自带平滑属性。嗯,这里要注意:不是所有曲线都适合做轨迹优化。

4.1.1 贝塞尔曲线

贝塞尔曲线是最直观的。给定n+1个控制点,就能生成一条n阶曲线。公式长这样:

B(t) = Σᵢ₌₀ⁿ Pᵢ * Bᵢ,ₙ(t),  t ∈ [0,1]

其中 Bᵢ,ₙ(t) = C(n,i) * tⁱ * (1-t)ⁿ⁻ⁱ

优点很明显:

  • 凸包性:曲线一定落在控制点围成的凸包内,安全性有保障
  • 端点插值:首尾控制点就是路径的起点和终点,好理解
  • 导数连续:n阶贝塞尔曲线在连接点处有n-1阶连续

但坑也不少。我曾经在项目中用高阶贝塞尔曲线做全局路径,结果控制点一多,曲线就开始「抽风」——稍微动一个点,整条曲线都跟着变形。这就是全局性的问题。

避坑指南:贝塞尔曲线不适合做长距离路径。我建议只用在局部路径规划或者曲率过渡段,比如换道时的平滑连接。超过10个控制点,赶紧换B样条。

4.1.2 B样条曲线

B样条曲线解决了贝塞尔的全局性问题。它引入了「节点向量」的概念,让每个控制点只影响局部区域。公式稍微复杂点:

C(t) = Σᵢ₌₀ⁿ Nᵢ,ₚ(t) * Pᵢ

其中 Nᵢ,ₚ(t) 是p次B样条基函数,由节点向量决定

我个人最喜欢B样条的地方在于:

  • 局部支撑性:移动一个控制点,只影响附近几段曲线。调试起来太爽了
  • 连续性可控:通过调整节点重复度,可以控制曲线在连接点处的光滑程度
  • 阶数灵活:3次B样条就能保证C2连续,对车辆控制来说完全够用
实战经验:我在做高速自动驾驶项目时,路径表示统一用3次均匀B样条。为什么?因为3次B样条的曲率变化足够平滑,车辆转向机构跟得上。你想想看,如果曲率突变,方向盘得打得多快?乘客不晕才怪。

这里有个小技巧:B样条的节点向量选择很关键。均匀节点适合一般场景,但如果你想让路径在某些区域更「听话」,可以用非均匀节点。比如在弯道入口处加密节点,让曲线更贴合道路走向。

4.2 路径点序列

参数化曲线虽好,但有时候我们就是想要最直接的方式——给一串点,连起来就是路径。路径点序列就是这么干的。

常见的表示方式:

  • 离散点列表:[(x₀,y₀), (x₁,y₁), ..., (xₙ,yₙ)],简单粗暴
  • 等间距采样:每隔固定距离取一个点,方便计算
  • 关键点+插值:只存关键弯道点,中间用插值补全

路径点序列最大的好处是直观。你从地图上采了一堆GPS点,直接扔进去就能用。但问题也很明显:

注意:原始路径点序列通常又抖又噪。我遇到过最夸张的一次,激光雷达扫出来的路径点,相邻两点之间的方向变化超过30度。这种路径直接给控制模块,车辆会像喝醉了一样左右摇摆。

所以路径点序列一般要配合平滑算法使用。常见的做法是:

  1. 先对原始点做滤波(比如滑动平均或Savitzky-Golay滤波)
  2. 再用B样条或贝塞尔曲线拟合
  3. 最后在拟合曲线上重新采样

说白了,路径点序列是「原材料」,参数化曲线是「精加工」。两者结合才是王道。

4.3 Frenet坐标系

终于聊到Frenet坐标系了。这东西在自动驾驶里太重要了,我甚至觉得它是轨迹优化的「灵魂」。

Frenet坐标系的核心思想:把路径分解成纵向(沿着道路方向)和横向(垂直于道路方向)两个独立维度。公式很简单:

纵向:s(t) —— 沿参考线走过的距离
横向:d(t) —— 偏离参考线的距离

为什么要这么搞?你想想看,在笛卡尔坐标系下,一条弯弯曲曲的道路,描述起来多费劲。但在Frenet坐标系下:

  • 纵向控制:只管加速减速,跟道路形状无关
  • 横向控制:只管左右偏移,跟车速无关
  • 解耦优化:纵向和横向可以分开优化,计算量直接减半
核心优势:Frenet坐标系让「路径」和「速度」彻底解耦。你可以先规划出一条漂亮的几何路径(横向),再独立设计速度曲线(纵向)。这在实车调试时太方便了——路径有问题改路径,速度有问题改速度,互不干扰。

我记得在做一个泊车项目时,用笛卡尔坐标系怎么调都调不好,车辆总是蹭到路边。换成Frenet坐标系后,问题一下子清晰了:原来是横向偏移的约束没处理好。改完约束,一把就停进去了。

Frenet坐标系和笛卡尔坐标系的转换公式:

笛卡尔 → Frenet:
  s = 参考线上最近点的弧长
  d = 点到参考线的带符号距离

Frenet → 笛卡尔:
  x = x_ref(s) - d * sin(θ_ref(s))
  y = y_ref(s) + d * cos(θ_ref(s))

这里要注意一个坑:参考线的选择很关键。如果参考线本身不平滑,Frenet坐标系下的计算会出问题。我建议参考线至少是C2连续的,最好用B样条拟合过。

4.4 三种方法的对比与选择

说了这么多,到底该用哪种?我整理了一张表,方便你对照:

方法 优点 缺点 适用场景
贝塞尔曲线 简单直观,凸包性好 全局性,不适合长路径 局部路径、换道、泊车
B样条曲线 局部可控,连续性好 节点选择需要经验 全局路径、高速巡航
路径点序列 直接易得,无需建模 噪声大,需后处理 原始数据、地图采集
Frenet坐标系 纵横向解耦,优化方便 依赖参考线质量 轨迹优化、运动规划

我个人习惯的组合是:用B样条做全局路径表示,在Frenet坐标系下做轨迹优化,最后用路径点序列做数据交换。这样既保证了平滑性,又方便调试,还能跟上下游模块对接。

小提示:刚开始接触轨迹优化时,别急着上复杂方法。先用路径点序列跑通流程,再逐步替换成参数化曲线。每一步都验证清楚,最后再上Frenet坐标系。这样出了问题也好定位。

好了,路径表示方法就聊到这儿。记住一句话:选对表示方法,轨迹优化就成功了一半。剩下的,就是调参和debug的体力活了。

路径表示方法知识体系 路径表示方法 参数化曲线 贝塞尔曲线 B样条曲线 路径点序列 离散点列表 等间距采样 Frenet坐标系 纵向s(t) 横向d(t) 核心:纵横向解耦,优化更方便 推荐组合 B样条(全局) + Frenet(优化) + 路径点(数据交换)
可可精品资料库