速度规划配置与轨迹规划联动 - 第2节

梯形速度规划:原理与数学公式

梯形速度规划,说白了就是让电机先匀加速、再匀速、最后匀减速。你想想看,这就像开车——红灯变绿时一脚油门踩到限速,然后匀速巡航,快到路口了再踩刹车。简单、直观、好算,工业现场用得最多的就是它。

我个人习惯把梯形规划叫做“三段式”,因为它的速度曲线就三段:加速段、匀速段、减速段。加速度在每一段里都是常数,所以速度变化是线性的。嗯,这里要注意:加速度突变的地方,就是加加速度(Jerk)无穷大的位置——后面我们会聊怎么处理这个冲击。

数学公式推导

假设我们要从起点 P₀ 运动到终点 P₁,总位移为 S,最大速度为 Vmax,加速度为 A(加速和减速的绝对值相等)。那么三段的时间分别是:

  • 加速时间:t₁ = Vmax / A
  • 减速时间:t₃ = Vmax / A(对称情况)
  • 匀速时间:t₂ = (S - A·t₁²) / Vmax

总时间就是 T = t₁ + t₂ + t₃。我在项目中遇到过一种情况:位移太短,还没加速到 Vmax 就得开始减速了。这时候就没有匀速段,我们叫它“三角形速度规划”。

关键判断条件:如果 S < Vmax² / A,说明位移不够,跑不到最大速度。此时实际最大速度 Vpeak = √(A·S),加速和减速时间各为 t = Vpeak / A。

位置与速度的实时计算

在每一时刻 t,我们可以分段计算速度和位置:

时间段 速度 v(t) 位置 p(t)
0 ≤ t < t₁ A·t ½·A·t²
t₁ ≤ t < t₁+t₂ Vmax ½·A·t₁² + Vmax·(t - t₁)
t₁+t₂ ≤ t ≤ T Vmax - A·(t - t₁ - t₂) ½·A·t₁² + Vmax·t₂ + Vmax·(t - t₁ - t₂) - ½·A·(t - t₁ - t₂)²

这些公式看着有点多,但写代码时就是几个 if-else 的事。我建议你把它们封装成一个函数,输入时间 t,输出速度和位置——后面做轨迹插补时直接调用就行。

加加速度与冲击限制

梯形规划有个硬伤:加速度在切换点瞬间跳变。你想想看,加速度从 0 直接跳到 A,又从 A 直接跳回 0——这意味着加加速度(Jerk)是无穷大。机械上会怎样?冲击、振动、甚至损坏丝杠或导轨。

我曾经调试一台高速贴片机,梯形规划跑出来的加速度曲线像锯齿一样。机器一启动就“哐”一声,导轨上的工件都跟着抖。后来加了 Jerk 限制,改成 S 形速度规划,问题才解决。

加加速度的定义

加加速度就是加速度的变化率:

Jerk = dA / dt

单位是 m/s³ 或 mm/s³。梯形规划的 Jerk 在切换点理论上无穷大,实际中受限于控制周期和机械响应,会表现为一个很陡的斜坡——但依然会造成冲击。

注意:如果你在梯形规划里直接限制 Jerk,那就变成了 S 形规划。梯形规划本身不处理 Jerk,所以如果你的设备对冲击敏感(比如精密加工、晶圆搬运),建议直接上 S 形或更高阶规划。

什么时候可以忽略 Jerk?

也不是所有场合都需要限制 Jerk。我列几个典型场景:

  • 可以忽略:传送带启停、低速搬运、大惯量负载(冲击被惯性吸收)
  • 必须考虑:高速高精度定位、轻载易振动结构、末端有易碎物品
  • 折中方案:在梯形规划的切换点插入一小段圆弧过渡,近似限制 Jerk

代码实现与参数配置

下面给出一段 C 风格的梯形规划实现。我习惯把参数放在结构体里,方便配置和调试。

typedef struct {
    float pos_start;   // 起始位置
    float pos_end;     // 终点位置
    float vel_max;     // 最大速度
    float acc;         // 加速度(绝对值)
    float dec;         // 减速度(绝对值,可与加速度不同)
    float t_acc;       // 加速时间(计算输出)
    float t_dec;       // 减速时间(计算输出)
    float t_const;     // 匀速时间(计算输出)
    float t_total;     // 总时间(计算输出)
    float vel_peak;    // 实际达到的最大速度(计算输出)
} TrapezoidProfile;

void TrapezoidProfile_Calc(TrapezoidProfile *p) {
    float S = p->pos_end - p->pos_start;
    float v_max_allowed = p->vel_max;
    float a = p->acc;
    float d = p->dec;

    // 计算理论加速和减速距离
    float dist_acc = 0.5f * v_max_allowed * v_max_allowed / a;
    float dist_dec = 0.5f * v_max_allowed * v_max_allowed / d;

    if (dist_acc + dist_dec <= S) {
        // 有匀速段
        p->vel_peak = v_max_allowed;
        p->t_acc = v_max_allowed / a;
        p->t_dec = v_max_allowed / d;
        p->t_const = (S - dist_acc - dist_dec) / v_max_allowed;
    } else {
        // 无匀速段,三角形规划
        // 解方程求实际峰值速度
        float v_peak = sqrtf(2.0f * a * d * S / (a + d));
        p->vel_peak = v_peak;
        p->t_acc = v_peak / a;
        p->t_dec = v_peak / d;
        p->t_const = 0.0f;
    }
    p->t_total = p->t_acc + p->t_const + p->t_dec;
}

我的经验:加减速度可以设成不同值。比如上升时用大加速度快速启动,下降时用小减速度防止过冲。我在做龙门架时就这么配的——效果比对称加减速好不少。

参数配置建议

配置梯形规划时,我一般按这个顺序来:

  1. 先定最大速度:看电机额定转速和机械限速,取较小值
  2. 再定加速度:根据负载惯量和电机扭矩算,留 20% 余量
  3. 最后调减速度:如果定位有超调,就减小减速度
  4. 检查位移是否足够:不够就自动降速(代码里已经处理了)

我曾经遇到一个坑:加速度设得太大,电机扭矩够,但联轴器打滑了。嗯,从那以后我每次都会校核机械部件的承受能力,不只是算电机参数。

梯形规划知识体系

梯形速度规划知识体系 梯形速度规划 原理与三段式结构 数学公式推导 加加速度与冲击 加速段 匀速段 减速段 速度/位置分段公式 三角形规划(无匀速段) Jerk 无穷大问题 适用场景判断 代码实现与参数配置 核心:三段式速度曲线 加速度恒定,速度线性变化

这张图把梯形规划的核心脉络理清了。你从根节点往下看:原理、公式、冲击分析,最后汇聚到代码实现。我个人建议初学者先吃透三段式结构和三角形规划的判断条件——这两个搞懂了,梯形规划就算拿下了八成。