梯形曲线数学模型:匀加速段、匀速段、匀减速段的三段式结构

好,咱们接着聊。上一章我讲了梯形曲线的基本概念,说白了就是「加速-匀速-减速」这么个三段式。这一章,咱们把它的数学模型彻底掰开揉碎了讲清楚。

我个人习惯,在写任何运动控制代码之前,先把数学公式在纸上推一遍。为什么?因为公式里藏着所有边界条件。你想想看,如果连加速度、速度、位移的关系都没搞明白,写出来的代码大概率会撞限位。

三段式的数学本质

梯形曲线,本质上就是三个时间段,每个时间段对应一个运动学方程。咱们用最经典的物理公式:

  • 匀加速段:速度从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画的梯形曲线三段式结构。你可以清晰地看到速度随时间的变化:

时间 t 速度 v 匀加速段 匀速段 匀减速段 t₁ t₁+t₂ T V 加速 匀速 减速

这张图里,红色是加速段,绿色是匀速段,蓝色是减速段。你注意看,加速和减速的斜率绝对值相等,这就是对称梯形曲线。如果斜率不同,那就是非对称梯形,咱们后面再聊。

实际编程中的离散化处理

理论公式讲完了,但实际写代码时,你不能直接用连续时间公式。为什么?因为运动控制器的周期是固定的,比如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,就报错并提示用户调整参数。

总结一下

梯形曲线的数学模型,说白了就是三个二次函数拼在一起。但真正用好它,你得理解三个关键点:

  1. 时间计算:t₁、t₂、t₃的公式要烂熟于心
  2. 边界判断:时刻检查匀速段时间是否为正
  3. 离散化处理:连续公式到离散代码的转换要小心浮点误差

我个人觉得,梯形曲线是所有运动控制曲线的基础。你把它的数学模型吃透了,后面学S形曲线、多项式曲线都会轻松很多。下一章咱们会聊梯形曲线的代码实现,到时候我会给出一个完整的Python类,包含速度规划、位置插补和实时监控。


公众号:蓝海资料掘金营,微信deep3321