梯形速度曲线:原理、数学模型、起止速度不为零的通用情况
梯形速度曲线,说白了就是让机器人先匀加速、再匀速、最后匀减速。这个名字很形象——你把速度画出来,形状就是个梯形。我在刚入行那会儿,觉得这东西太简单了,不就是个加减速嘛。后来真到现场调机器人,才发现里面坑不少。
今天咱们就把梯形速度曲线掰开揉碎了讲。从原理到数学,再到起止速度不为零的通用情况,一步到位。
1. 梯形速度曲线的核心思想
为什么叫梯形?你想想看:
- 加速段:速度从起始值线性增加到目标值
- 匀速段:保持目标速度运行
- 减速段:速度从目标值线性减小到终止值
这三段拼在一起,速度曲线就是个梯形。如果起始速度和终止速度都是零,那就是个标准的等腰梯形。但实际项目中,起止速度往往不为零——比如机器人抓完一个工件,还没完全停下来就要去下一个点。这时候梯形就变成「斜边梯形」了。
核心要点:梯形速度曲线本质上是「三段式」运动规划。每一段都是恒定的加速度或零加速度。数学上简单,工程上好用。
2. 数学模型:从物理到公式
咱们先定义几个符号:
v₀:起始速度v₁:终止速度v_max:最大速度(匀速段速度)a_max:最大加速度(绝对值)d_max:最大减速度(绝对值)s:总位移t:总时间
嗯,这里要注意:加速和减速的加速度不一定相等。我见过不少教材默认加减速对称,但实际项目中,电机加速能力和减速能力往往不同。比如垂直轴,上升和下降的加速度就得分开设。
2.1 加速段时间和位移
加速段从 v₀ 加速到 v_max,加速度为 a_max:
t₁ = (v_max - v₀) / a_max
s₁ = v₀ * t₁ + 0.5 * a_max * t₁²
2.2 减速段时间和位移
减速段从 v_max 减速到 v₁,减速度为 d_max:
t₃ = (v_max - v₁) / d_max
s₃ = v_max * t₃ - 0.5 * d_max * t₃²
2.3 匀速段时间和位移
剩下的位移就是匀速段走的:
s₂ = s - s₁ - s₃
t₂ = s₂ / v_max
如果 s₂ < 0,说明位移太短,根本到不了最大速度。这时候就没有匀速段,曲线变成「三角形」——只有加速和减速。
注意:当 s₂ < 0 时,需要重新计算实际能达到的最大速度。这个情况我在项目中踩过坑——直接按原公式算,结果时间算出来是负数,电机直接报错。
3. 起止速度不为零的通用情况
这才是梯形速度曲线的完整形态。我建议你直接把这个通用公式记下来,因为实际项目中99%的情况都用得到。
3.1 通用公式推导
假设起始速度 v₀ 和终止速度 v₁ 都不为零,且可能不相等。那么:
- 加速段:从
v₀到v_max,加速度a_max - 匀速段:保持
v_max - 减速段:从
v_max到v₁,减速度d_max
关键判断:能不能达到 v_max?
// 计算加速和减速所需的最小位移
s_min_acc = (v_max² - v₀²) / (2 * a_max)
s_min_dec = (v_max² - v₁²) / (2 * d_max)
if (s_min_acc + s_min_dec <= s) {
// 能达到 v_max,有匀速段
} else {
// 达不到 v_max,需要重新计算实际最大速度
// 解方程:v_actual² - v₀²)/(2*a_max) + (v_actual² - v₁²)/(2*d_max) = s
v_actual = sqrt((2*a_max*d_max*s + d_max*v₀² + a_max*v₁²) / (a_max + d_max))
}
这个公式看着有点复杂,但说白了就是能量守恒的思路——加速段「赚」的位移加上减速段「花」的位移,不能超过总位移。
3.2 特殊情况处理
| 情况 | 说明 | 处理方式 |
|---|---|---|
| v₀ = v₁ = 0 | 标准梯形 | 直接用对称公式 |
| v₀ = v₁ ≠ 0 | 起止速度相同 | 加速和减速对称,但起始速度不为零 |
| v₀ ≠ v₁ | 起止速度不同 | 加速和减速不对称,分别计算 |
| v₀ > v_max | 起始速度超限 | 直接进入减速段,没有加速 |
| v₁ > v_max | 终止速度超限 | 先减速到 v_max,再加速到 v₁(少见) |
我的经验:起止速度不为零时,最容易出问题的是「速度方向相反」的情况。比如机器人正往东走,突然要往西走。这时候必须先减速到零,再反向加速。梯形速度曲线处理不了这种「过零」情况,得用S形曲线或者分段规划。
4. 梯形速度曲线的优缺点
说实话,梯形速度曲线在工业机器人里用得越来越少。但作为入门,它依然是必学的。为什么?
- 优点:计算简单、实时性好、容易理解
- 缺点:加速度突变(加加速度无穷大),导致机械冲击
我记得有一次调试一个六轴机器人,用梯形速度曲线跑一个高速拾取动作。结果每次加减速的时候,末端都会抖一下。后来换成S形曲线,抖动就消失了。但梯形曲线在低速、轻载的场合,完全够用。
5. 代码实现示例
下面是一个完整的梯形速度曲线规划函数。我习惯用C风格写,方便移植到嵌入式系统:
typedef struct {
float v0; // 起始速度
float v1; // 终止速度
float v_max; // 最大速度
float a_max; // 最大加速度
float d_max; // 最大减速度
float s; // 总位移
} TrapezoidProfile;
typedef struct {
float t1; // 加速段时间
float t2; // 匀速段时间
float t3; // 减速段时间
float v_actual; // 实际最大速度
int has_cruise; // 是否有匀速段
} TrapezoidResult;
void trapezoid_plan(TrapezoidProfile *p, TrapezoidResult *r) {
// 计算加速和减速所需的最小位移
float s_acc = (p->v_max * p->v_max - p->v0 * p->v0) / (2.0f * p->a_max);
float s_dec = (p->v_max * p->v_max - p->v1 * p->v1) / (2.0f * p->d_max);
if (s_acc + s_dec <= p->s) {
// 能达到最大速度
r->v_actual = p->v_max;
r->has_cruise = 1;
r->t1 = (p->v_max - p->v0) / p->a_max;
r->t3 = (p->v_max - p->v1) / p->d_max;
r->t2 = (p->s - s_acc - s_dec) / p->v_max;
} else {
// 达不到最大速度,重新计算
r->has_cruise = 0;
float a = p->a_max;
float d = p->d_max;
float num = 2.0f * a * d * p->s + d * p->v0 * p->v0 + a * p->v1 * p->v1;
float den = a + d;
r->v_actual = sqrtf(num / den);
r->t1 = (r->v_actual - p->v0) / a;
r->t3 = (r->v_actual - p->v1) / d;
r->t2 = 0.0f;
}
}
注意:实际工程中,还要考虑速度方向、加速度限制、电机力矩饱和等问题。上面的代码只是一个基础框架,真正用的时候要加边界检查和异常处理。
6. 梯形速度曲线的可视化
下面我用SVG画一个梯形速度曲线的示意图。加速段、匀速段、减速段一目了然:
这张图里,起始速度 v₀ 和终止速度 v₁ 都不为零。你可以看到加速段和减速段的斜率不同——这就是加减速不对称的情况。实际项目中,这种不对称很常见。
7. 避坑指南
最后,分享几个我踩过的坑:
- 我曾经在计算加速段位移时,忘了考虑起始速度。结果加速段算短了,机器人冲过头。记住:
s₁ = v₀*t₁ + 0.5*a*t₁²,不是0.5*a*t₁²。 - 我曾经在起止速度不同时,直接用了对称公式。结果减速段算出来是负数。后来才意识到,起止速度不同时,加减速必须分开算。
- 我建议在代码里加一个「速度方向一致性检查」。如果
v₀和v₁方向相反,直接报错或者切换到更复杂的规划算法。
小技巧:调试梯形速度曲线时,先把加速度设小一点(比如最大值的10%),跑一遍看看曲线形状对不对。确认没问题了,再慢慢加大加速度。这样能避免电机过载或者机械冲击。
梯形速度曲线虽然简单,但它是所有轨迹规划算法的基础。把它的原理和数学模型吃透了,后面学S形曲线、多项式曲线都会轻松很多。嗯,今天就到这里。
公众号:蓝海资料掘金营,微信deep3321