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形规划时常用的决策流程。它帮你判断当前运动应该走几段,以及如何计算各段的时间参数。
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%。但在高精度场景下,这个代价完全值得。