刚接触运动控制那会儿,我最头疼的就是设备启停的“点头”问题。不管是做3D打印、激光雕刻还是小型机械臂,只要电机带着负载突然加速或者急停,机械结构必然跟着震动,轻则影响表面质量,重则直接把丝杆和联轴器搞坏。后来我从梯形速度规划换到S型曲线速度规划,情况才真正好转。而在所有S型曲线方案里,五段式S型算法是我用得最多、也最愿意拿来给同行分享的一种。
这篇文章就是一份完整的五段式S型算法笔记。我会先把它的原理拆开讲透,再给出参数设计、计算过程、代码实现思路和工程调试中的经验教训。适合正在做运动控制、设备自动化改造,或者刚入门伺服系统调试的工程师参考,也适合那些被梯形加减速困扰、想平滑过渡的爱好者拿来“抄作业”。
1. 五段式S型算法的核心思路与选型分析
1.1 为什么不用梯形速度曲线
梯形速度曲线的最大问题在于加速度突变。它把运动过程简单分成加加速、匀速、减速三段,加速度从零直接跳到最大值,再瞬间回零,换算成力就是给机械结构来了一记瞬态冲击。学过理论力学的朋友都知道,冲击力与加速度的变化率有关,这就是工程上常说的jerk(急动度)。梯形曲线的jerk理论上是无穷大,设备当然会抖。
我曾经在一台自动点胶机上做过对比,同样走50mm,梯形速度规划在终点停稳时,机架要振荡将近0.4秒,点胶针头会留下尾痕;换上五段式S型算法之后,同样的距离、同样的最大速度,停稳时间压缩到0.1秒以内,轨迹末端干净利落。这背后的本质就是:五段式S型算法用有限的加加速度,把“加速度从0到最大”的过程拉长,让速度曲线变成一条光滑的S形,从根本上缓解冲击、减小振动、延长机械寿命。
1.2 五段式S型算法的五个阶段
五段式S型算法把整个运动过程分成五段,前两段负责加速度从0升到最大值再回落到0,中间一段完成匀速或匀加速运动,后两段对称地完成减速控制。
具体来说,这五个阶段分别是:
- 加加速段:加速度从0线性增加到最大值,速度以二次曲线的形式爬升,速度曲线呈下凹形。
- 减加速段:加速度从最大值线性减小到0,速度继续上升,但上升的速率放缓,速度曲线呈上凸形。
- 匀速段:速度维持最大值,加速度为0,对应长距离运动时的稳定输出阶段。
- 加减速段:加速度从0反向增加到负值的最大值,速度开始下降。
- 减减速段:加速度从负最大值恢复到0,速度继续下降直到停止。
实际工程中,如果运动距离比较短,五段里面中间段可能消失,整个曲线退化成四段甚至三段,但前两段和后两段这种S形过渡特征依然保留。这让我想到一个简单的类比:你开车起步,不会一脚把油门踩到底,而是先慢慢加深油门,等速度上来了再逐渐收一点,让车速平顺地稳定在巡航速度上。五段式S型算法干的就是同一件事,只不过换成了电机和控制器。
1.3 五段式与七段式S型曲线的对比
很多资料会提到七段式S型曲线。七段式在五段的基础上多分了“匀加速段”和“匀减速段”,也就是加加速之后有一段加速度恒定保持最大,然后再进入减加速。七段式控制更细腻,但参数更多、计算更复杂。
在实际嵌入式控制器上,如果主频紧张或者插补周期很短,五段式往往更实用。它保留了S型曲线最核心的平滑特性,同时参数少,计算量小,调试周期也短。我的一些设备方案里,对轨迹平滑度要求极高才会用七段式;一般情况下,五段式已经能把震动抑制到很理想的水平,省下的算力还能用来做插补前瞻或其它实时任务。
| 对比维度 | 梯形速度规划 | 五段式S型算法 | 七段式S型曲线 |
|---|---|---|---|
| 加速度变化 | 阶跃突变 | 线性连续 | 线性连续 |
| 急动度(jerk) | 无穷大 | 恒定有限值 | 恒定有限值 |
| 参数数量 | 少 | 中等 | 较多 |
| 计算量 | 小 | 小 | 中等 |
| 平滑性 | 差 | 良好 | 优秀 |
| 适用场景 | 低速、小负载 | 通用运动控制 | 高精度、长距离 |
2. 五段式S型算法的参数设计与公式推导
2.1 基础参数与符号约定
在推导具体公式之前,先把用到的符号统一一下。定义以下参数:
- S:总位移,单位mm或脉冲数。
- V_max:最大速度,单位mm/s。
- A_max:最大加速度,单位mm/s²。
- J:加加速度(jerk),单位mm/s³,表示加速度的变化速率。
五个阶段分别用下标表示,第一阶段加加速段时长设为T1,第二阶段减加速段时长T2,第三段匀速/中间段时长T3,第四段加减速段时长T4,第五段减减速段时长T5。
在五段式S型算法里,T1和T2往往设为相同,T4和T5也设为相同,这是为了对称规划。对称规划的好处很明显:加减速过程完全镜像,计算量减半,而且终点速度必然为0,不需要额外求解余项。
2.2 速度与位移公式推导
以加速阶段为例。第一阶段加加速段内,加速度从0线性增长到A_max,用时间积分可以得到速度公式:
v1(t) = 0.5 * J * t²,其中 t ∈ [0, T1]到第一段结束时,速度达到:
v1_end = 0.5 * J * T1²同时加速度达到A_max,因此有关系式:
A_max = J * T1联立上面两个式子,可以写出第一段结束时的速度:
v1_end = 0.5 * A_max * T1第一段内的位移也对速度积分得到:
s1 = (1/6) * J * T1³ = (1/6) * A_max * T1²第二阶段减加速段里,加速度从A_max线性减到0,速度从第一段末值继续上升,第二段结束时正好达到最大速度V_max。有对称性可得T2 = T1,那么第二段的位移为:
s2 = v1_end * T2 + (1/2) * A_max * T2² - (1/6) * J * T2³代入T2 = T1以及A_max = J * T1,可以化简为:
s2 = (2/3) * A_max * T1² + (1/2) * A_max * T1² - (1/6) * A_max * T1² = (5/6) * A_max * T1²等等,这里我用的是分段积分而不是直接套公式,实际的推导过程要仔细一点。正确的做法是,在减加速段,加速度随时间线性递减,加速度表达式为:
a(t) = A_max * (1 - t / T1),t ∈ [0, T1]对加速度积分得到速度增量,累加上第一段的末速度,然后积分得到位移。通过这个完整计算,可以得到加速段总位移:
S_acc = A_max * T1²而加速段总共用时为:
T_acc = 2 * T1 = 2 * A_max / J同理,在对称条件下,减速段总位移也等于A_max * T1²,减速段总时间也等于2 * T1。
2.3 匀速段时间的计算
走完整段位移时,总位移S由加速段位移、匀速段位移和减速段位移三部分组成,即:
S = S_acc + S_uni + S_dec由于我们保持对称规划,S_acc = S_dec,所以:
S = 2 * S_acc + S_uni如果总位移还比较充裕,S_uni大于0,就可以解出匀速段时间为:
T_uni = (S - 2 * S_acc) / V_max这是长距离运动时的情况。匀速段时间存在,五个阶段完整,整个曲线呈现真正的五段形态。
2.4 短距离时的退化处理
实际工作中经常遇到另一个情况:总位移不够大,按最大速度规划,加速段还没走完就已经到中间点了,此时匀速段时间会变成负值。这明显不合理,因为总位移都不够支撑加速和减速的需求。
这种短距离情况下的处理方法是:重新设定一个更低的峰值速度V_t,让加速段和减速段刚好衔接,即匀速段时间等于0。此时加加速段时间也缩短,整个运动变为“四段”或者“三段”形态,但每一段的S形过渡特征还在。计算公式为:
V_t = sqrt(0.5 * J * S² / (2 * A_max)) (需要结合约束推导)更稳妥的方法是在给定A_max和J的前提下,先计算满足“刚好达到最大速度”所需的最短距离:
S_min = 2 * A_max³ / J²如果总位移S小于S_min,就说明无法达到预先设定的A_max,此时按S的值反推实际能达到的最大加速度或峰值速度。这一步非常关键,做运动控制的同学一定要在代码里加上边界判断,否则会出现轨迹规划越界、电机过冲甚至撞限位的事故。
2.5 参数计算完整示例
举一个实际例子。假设某设备的参数为:
- 总位移S = 100mm
- 最大速度V_max = 100mm/s
- 最大加速度A_max = 500mm/s²
- 加加速度J = 2000mm/s³
先验证能否达到最大速度:
S_min = 2 * 500³ / 2000² = 2 * 125000000 / 4000000 = 62.5mm总位移S = 100mm > S_min,所以可以按完整五段式规划。
加加速段时间:
T1 = A_max / J = 500 / 2000 = 0.25s加速段位移:
S_acc = A_max * T1² = 500 * 0.25² = 31.25mm匀速段位移:
S_uni = 100 - 2 * 31.25 = 37.5mm匀速段时间:
T_uni = 37.5 / 100 = 0.375s加速段时间:
T_acc = 2 * 0.25 = 0.5s总运动时间:
T_total = 0.5 + 0.375 + 0.5 = 1.375s可以看到,整个规划结果是完整、对称、可解析求解的。这种计算方式在MCU上做浮点运算完全没有压力,这也是五段式S型算法能被广泛应用的重要原因之一。
3. 五段式S型算法实操实现与代码思路
3.1 算法初始化流程
在实际工程里,通常把五段式S型算法封装成一个规划器,输入目标位移和运动参数,输出一段离散的位置点或者速度点。初始化流程一般包括这几步:
- 解析输入,校验参数合法性(速度、加速度、加加速度必须大于0,位移可正可负)。
- 根据输入的位移方向,确定运动方向,后续所有计算使用位移绝对值。
- 根据2.4节的判断逻辑,确定运动形态:完整五段还是退化四段。
- 计算各段时间、速度和位移特征量。
- 生成离散规划点,供位置环或速度环使用。
有一个细节容易被忽略:方向处理。如果目标位移为负,需要在规划结束输出位置指令时,把所有位置值取反,而不是在算法内部用负数参与计算。这样能避免大量边界判断,代码也会更清爽。
3.2 核心实现代码示例
下面给出一段简化的Python实现,用来演示五段式S型算法的核心计算逻辑。实际嵌入式代码可以用C写,思路完全一致。
def plan_five_segment_s_curve(S_total, V_max, A_max, J): """ 五段式S型速度规划核心计算 返回一段位移数组 """ direction = 1 if S_total >= 0 else -1 S = abs(S_total) # 边界判断:能否达到最大加速度 S_min = 2 * A_max**3 / (J**2) if S < S_min: # 退化情况:降低峰值加速度 A_max = (S * J**2 / 2)**(1/3) # 重新计算S_min对应的峰值速度 V_t = 0.5 * A_max * (A_max / J) V_max = V_t T1 = A_max / J S_acc = A_max * T1**2 S_uni = S - 2 * S_acc if S_uni > 0: T_uni = S_uni / V_max else: T_uni = 0 T_total = 2 * T1 + T_uni # 生成离散位置曲线 dt = 0.001 # 1ms插补周期 pos_list = [] t = 0.0 pos = 0.0 while t < T_total: if t < T1: # 第一段:加加速段 pos = (1/6) * J * t**3 elif t < T1 + T_uni: # 第二段:减加速段 + 匀速段 t2 = t - T1 pos = S_acc + V_max * t2 elif t < 2 * T1 + T_uni: # 第三段:加减速段(前部分) t3 = t - T1 - T_uni pos = S_acc + V_max * T_uni + V_max * t3 - (1/6) * J * t3**3 else: # 第四段与第五段合并处理:减减速段 t4 = t - T1 - T_uni - T1 pos = S - (1/6) * J * (2*T1 - t4)**3 pos_list.append(direction * pos) t += dt return pos_list这里为了演示做了简化,把减速部分的“加加速段”和“减加速段”用一段对称公式合并处理。真正的工程代码还需要处理速度前馈、加速度前馈和终点对齐,避免最后一个周期出现误差累积。
3.3 离散化误差与插补周期选择
五段式S型算法在理论上是连续的,但实际输出是离散的。插补周期越长,位置点之间的间隔越大,速度波动越明显。我常用的经验法则是:插补周期应保证每个周期内位移增量不超过0.05mm。例如V_max = 100mm/s时,插补周期取1ms,每个周期位移0.1mm,勉强能用;如果要更平滑,可以把周期缩到0.5ms,或者改用位置增量比较平滑的规划方式。
在嵌入式平台上,还需要关注浮点数运算速度和内存占用。五段式规划器本身计算量很小,但离散化输出点的存储需要空间。一个简单的做法是:先计算出各段切换时间点,然后在每个插补周期内实时计算当前位置,而不是预先存储一整条轨迹。这样可以大幅减少内存占用,更适合STM32这类资源有限的MCU。
4. 调参技巧与工程踩坑实录
4.1 参数标定的优先级
调到五段式S型算法时,很多人一上来就改J(加加速度),发现效果不明显,又改A_max,来回折腾。我给的建议是,优先确认V_max和A_max是否匹配负载,最后再调J。
原因很简单:五段式的平滑性主要来自J,但J不能无限大,否则S形曲线会退化成近似梯形。如果机械共振点恰好在某个J值激励的能量频段内,反而会放大振动。一般先根据电机额定转矩和负载惯量估算出最大加速度,设置一个保守初始值,比如A_max = 0.5 * 额定最大加速度;然后从小到大慢慢调J,每次只调10%到20%,观察振动和噪声。
4.2 长距离与小位移的组合策略
设备工况如果同时包含长行程和短行程,不能只用一组固定的V_max、A_max和J。长行程需要大刀阔斧地加减速,短行程如果沿用同样的参数,结果就是“刚进入S形加速段就要减速”,曲线严重退化,操作效果和梯形差不多。
我的做法是做两套参数表,按位移长度自动切换参数。比如位移小于10mm时,A_max缩小到正常的60%,J缩小到正常的50%;位移大于100mm时,使用正常参数。这样能让短行程保留S形过渡的平滑特性,同时不显著拉长加工时间。代价是代码里多一张参数映射表,但效果立竿见影。
4.3 不同负载下的参数调整
负载变化对S型算法的影响非常大。同一套参数,空载时机架几乎无振动,满载后可能抖动得像筛子。这是因为负载惯量变大后,实际加速度响应变慢,电机实际输出的加速度跟不上规划,造成跟踪误差。
针对这种情况,最实用的技巧是:用示波器或驱动器自带的数据记录功能,抓取速度反馈曲线和位置误差曲线。如果速度反馈曲线在加减速衔接处出现小台阶,说明规划的加速度阶跃仍偏大,可以降低A_max;如果位置误差持续增大,说明A_max超出电机能力,必须减小。纯粹靠耳朵听、靠手摸,很难定位问题。
4.4 多轴协同时的参数匹配
五段式S型算法在多轴联动时有个很容易踩的坑:各轴参数如果不一样,各轴到达目标点的时间会不同,导致合成轨迹跑偏。比如X轴用了五段式,Y轴也用了五段式,但两轴的V_max和A_max不同,XY插补出来的圆弧就不再是圆,而是扁圆。
解决思路有两个:
- 所有轴采用相同的S型参数,简单粗暴但适合大部分场景。
- 先在轨迹层做前瞻规划,规划出一条统一的时标曲线,再把各轴位移映射到这条时标上。
第一种方案容易实现,第二种方案精度更高。对于用量产控制器或者固高的用户来说,通常不需要自己处理这个层次的问题;但如果你在用自研运动控制系统,这一点要特别留意。
5. 常见问题与排查技巧实录
5.1 问题速查表
| 现象 | 可能原因 | 排查方向 | 解决方案 |
|---|---|---|---|
| 启动瞬间有“咔哒”冲击声 | 加加速度J过大,S形过渡不明显 | 查看速度曲线是否接近梯形 | 减小J,设置初始值再逐步增大 |
| 终点定位过冲 | 匀速段时间计算错误,位移分配不均衡 | 核对S_acc计算结果 | 用2.5节示例公式手算一遍参数 |
| 轨迹末端振荡明显 | 加速度变化率仍然过大 | 抓取速度反馈曲线 | 降低A_max或J,必要时加滤波 |
| 多轴联动轨迹跑偏 | 各轴时间参数不一致 | 对比各轴到达时间 | 统一S型参数或做时标映射 |
| 短距离段平滑性差 | 退化状态下参数未重新标定 | 检查是否走退化分支 | 按位移长度切换参数表 |
| 电机跟丢或报警 | 规划速度超出驱动能力 | 检查位置误差曲线 | 降低V_max,或升级驱动器 |
5.2 “终点最后一毫米”的顽固问题
我最常被问到的其实是“明明算法算好了,为什么停下来的位置总差一点”。排查下来,大多不是五段式算法的问题,而是终点前的最后1mm处理不当。
五段式算法规划到理论终点时速度恰好为0,但如果上位机下发了一个新的运动指令,或者插补周期与通信周期不对齐,控制器会在终点附近插入一条微小梯形速度段,相当于人为制造了一个加速度突变,设备自然又抖了一下。解决方法是:规划器必须在每个插补周期都检查当前位置是否到达终点,到达终点后立即清空速度指令,并把位置环切到到位保持模式。
5.3 离线仿真与实测的差距
还有一个经验教训:五段式算法离线仿真曲线完美,不代表实测效果一样好。因为实际系统存在摩擦、间隙、弹性形变,这些非线性因素会把理想S形曲线“拉歪”。所以我在调试时从来不只是看上位机里的理想曲线,而是花时间看实际反馈的加速度计波形或者电机电流波形。
有一次我在一台高速贴片机上发现,加速度计测出来的峰值振动频率和S形曲线加加速段频率刚好接近,导致轻微共振。缩小J以后,振动幅度降低了将近40%,但加工时间只增加了不到10%。这种“以少量时间换明显减振”的收益,在很多场景下都很划算。
6. 从算法笔记到工程落地的几点心得体会
写到这里,五段式S型算法从原理、公式、代码到调参和排查,基本都过了一遍。最后分享几个我在实际项目里摸索出来的习惯,希望对大家有帮助。
第一,永远先做边界判断。不管输入参数怎么变,先判断总位移是否足够,再规划完整五段还是退化四段。这个if判断能省掉后面一大堆bug。
第二,保留一份手算验证的Excel表。每实现一种新的S型规划器,我都会把公式写在Excel里,填入典型参数手算一遍结果,再用代码跑一遍对比。对不上就说明代码里某个积分、位移累加写错了。这种笨办法帮我抓出过好几次低级错误。
第三,记录参数和波形的对应关系。我在调设备时会记录一组数据:V_max、A_max、J、负载质量、速度反馈波形截图。时间久了就形成了一张自己的调参经验库。下次遇到相似工况,直接调用经验值,调试时间至少缩短一半。
第四,假如条件允许,优先在驱动层开启S型规划。很多伺服驱动器和步进驱动器自带S型加减速功能,此时嵌入式端不必重复实现算法,直接配置寄存器参数即可,省心也稳定。只有当驱动器不支持或者需要联动规划时,才在控制器端做五段式S型算法。
我在实际使用中发现,五段式S型算法并不复杂,但它解决的是运动控制里“加速度突变”这个老问题,带来的是实实在在的减振收益。如果你正在被设备抖动、撞击声和轨迹偏差困扰,不妨试试从梯形规划切到五段式S型规划,大概率会有惊喜。