4、位置环与轨迹规划调试:梯形/S形曲线规划器调试、位置环跟随误差分析、加减速过程中的过冲与欠冲处理

各位工程师朋友,咱们今天聊点实在的。位置环和轨迹规划,说白了就是让电机“听话”地走到指定位置。我见过太多项目,代码写得花里胡哨,结果电机一跑就露馅——要么抖得像筛糠,要么冲过头刹不住。嗯,这节课咱们就把这些坑一个个填平。

4.1 梯形曲线规划器调试

梯形速度曲线,是最基础的加减速方式。它的逻辑很简单:先匀加速,再匀速,最后匀减速。我刚开始做运动控制时,觉得这玩意儿太简单了,闭着眼都能写。结果呢?第一次上机测试,电机直接冲过了限位开关,差点把机械结构撞坏。

为什么会这样?因为梯形曲线有个致命弱点——加速度突变。在加速结束、匀速开始的瞬间,加速度从最大值直接跳变到0。你想想看,电机轴上的惯性力会瞬间消失,但负载的惯性还在,这就造成了冲击。

调试梯形曲线,我个人的习惯是盯着三个参数:

  • 最大速度:别设得太高,留20%余量给位置环调节
  • 加速度:从理论值的50%开始往上调,每次增加10%
  • 减速度:通常设成加速度的1.2倍,这样能更快刹停

核心要点:梯形曲线的调试顺序是“先低速后高速,先轻载后重载”。千万别一上来就满速跑,那是找摔。

这里给一段梯形曲线规划器的核心代码,我习惯用状态机来实现:

// 梯形曲线规划器 - 状态机实现
typedef enum {
    TRAP_IDLE,
    TRAP_ACCEL,
    TRAP_CRUISE,
    TRAP_DECEL,
    TRAP_DONE
} TrapState;

void TrapPlanner_Update(TrapPlanner *planner, float dt) {
    switch (planner->state) {
        case TRAP_ACCEL:
            planner->velocity += planner->accel * dt;
            if (planner->velocity >= planner->max_vel) {
                planner->velocity = planner->max_vel;
                planner->state = TRAP_CRUISE;
            }
            break;
        case TRAP_CRUISE:
            // 计算剩余距离,判断是否需要减速
            float remain_dist = planner->target_pos - planner->current_pos;
            float decel_dist = (planner->velocity * planner->velocity) / (2 * planner->decel);
            if (remain_dist <= decel_dist) {
                planner->state = TRAP_DECEL;
            }
            break;
        case TRAP_DECEL:
            planner->velocity -= planner->decel * dt;
            if (planner->velocity <= 0) {
                planner->velocity = 0;
                planner->state = TRAP_DONE;
            }
            break;
        default:
            break;
    }
    planner->current_pos += planner->velocity * dt;
}

调试技巧:在梯形曲线的加速段和减速段,我习惯用示波器抓一下速度波形。如果加速段出现“台阶”,说明加速度设得太大了,电机扭矩不够,被负载拖住了。

4.2 S形曲线规划器调试

S形曲线,说白了就是给梯形曲线加了“圆角”。它用加加速度(Jerk)来平滑加速度的变化,让电机启停更柔和。我在做高精度定位平台时,梯形曲线根本没法用——每次启停都会把工件震歪。换成S形曲线后,问题迎刃而解。

S形曲线的调试比梯形复杂得多。它多了两个阶段:加加速段和减加速段。嗯,这里要注意,S形曲线有7段状态,比梯形的4段多了整整3段。

我个人建议,调试S形曲线时先关注三个关键参数:

  • 加加速度(Jerk):这是S形曲线的灵魂。Jerk越大,曲线越接近梯形;Jerk越小,曲线越平滑。我一般从最大加速度的10倍开始试。
  • 加速度:可以比梯形曲线设得大一些,因为S形曲线有缓冲,冲击小。
  • 速度:和梯形一样,留余量。

注意:S形曲线不是万能的。如果Jerk设得太小,加减速时间会变得很长,影响生产效率。我曾经在一个项目中把Jerk设得太保守,结果一个定位动作花了3秒,客户直接投诉了。

这里给一个S形曲线的速度规划公式,方便大家理解:

// S形曲线 - 速度分段计算
// 假设总行程为S,最大速度为Vmax,最大加速度为Amax,加加速度为J
// 1. 加加速段:v(t) = 0.5 * J * t^2
// 2. 匀加速段:v(t) = V1 + Amax * t
// 3. 减加速段:v(t) = V2 + Amax * t - 0.5 * J * t^2
// 4. 匀速段:v(t) = Vmax
// 5. 加减速段:v(t) = Vmax - 0.5 * J * t^2
// 6. 匀减速段:v(t) = V3 - Amax * t
// 7. 减减速段:v(t) = V4 - Amax * t + 0.5 * J * t^2

我的经验:调试S形曲线时,先用仿真工具跑一遍,看看速度曲线是不是“S”形。如果加速段太陡,说明Jerk太大了;如果加速段太平,说明Jerk太小了。调好参数再上机,能省不少时间。

4.3 位置环跟随误差分析

跟随误差,就是指令位置和实际位置的差值。说白了,就是电机“跟不跟得上”的问题。我见过最夸张的一次,跟随误差达到了5mm,结果工件直接报废了。

为什么会产生跟随误差?三个原因:

  1. 位置环增益太低:电机反应慢,跟不上指令
  2. 速度前馈没加:位置环全靠误差驱动,天生滞后
  3. 机械间隙或摩擦:电机转了,负载没动

分析跟随误差,我习惯用示波器同时抓指令位置和实际位置。如果两条曲线形状相似,但实际位置始终落后一段距离,那就是增益不够。如果实际位置在加速段和减速段偏差特别大,那就是前馈没加好。

关键指标:跟随误差的峰值通常出现在加减速阶段。如果匀速段的跟随误差也很大,那就要检查机械传动部分了。

这里给一个位置环的PID控制代码,我加了速度前馈:

// 位置环PID + 速度前馈
float PositionLoop_Update(float target_pos, float current_pos, float target_vel) {
    float error = target_pos - current_pos;
    
    // PID计算
    static float integral = 0;
    integral += error * dt;
    float derivative = (error - prev_error) / dt;
    float pid_out = Kp * error + Ki * integral + Kd * derivative;
    
    // 速度前馈
    float ff_out = Kff * target_vel;
    
    // 限幅
    float output = pid_out + ff_out;
    if (output > MAX_OUTPUT) output = MAX_OUTPUT;
    if (output < -MAX_OUTPUT) output = -MAX_OUTPUT;
    
    prev_error = error;
    return output;
}

调试顺序:先调Kp,让跟随误差减小到可接受范围;再加Kd,抑制震荡;最后加Kff,消除稳态误差。我一般把Kff设成0.8~1.0,效果最好。

4.4 加减速过程中的过冲与欠冲处理

过冲,就是电机冲过了目标位置又倒回来。欠冲,就是电机没走到位就停了。这两个问题,说白了都是位置环和轨迹规划没配合好。

我遇到过最头疼的一次,是一个高速贴片机项目。每次定位都会过冲0.5mm,然后来回震荡3次才稳定。客户说:“你这机器贴的芯片,都快被我晃晕了。”

处理过冲和欠冲,我总结了三个方法:

  • 调整位置环增益:过冲通常是Kp太大,欠冲通常是Kp太小。我一般用“临界比例法”来调——先把Ki和Kd设成0,只调Kp,直到系统开始震荡,然后取震荡值的60%作为Kp。
  • 优化减速段规划:如果减速段太短,电机来不及减速,必然过冲。我习惯在减速段加一个“提前量”,让电机提前开始减速。
  • 加末端微调:在目标位置附近,切换成更小的速度进行微调。就像停车一样,先快速开到车位附近,再慢慢挪进去。

避坑指南:我曾经为了消除过冲,把Kp调得特别小。结果过冲没了,但定位时间从100ms变成了500ms。嗯,过冲和定位时间是一对矛盾,要找到平衡点。

这里给一个末端微调的实现思路:

// 末端微调 - 分段速度控制
void FineTuning_Control(float target_pos, float current_pos) {
    float distance = fabs(target_pos - current_pos);
    
    if (distance > 10.0f) {
        // 粗定位阶段:高速运行
        SetTargetVelocity(100.0f);
    } else if (distance > 1.0f) {
        // 中定位阶段:中速运行
        SetTargetVelocity(20.0f);
    } else {
        // 精定位阶段:低速微调
        SetTargetVelocity(2.0f);
    }
}

我的习惯:在精定位阶段,我会把位置环的Kp临时提高50%,这样能更快地消除微小误差。等定位完成后,再把Kp恢复原值。

4.5 本章知识体系

为了让大家更直观地理解本章内容,我画了一张流程图,展示了位置环与轨迹规划调试的核心逻辑:

位置环与轨迹规划调试知识体系 梯形曲线规划器 S形曲线规划器 位置环跟随误差分析 加速度突变 → 冲击问题 参数:最大速度、加速度、减速度 调试顺序:先低速后高速 加加速度Jerk → 平滑过渡 7段状态:加加速/匀加速/减加速... Jerk从最大加速度的10倍开始试 跟随误差 = 指令位置 - 实际位置 原因:增益低/无前馈/机械间隙 解决方案:PID + 速度前馈 过冲与欠冲处理 调整位置环增益(临界比例法) 优化减速段规划(提前量) 末端微调(分段速度控制)

这张图把本章的核心逻辑串起来了。从梯形和S形曲线规划器出发,到位置环的跟随误差分析,最后汇聚到过冲与欠冲的处理方法。你想想看,调试的时候只要沿着这条线走,基本不会漏掉关键环节。

好了,这节课的内容就到这里。记住,运动控制调试没有捷径,多试、多看波形、多总结,你也能成为老手。

专注资料整理