2. 曲率约束基础:曲率的几何定义、物理意义及其在路径规划中的角色

各位同学,咱们今天聊聊曲率约束。说实话,这玩意儿在路径规划里是个绕不开的坎儿。我刚开始做自动驾驶那会儿,总觉得路径规划就是找条路走,后来发现——嗯,没那么简单。

你想想看,一辆车在高速上跑,突然来个急转弯,乘客会怎么想?肯定骂娘。更别提如果曲率太大,车可能直接侧翻。所以,曲率约束不是锦上添花,而是安全底线。

2.1 曲率的几何定义:从圆说起

曲率这个概念,说白了就是描述曲线弯曲程度的量。怎么定义呢?

想象一条曲线上的某一点。过这一点,我们可以画一个最贴近曲线的圆——这个圆叫密切圆。密切圆的半径越小,说明曲线在这个点弯得越厉害;半径越大,说明越平缓。

曲率 κ 的数学定义就是密切圆半径 R 的倒数:

κ = 1 / R

单位是 1/m。举个例子,半径 10 米的圆,曲率就是 0.1。直线呢?直线可以看作半径无穷大的圆,曲率就是 0。

我个人习惯用这个公式来理解:曲率越大,转弯越急。就这么简单。

核心要点:

  • 曲率 κ = 1 / R,R 是密切圆半径
  • 直线曲率为 0
  • 曲率越大,弯曲越剧烈

2.2 物理意义:车为什么不能无限转弯?

好,几何定义搞清楚了。那物理上呢?

我遇到过不少刚入行的朋友,他们觉得路径规划就是数学游戏。其实不是。车辆有物理极限。

一辆车转弯时,靠的是轮胎与地面的摩擦力。曲率越大,需要的向心力越大。向心力公式还记得吧?

F = m * v² / R = m * v² * κ

其中 m 是质量,v 是速度。你看,曲率 κ 和速度 v 的平方是乘在一起的。这意味着:

  • 速度越快,能承受的曲率越小
  • 曲率越大,必须降速

我曾经在一个项目中,路径规划器生成了一个曲率 0.2 的弯道,车速 60 km/h。结果仿真一跑,侧向加速度直接超了 0.5g。乘客肯定受不了。后来我加了个曲率-速度耦合约束,才把问题解决。

实战技巧: 在实际系统中,我通常把最大曲率与最大速度绑定。比如:

κ_max(v) = a_lat_max / v²

其中 a_lat_max 是最大允许侧向加速度,一般取 0.3g ~ 0.5g。

2.3 路径规划中的角色:曲率约束到底管什么?

曲率约束在路径规划里,主要干三件事:

  1. 保证可执行性——规划出的路径,车辆必须能实际开出来
  2. 保证舒适性——乘客不晕车、不难受
  3. 保证安全性——不侧翻、不失控

说白了,没有曲率约束的路径,就是一张废纸。

我记得有一次做园区物流小车,规划器输出了一条路径,曲率在某个点突然从 0.05 跳变到 0.15。小车一执行,方向盘猛地一打,差点把货甩出去。这就是曲率不连续的问题。

注意: 曲率不仅要限制大小,还要限制变化率。曲率突变会导致方向盘急转,这在高速场景下极其危险。我一般会加一个曲率变化率约束:

|dκ/ds| ≤ κ_dot_max

其中 s 是路径弧长。

2.4 曲率约束的数学表达

在路径规划中,我们通常把路径参数化为 x(s) 和 y(s),其中 s 是弧长。曲率的计算公式是:

κ(s) = |x'(s) y''(s) - y'(s) x''(s)| / (x'(s)² + y'(s)²)^(3/2)

看着复杂?其实不用怕。实际工程中,我们很少直接算这个。更常用的方法是:

  • 用离散点近似曲率
  • 或者用参数化曲线(如B样条、贝塞尔曲线)直接控制曲率

我个人偏好用B样条。为什么呢?因为B样条的曲率可以通过控制点来调节,而且天然具有连续性。我在做高速路径规划时,B样条帮了大忙。

2.5 知识体系总览

下面这张图,是我自己总结的曲率约束知识框架。你看一眼,心里就有数了。

曲率约束基础 几何定义 κ = 1 / R 密切圆概念 物理意义 向心力约束 速度-曲率耦合 路径规划角色 可执行性 舒适性 安全性 约束类型:大小约束 + 变化率约束 κ ≤ κ_max |dκ/ds| ≤ κ_dot_max

2.6 一个简单的曲率计算示例

光说不练假把式。咱们写个简单的 Python 代码,算算离散路径点的曲率。

import numpy as np

def compute_curvature(x, y):
    """
    计算离散路径点的曲率
    x, y: 路径点坐标数组
    返回: 每个点的曲率值
    """
    dx = np.gradient(x)
    dy = np.gradient(y)
    ddx = np.gradient(dx)
    ddy = np.gradient(dy)
    
    # 曲率公式
    numerator = np.abs(dx * ddy - dy * ddx)
    denominator = (dx**2 + dy**2)**1.5
    
    # 避免除零
    curvature = np.divide(numerator, denominator, 
                          out=np.zeros_like(numerator), 
                          where=denominator > 1e-6)
    return curvature

# 示例:一个半圆路径
theta = np.linspace(0, np.pi, 50)
x = 10 * np.cos(theta)
y = 10 * np.sin(theta)

kappa = compute_curvature(x, y)
print(f"平均曲率: {np.mean(kappa):.4f}")  # 应该接近 0.1

这段代码我用了很多年。注意 np.gradient 用的是中心差分,精度还行。如果你需要更高精度,可以用样条插值后再求导。

小提示: 实际工程中,路径点往往有噪声。直接求导会放大噪声,曲率值会剧烈跳动。我一般先做平滑滤波,再算曲率。常用的方法有 Savitzky-Golay 滤波或移动最小二乘法。

2.7 避坑指南

最后,分享几个我踩过的坑:

  • 曲率不连续——路径规划器输出了一段直线接圆弧,曲率从 0 跳到 0.1。车辆执行时方向盘猛打,乘客直接晕车。解决办法:用回旋曲线(Clothoid)过渡。
  • 忽略曲率变化率——只限制曲率大小,没限制变化率。结果路径曲率变化太快,转向系统跟不上。后来我加了 |dκ/ds| 约束,问题解决。
  • 曲率与速度解耦——单独规划路径,再单独规划速度。结果路径曲率大的地方速度没降下来,侧向加速度超标。现在我做联合优化,路径和速度一起考虑。

嗯,曲率约束的基础就这些。说白了,它就是连接几何、物理和工程的一座桥。理解了它,后面的轨迹平滑就好办了。


可可精品资料库