Bezier曲线曲面生成算法

Bezier 曲线/曲面是 CNC、机器人、矢量图形和运动规划中最常用的轨迹生成工具


一、Bezier 曲线数学本质

Bezier 曲线 = 控制点加权叠加 + Bernstein 多项式

定义式

给定 ( \(n+1\) ) 个控制点 ( \(P_0 \dots P_n\) ):

\(B(t) = \sum_{i=0}^{n} \binom{n}{i}(1-t)^{n-i}t^i P_i,\quad t\in[0,1]\)

优点

  • 必过起点和终点
  • 曲线被控制多边形“包裹”
  • 连续、平滑、易求导

缺点

  • 高阶不稳定(>6 阶不建议)

二、最推荐:De Casteljau 算法

这是数值最稳定、最适合 MCU 的实现方法。

1、几何意义

在每条线段上按比例 ( t ) 取点,逐层递归,直到只剩一个点 —— 那就是曲线上的点。

2、二维 Bezier 曲线(C 代码)

typedef struct {
    float x;
    float y;
} Point2f;

Point2f bezier2(Point2f p[3], float t)
{
    Point2f q0, q1, r;

    q0.x = (1 - t) * p[0].x + t * p[1].x;
    q0.y = (1 - t) * p[0].y + t * p[1].y;

    q1.x = (1 - t) * p[1].x + t * p[2].x;
    q1.y = (1 - t) * p[1].y + t * p[2].y;

    r.x = (1 - t) * q0.x + t * q1.x;
    r.y = (1 - t) * q0.y + t * q1.y;

    return r;
}

适合 STM32 / GRBL / 运动插补


3、任意阶 De Casteljau(通用版)

void bezier_casteljau(Point2f *P, int n, float t, Point2f *out)
{
    Point2f tmp[n];
    for (int i = 0; i < n; i++)
        tmp[i] = P[i];

    for (int k = 1; k <= n; k++) {
        for (int i = 0; i < n - k; i++) {
            tmp[i].x = (1 - t) * tmp[i].x + t * tmp[i + 1].x;
            tmp[i].y = (1 - t) * tmp[i].y + t * tmp[i + 1].y;
        }
    }
    *out = tmp[0];
}

复杂度 O(n²),n ≤ 6 完全没问题


三、Bezier 曲线在运动控制中的用法(重点)

1、生成轨迹点(插补)

for (int i = 0; i <= 100; i++) {
    float t = i / 100.0f;
    Point2f pt = bezier2(ctrl, t);
    move_to(pt.x, pt.y);
}

替代直线插补
用于 CNC 圆角、平滑路径
可用于 速度规划(对 t 求导)


2、一阶导数

\(B'(t) = n\sum_{i=0}^{n-1}(P_{i+1}-P_i)B_{i,n-1}(t)\)

Point2f bezier_velocity(Point2f p[3], float t)
{
    Point2f v;
    v.x = 2 * ((1 - t)*(p[1].x - p[0].x) + t*(p[2].x - p[1].x));
    v.y = 2 * ((1 - t)*(p[1].y - p[0].y) + t*(p[2].y - p[1].y));
    return v;
}

四、Bezier 曲面(CNC / 3D 打印核心)

1、双三次 Bezier 曲面

\(S(u,v)=\sum_{i=0}^{n}\sum_{j=0}^{m}B_i^n(u)B_j^m(v)P_{ij}\)

2、直观理解

  • u 方向一条 Bezier
  • v 方向一条 Bezier
  • 网格控制点 → 曲面

3、代码

Point3f bezier_surface(Point3f P[4][4], float u, float v)
{
    Point3f pu[4];

    for (int i = 0; i < 4; i++)
        pu[i] = bezier_casteljau(P[i], 4, u);

    return bezier_casteljau(pu, 4, v);
}

参考代码 Bezier曲线曲面生成算法 www.youwenfan.com/contentcnu/70189.html

五、工程落地建议(STM32 / GRBL)

只用 3~4 阶 Bezier
预计算 t 表(节省 CPU)
固定点运算(Q16.16)
曲线 → 微小直线段(G-code 兼容)
用于:

  • 圆弧平滑
  • S 形加减速
  • 拐角过渡
  • 机器人末端轨迹

六、常见坑

问题 解决方案
高阶震荡 拆成多段低阶
计算量大 查表 + DMA
不光滑 保证 C¹ 连续
轨迹超界 限制控制点范围
posted @ 2026-05-15 11:13  hczyydqq  阅读(22)  评论(0)    收藏  举报