4、曲率计算与离散化:连续曲率公式、离散点曲率近似(三点法、五点法)

各位同学,咱们今天聊点实在的。曲率这东西,说白了就是描述曲线“弯”的程度。你开车过弯,方向盘打得越狠,曲率就越大。但在控制算法里,我们面对的往往不是连续曲线,而是一堆离散的点——比如激光雷达扫出来的路径点,或者规划层给的一串轨迹点。怎么从这些离散点里算出曲率?这就是本章要啃的硬骨头。

4.1 连续曲率公式:先打好理论基础

先回顾一下数学定义。对于一条连续曲线 y = f(x),曲率 κ 的公式是:

κ = |y''| / (1 + y'²)^(3/2)

嗯,看着有点吓人。但说白了,分子是二阶导(加速度),分母是一阶导(速度)的某种组合。你想想看,如果曲线很平缓,y' 很小,分母接近1,曲率主要由 y'' 决定。如果曲线很陡,y' 很大,分母变大,曲率就会被压下去——这很符合直觉:陡坡上的弯道,其实没那么“弯”。

我个人习惯把这个公式记成“弯度 = 加速度 / 速度的某种三次方”。虽然不严谨,但好记。

对于参数曲线 (x(t), y(t)),公式稍微变一下:

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

这个形式更通用。我在项目中遇到过用三次样条插值做路径平滑,然后直接用这个公式算曲率。效果不错,但计算量稍大。

核心要点:连续曲率公式是理论基础。但在实际控制中,我们很少直接用它——因为数据是离散的,求导会放大噪声。

4.2 离散点曲率近似:三点法

好,现在进入实战。假设你有一串离散点 P0, P1, P2, ..., Pn。怎么算 Pi 点的曲率?

最经典的方法就是三点法。取 Pi 的前一个点 Pi-1 和后一个点 Pi+1,用这三个点拟合一个圆,然后取这个圆的半径的倒数作为曲率。

公式如下:

设三点为 A(x1,y1), B(x2,y2), C(x3,y3)
先算边长:
a = dist(B, C)
b = dist(A, C)
c = dist(A, B)

然后算三角形面积:
s = |(x2-x1)*(y3-y1) - (x3-x1)*(y2-y1)| / 2

外接圆半径:
R = (a * b * c) / (4 * s)

曲率:
κ = 1 / R

注意,这里 s 是三角形面积。如果三点共线,s = 0,R 无穷大,曲率为 0。这很合理——直线嘛,不弯。

我曾经踩过一个坑:三点法对噪声非常敏感。如果点间距不均匀,或者有测量噪声,算出来的曲率会剧烈抖动。有一次做AGV的路径跟踪,曲率一抖,控制器就跟着抖,车在仓库里走S形。后来加了滤波才稳住。

三点法的优点是简单、计算快。适合嵌入式系统,或者对实时性要求高的场景。但缺点也很明显:

  • 对噪声敏感
  • 只能反映局部弯曲程度
  • 点间距不均匀时误差大

4.3 离散点曲率近似:五点法

为了克服三点法的缺点,我们可以用更多的点来做拟合。五点法就是取 Pi 前后各两个点,一共五个点,拟合一个二次曲线或三次曲线,然后求导得到曲率。

具体做法:

  1. 取点 Pi-2, Pi-1, Pi, Pi+1, Pi+2
  2. 用最小二乘法拟合一个二次多项式 y = a x² + b x + c
  3. 然后直接用连续曲率公式:κ = |2a| / (1 + (2a x + b)²)^(3/2)

当然,更常见的是用参数曲线拟合。把五个点的 x 和 y 分别用弧长参数化,然后分别拟合 x(s) 和 y(s) 的二次或三次多项式,再代入参数形式的曲率公式。

// 伪代码示例:五点法曲率计算
function curvatureFivePoints(points, i):
    // points 是点数组,i 是目标点索引
    // 取前后各两个点
    p = points[i-2 : i+3]  // 共5个点
    
    // 用弧长参数化
    s = cumulative_distance(p)
    
    // 拟合 x(s) 和 y(s) 的二次多项式
    coeff_x = polyfit(s, x_coords, 2)
    coeff_y = polyfit(s, y_coords, 2)
    
    // 计算一阶导和二阶导
    x1 = 2*coeff_x[0]*s[2] + coeff_x[1]  // 在中间点求导
    y1 = 2*coeff_y[0]*s[2] + coeff_y[1]
    x2 = 2*coeff_x[0]
    y2 = 2*coeff_y[0]
    
    // 曲率公式
    k = abs(x1*y2 - y1*x2) / (x1^2 + y1^2)^(1.5)
    return k

我的建议:如果数据质量好(噪声小、点间距均匀),三点法就够用。如果数据有噪声,或者点间距不均匀,用五点法更稳。我在做无人车路径跟踪时,激光雷达的点云数据噪声大,用五点法配合滑动窗口滤波,曲率曲线平滑多了。

4.4 三点法与五点法的对比

对比项 三点法 五点法
计算量 小(适合嵌入式) 较大(需要拟合)
噪声敏感度 高 低(有平滑效果)
点间距适应性 差 好
边界处理 简单(首尾点需特殊处理) 复杂(首尾各两个点需特殊处理)
适用场景 实时性高、数据干净 噪声大、精度要求高

4.5 知识体系图

下面这张图展示了本章的核心逻辑:从连续曲率公式出发,到离散化的两种近似方法,再到实际应用中的选择策略。

曲率计算与离散化知识体系 连续曲率公式 离散点曲率近似 三点法 外接圆半径求曲率 五点法 多项式拟合求导 简单、快速、噪声敏感 平滑、鲁棒、计算量大

4.6 实际应用中的选择策略

说了这么多,到底用哪个?我个人的经验是:

  • 如果你在做实时控制(比如电机伺服、无人机飞控),用三点法。计算快,够用。
  • 如果你在做路径规划或离线分析,用五点法。精度高,曲线平滑。
  • 如果数据噪声特别大,可以考虑用更多点(七点法、九点法),但边际效益递减。

避坑指南:我曾经在一个项目中,直接用三点法算曲率,然后喂给PID控制器。结果曲率一抖,控制量就抖,系统直接发散。后来加了限幅和低通滤波,才稳住。记住:曲率计算不是越精确越好,而是要和控制器匹配。

嗯,曲率计算这块就聊到这儿。下一节咱们会讲曲率约束怎么加到控制律里,以及怎么防止控制发散。到时候你会看到,曲率算得准不准,直接决定了你的车能不能稳稳地过弯。

小技巧:如果你用三点法,可以在算曲率之前先对点序列做一次滑动平均滤波。效果立竿见影。

可可精品资料库