Bezier 曲线/曲面是 CNC、机器人、矢量图形和运动规划中最常用的轨迹生成工具。
一、Bezier 曲线数学本质
Bezier 曲线 = 控制点加权叠加 + Bernstein 多项式
定义式
给定 ( n+1n+1n+1 ) 个控制点 ( P0...PnP_0 \dots P_nP0...Pn ):
B(t)=∑i=0n(ni)(1−t)n−itiPi,t∈[0,1]B(t) = \sum_{i=0}^{n} \binom{n}{i}(1-t)^{n-i}t^i P_i,\quad t\in[0,1]B(t)=∑i=0n(in)(1−t)n−itiPi,t∈[0,1]
优点:
- 必过起点和终点
- 曲线被控制多边形"包裹"
- 连续、平滑、易求导
缺点:
- 高阶不稳定(>6 阶不建议)
二、最推荐:De Casteljau 算法
这是数值最稳定、最适合 MCU 的实现方法。
1、几何意义
在每条线段上按比例 ( t ) 取点,逐层递归,直到只剩一个点 ------ 那就是曲线上的点。
2、二维 Bezier 曲线(C 代码)
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(通用版)
c
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、生成轨迹点(插补)
c
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∑i=0n−1(Pi+1−Pi)Bi,n−1(t)B'(t) = n\sum_{i=0}^{n-1}(P_{i+1}-P_i)B_{i,n-1}(t)B′(t)=n∑i=0n−1(Pi+1−Pi)Bi,n−1(t)
c
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)=∑i=0n∑j=0mBin(u)Bjm(v)PijS(u,v)=\sum_{i=0}^{n}\sum_{j=0}^{m}B_i^n(u)B_j^m(v)P_{ij}S(u,v)=∑i=0n∑j=0mBin(u)Bjm(v)Pij
2、直观理解
- u 方向一条 Bezier
- v 方向一条 Bezier
- 网格控制点 → 曲面
3、代码
c
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/contentcsu/70189.html
五、工程落地建议(STM32 / GRBL)
只用 3~4 阶 Bezier
预计算 t 表(节省 CPU)
固定点运算(Q16.16)
曲线 → 微小直线段(G-code 兼容)
用于:
- 圆弧平滑
- S 形加减速
- 拐角过渡
- 机器人末端轨迹
六、常见坑
| 问题 | 解决方案 |
|---|---|
| 高阶震荡 | 拆成多段低阶 |
| 计算量大 | 查表 + DMA |
| 不光滑 | 保证 C¹ 连续 |
| 轨迹超界 | 限制控制点范围 |