3. 直线插补加减速控制

任务目标

在直线插补过程中,控制运动轴从起点到终点时速度按梯形曲线变化:匀加速、匀速、匀减速三段。给定总位移、最大速度、加速度,计算各阶段位移与时间,并输出每个插补周期(如1ms)的目标位置序列。

核心算法

梯形速度曲线规划的关键是判断是否达到最大速度。设总位移为 S,最大速度为 Vmax,加速度为 A(加减速值相同)。若 S < Vmax² / A,则无法达到最大速度,实际峰值速度 Vp = sqrt(S·A),此时只有加速和减速段;否则 Vp = Vmax,包含匀速段。加速段位移 Sa = Vp²/(2A),减速段位移与加速段相同,匀速段位移 Sc = S - 2·Sa。

完整实现

import math

def trapezoidal_profile(S, Vmax, A, T_cycle=0.001):
    """
    梯形加减速直线插补规划
    参数:
        S: 总位移 (单位: mm 或 pulse)
        Vmax: 最大速度 (单位/s)
        A: 加速度 (单位/s²)
        T_cycle: 插补周期 (s)
    返回:
        (positions, times, phases)
        positions: 每个周期的目标位置列表
        times: 对应时间点列表
        phases: 每段对应的阶段标签 ('accel'/'cruise'/'decel')
    """
    # 判断是否可达最大速度
    S_accel_min = Vmax * Vmax / (2 * A)  # 加速到Vmax所需位移
    if S < 2 * S_accel_min:
        # 三角形速度曲线:达不到最大速度
        Vp = math.sqrt(S * A)
        Sa = S / 2
        t_accel = Vp / A
        t_total = 2 * t_accel
        t_cruise_start = t_accel
        t_cruise_end = t_accel  # 无匀速段
    else:
        # 梯形速度曲线
        Vp = Vmax
        Sa = S_accel_min
        t_accel = Vmax / A
        Sc = S - 2 * Sa
        t_cruise = Sc / Vmax
        t_total = 2 * t_accel + t_cruise
        t_cruise_start = t_accel
        t_cruise_end = t_accel + t_cruise

    # 生成插补点
    positions = []
    times = []
    phases = []
    t = 0.0
    pos = 0.0
    while t <= t_total + 1e-9:
        if t < t_accel:
            # 加速段: s = 0.5*A*t²
            pos = 0.5 * A * t * t
            phase = 'accel'
        elif t < t_cruise_end:
            # 匀速段: s = Sa + Vp*(t - t_accel)
            pos = Sa + Vp * (t - t_accel)
            phase = 'cruise'
        else:
            # 减速段: s = S - 0.5*A*(t_total - t)²
            t_remain = t_total - t
            pos = S - 0.5 * A * t_remain * t_remain
            phase = 'decel'
        positions.append(pos)
        times.append(t)
        phases.append(phase)
        t += T_cycle

    # 确保终点精确
    if positions:
        positions[-1] = S
    return positions, times, phases

# 最小调用示例
if __name__ == "__main__":
    S = 100.0      # 总位移 100mm
    Vmax = 200.0   # 最大速度 200mm/s
    A = 500.0      # 加速度 500mm/s²
    T = 0.001      # 1ms插补周期

    pos_list, time_list, phase_list = trapezoidal_profile(S, Vmax, A, T)

    # 输出关键规划结果
    print(f"总点数: {len(pos_list)}")
    print(f"首点: pos={pos_list[0]:.4f}, t={time_list[0]:.4f}")
    print(f"末点: pos={pos_list[-1]:.4f}, t={time_list[-1]:.4f}")

    # 验证加减速对称性
    accel_end = max(i for i, p in enumerate(phase_list) if p == 'accel')
    decel_start = min(i for i, p in enumerate(phase_list) if p == 'decel')
    print(f"加速段结束于索引 {accel_end}, 位置 {pos_list[accel_end]:.4f}")
    print(f"减速段开始于索引 {decel_start}, 位置 {pos_list[decel_start]:.4f}")
    print(f"中点位置: {pos_list[len(pos_list)//2]:.4f} (理论中点 {S/2:.4f})")

运行与验证

直接运行上述代码(Python 3,无需额外依赖)。程序会输出插补总点数、首末点位置及加减速切换点。验证通过条件:

  • 末点位置精确等于总位移 S(100.0)
  • 加速段结束位置与减速段开始位置关于中点对称,即两者之和等于 S
  • 中点位置接近理论中点 S/2(因离散化存在≤半个周期的误差)
  • 相邻点位移差(即瞬时速度)先增后减,且峰值不超过 Vmax

关键说明

本实现采用时间基插补,每个周期计算一次位置。实际工程中需将位置增量 Δpos = pos[i] - pos[i-1] 转换为脉冲频率或速度指令发送给驱动器。若需更高精度,可改用位置增量累加方式避免浮点累积误差。对于三角形曲线(无法达到最大速度)的情况,代码已自动处理,无需额外分支调用。