梯形曲线数学模型:匀加速段、匀速段、匀减速段的三段式结构
好,咱们接着聊。上一章我讲了梯形曲线的基本概念,说白了就是「加速-匀速-减速」这么个三段式。这一章,咱们把它的数学模型彻底掰开揉碎了讲清楚。
我个人习惯,在写任何运动控制代码之前,先把数学公式在纸上推一遍。为什么?因为公式里藏着所有边界条件。你想想看,如果连加速度、速度、位移的关系都没搞明白,写出来的代码大概率会撞限位。
三段式的数学本质
梯形曲线,本质上就是三个时间段,每个时间段对应一个运动学方程。咱们用最经典的物理公式:
- 匀加速段:速度从0线性增加到目标速度V
- 匀速段:速度保持V不变
- 匀减速段:速度从V线性减小到0
嗯,这里要注意一点:加速和减速的加速度大小可以不同。我在项目中遇到过,有些设备为了减少冲击,减速段的加速度会设得比加速段小。但为了简化讨论,咱们先假设加减速对称,即加速度大小相等。
核心公式推导
设总位移为S,目标速度为V,加速度为a。那么三段的时间分别为:
- 加速时间:t₁ = V / a
- 减速时间:t₃ = V / a(对称情况)
- 匀速时间:t₂ = (S - V²/a) / V
这里有个关键点:匀速段的时间不能为负数。如果S太小,导致S - V²/a < 0,那就说明根本跑不到目标速度。这种情况我称之为「三角曲线」——只有加速和减速,没有匀速段。
避坑指南:我曾经在调试一台高速贴片机时,发现运动轨迹总是抖动。查了半天,原来是位移太短,梯形曲线自动退化为三角曲线,但我的速度规划没做边界处理。从那以后,我每次写梯形曲线代码,都会先判断S是否大于V²/a。
位置与时间的分段函数
把三段的位置公式写出来,就是这样的分段函数:
# 匀加速段 (0 ≤ t ≤ t₁)
position = 0.5 * a * t²
velocity = a * t
# 匀速段 (t₁ < t ≤ t₁ + t₂)
position = 0.5 * a * t₁² + V * (t - t₁)
velocity = V
# 匀减速段 (t₁ + t₂ < t ≤ t₁ + t₂ + t₃)
position = 0.5 * a * t₁² + V * t₂ + V * (t - t₁ - t₂) - 0.5 * a * (t - t₁ - t₂)²
velocity = V - a * (t - t₁ - t₂)
你看,其实不复杂。每个阶段都是二次函数或一次函数。但实际编程时,我建议用时间累加器的方式,而不是直接套公式。为什么?因为实时系统里,时间往往是离散的,用累加器更容易处理中断和插补。
关键参数表
为了方便查阅,我把三个阶段的特征参数整理成表格:
| 阶段 | 时间范围 | 速度表达式 | 位移表达式 |
|---|---|---|---|
| 匀加速 | [0, t₁] | v = a·t | s = ½·a·t² |
| 匀速 | [t₁, t₁+t₂] | v = V | s = ½·a·t₁² + V·(t-t₁) |
| 匀减速 | [t₁+t₂, T] | v = V - a·(t-t₁-t₂) | s = ½·a·t₁² + V·t₂ + V·(t-t₁-t₂) - ½·a·(t-t₁-t₂)² |
其中T = t₁ + t₂ + t₃,是总运动时间。
梯形曲线的SVG结构图
下面这张图,是我用SVG画的梯形曲线三段式结构。你可以清晰地看到速度随时间的变化:
这张图里,红色是加速段,绿色是匀速段,蓝色是减速段。你注意看,加速和减速的斜率绝对值相等,这就是对称梯形曲线。如果斜率不同,那就是非对称梯形,咱们后面再聊。
实际编程中的离散化处理
理论公式讲完了,但实际写代码时,你不能直接用连续时间公式。为什么?因为运动控制器的周期是固定的,比如1ms或100μs。你需要把连续时间离散化。
我常用的做法是这样的:
# 伪代码示例:梯形曲线离散化
def trapezoidal_profile(total_distance, max_velocity, acceleration, dt):
# 计算理论时间
t_acc = max_velocity / acceleration
t_dec = max_velocity / acceleration
t_const = (total_distance - max_velocity**2 / acceleration) / max_velocity
# 如果匀速段时间为负,退化为三角曲线
if t_const < 0:
# 重新计算最大可达速度
max_velocity = sqrt(acceleration * total_distance)
t_acc = max_velocity / acceleration
t_dec = max_velocity / acceleration
t_const = 0
total_time = t_acc + t_const + t_dec
num_steps = int(total_time / dt)
# 离散化输出
positions = []
for i in range(num_steps):
t = i * dt
if t <= t_acc:
# 加速段
pos = 0.5 * acceleration * t**2
elif t <= t_acc + t_const:
# 匀速段
pos = 0.5 * acceleration * t_acc**2 + max_velocity * (t - t_acc)
else:
# 减速段
t_dec_local = t - t_acc - t_const
pos = 0.5 * acceleration * t_acc**2 + max_velocity * t_const \
+ max_velocity * t_dec_local - 0.5 * acceleration * t_dec_local**2
positions.append(pos)
return positions
小技巧:我建议在离散化时,把时间步长dt设得比控制周期略小一点,比如控制周期是1ms,dt设成0.95ms。这样能避免因为浮点误差导致最后一个点超出总位移。嗯,这个坑我踩过,当时一个伺服电机在终点位置来回震荡,就是因为最后一个点的位置指令超过了目标值。
边界条件与异常处理
梯形曲线看起来简单,但实际应用中,边界条件才是最容易出问题的地方。我总结了几种常见情况:
- 位移太小:S < V²/a,无法达到目标速度,退化为三角曲线
- 加速度太小:加速段太长,导致总时间超出工艺要求
- 速度太小:V太小,匀速段几乎不存在,曲线接近三角
- 非对称加减速:加速和减速的加速度不同,需要分别计算t₁和t₃
我记得有一次调试一个龙门架,客户要求加速要柔和,减速要快速。这就是典型的非对称梯形曲线。加速段加速度0.5m/s²,减速段加速度2m/s²。公式就要拆开算:t₁ = V/a₁,t₃ = V/a₃,匀速段时间 t₂ = (S - V²/(2a₁) - V²/(2a₃)) / V。
警告:非对称梯形曲线中,如果加速和减速的加速度差异过大,可能会导致匀速段时间为负。这时候不能简单退化为三角曲线,因为三角曲线假设对称。你需要重新计算一个「等效加速度」或者采用更复杂的S形曲线。我建议在代码里加一个检查:如果t₂ < 0,就报错并提示用户调整参数。
总结一下
梯形曲线的数学模型,说白了就是三个二次函数拼在一起。但真正用好它,你得理解三个关键点:
- 时间计算:t₁、t₂、t₃的公式要烂熟于心
- 边界判断:时刻检查匀速段时间是否为正
- 离散化处理:连续公式到离散代码的转换要小心浮点误差
我个人觉得,梯形曲线是所有运动控制曲线的基础。你把它的数学模型吃透了,后面学S形曲线、多项式曲线都会轻松很多。下一章咱们会聊梯形曲线的代码实现,到时候我会给出一个完整的Python类,包含速度规划、位置插补和实时监控。
公众号:蓝海资料掘金营,微信deep3321