3. S形速度规划:平滑与冲击的博弈

梯形速度规划简单粗暴,但有个硬伤——加速度突变。你想想看,电机在启动瞬间从0加速到满加速度,那一下冲击力,对机械结构是实打实的伤害。我最早做自动化设备时,就吃过这个亏。后来才明白,真正工程上能用的,是S形速度规划。

3.1 加加速度(Jerk)——被忽视的关键参数

先聊一个概念:加加速度(Jerk)。说白了,就是加速度的变化率。

  • 加速度:速度的变化率(m/s²)
  • 加加速度:加速度的变化率(m/s³)

为什么梯形曲线有冲击?因为它在加减速切换点,加速度瞬间跳变。Jerk 理论上无穷大。而S形曲线,就是通过限制 Jerk,让加速度平滑过渡。

核心观点: 梯形曲线控制的是速度,S形曲线控制的是加速度。S形曲线本质上是对加速度再做一次平滑。

我在调试高速贴片机时遇到过,梯形曲线跑出来的振动,在末端会反弹回来,导致定位精度下降。换成S形曲线后,同样的运动时间,末端抖动直接降了60%。这就是Jerk约束的价值。

3.2 S形曲线的7段式模型

标准的S形速度规划,分为7个阶段。我习惯叫它「三段加速、三段减速、一段匀速」。具体来看:

阶段 名称 加速度状态 Jerk状态
1 加加速度段 正向增加 正向恒定
2 匀加速段 正向恒定 0
3 减加速度段 正向减小 负向恒定
4 匀速段 0 0
5 加减速度段 负向增加 负向恒定
6 匀减速段 负向恒定 0
7 减减速度段 负向减小 正向恒定

嗯,这里要注意:并不是所有运动都必须走满7段。如果距离太短,匀加速段(第2段)和匀减速段(第6段)可能会消失,变成5段甚至3段。我刚开始做规划时,没考虑这个边界情况,结果短距离运动时曲线直接崩了。

实战经验: 当运动距离小于某个阈值时,S形曲线会自动退化为三角形或梯形。这个阈值取决于你设定的最大加速度和最大Jerk。建议在代码里加一个判断分支,避免数学计算溢出。

3.3 S形曲线相比梯形曲线的优势

梯形曲线和S形曲线,到底差在哪?我用一个表格对比:

对比项 梯形曲线 S形曲线
加速度变化 阶跃跳变 连续平滑
Jerk 无穷大(理论) 有限值(可配置)
机械冲击 大,易产生振动 小,抑制残余振动
运动时间 最短(理论最优) 略长(约5%~15%)
定位精度 受振动影响 更稳定
适用场景 低精度、低成本 高精度、高速、重载

说白了,梯形曲线追求的是「快」,S形曲线追求的是「稳」。在工业机器人、数控机床、高精度贴片机这些场景,稳比快更重要。我曾经调试一台龙门架,用梯形曲线跑,末端抖动幅度有0.3mm;换成S形曲线后,抖动降到0.05mm以内。代价只是运动时间多了8%。

3.4 平滑性与冲击抑制的工程意义

为什么平滑性这么重要?因为机械系统有固有频率。当梯形曲线的加速度跳变频率接近机械共振频率时,会激发大幅振动。这就是所谓的「冲击激励」。

S形曲线通过限制Jerk,把加速度的变化率控制在一个安全范围内。这样,激励的能量被分散到更宽的频带上,不会集中在共振点附近。

避坑指南: 我曾经遇到过,把Jerk设得太小,结果运动时间暴增30%,反而因为低速爬行导致摩擦力不均匀,定位精度下降。Jerk不是越小越好,需要根据机械刚度和负载惯量来折中。一般建议Jerk值设为最大加速度的10~20倍。

另外,S形曲线还有一个隐藏优势:对电机电流的冲击更小。梯形曲线在加速度跳变时,电流会瞬间拉高,容易触发驱动器的过流保护。S形曲线让电流平滑上升,对电机和驱动器都更友好。

3.5 S形曲线核心逻辑流程图

下面这张图,是我做S形规划时常用的决策流程。它帮你判断当前运动应该走几段,以及如何计算各段的时间参数。

S形速度规划核心决策流程 输入:距离、速度、加速度、Jerk 距离是否足够达到最大速度? 计算理论最大速度 vs 实际距离 否 是 退化为三角形/梯形 无匀速段,5段或3段 完整7段S形曲线 包含匀速段 计算各段时间参数 T1=T3=T5=T7, T2=T6, T4 输出速度曲线 说明:当距离不足时,S形曲线会自动降级为5段或3段,避免数学计算溢出

3.6 代码实现要点

最后,给一段S形规划的核心计算片段。这是我在实际项目中用的简化版,重点展示各段时间的计算逻辑:

// S形曲线时间参数计算(简化版)
// 输入:总距离 S,最大速度 Vmax,最大加速度 Amax,最大加加速度 Jmax

// 1. 计算加速阶段时间(假设对称)
float T_acc = Amax / Jmax;           // 加加速度段时间
float T_ramp = Vmax / Amax;          // 理论加速总时间

// 2. 判断是否达到最大速度
float S_acc = Amax * T_ramp * T_ramp; // 加速段所需距离
if (S < 2 * S_acc) {
    // 距离不足,降级为三角形
    // 重新计算实际可达速度
    V_actual = sqrt(Amax * S);
    T_ramp = V_actual / Amax;
    T4 = 0;  // 无匀速段
} else {
    // 完整7段
    T4 = (S - 2 * S_acc) / Vmax;  // 匀速段时间
}

// 3. 各段时间赋值
float T1 = T_acc;   // 加加速度段
float T2 = T_ramp - T_acc;  // 匀加速段
float T3 = T_acc;   // 减加速度段
float T5 = T_acc;   // 加减速度段
float T6 = T_ramp - T_acc;  // 匀减速段
float T7 = T_acc;   // 减减速度段

个人习惯: 我一般会在代码里加一个「时间同步」步骤。因为浮点运算有误差,各段时间加起来可能不等于总时间。我会在最后做一个归一化处理,确保时间轴闭合。

嗯,S形曲线到这里基本讲透了。它比梯形曲线多了一个Jerk维度,换来的是平滑性和冲击抑制。代价是计算复杂了一点,运动时间长了5%~15%。但在高精度场景下,这个代价完全值得。