第四节:重力补偿与摩擦补偿

各位同学好。今天我们来聊聊力矩控制里两个绕不开的话题——重力补偿和摩擦补偿。

说实话,我刚入行那会儿,觉得力矩控制嘛,给个期望力矩,电机转就完了。结果第一次调试六轴机械臂,空载时还好,一装上负载,整个手臂往下坠,跟断了似的。嗯,那时候我才意识到:重力补偿,不是可选项,是必选项。

4.1 静态重力矩计算

先说说重力补偿的本质。说白了,就是算出机器人各个关节因为自身重量和负载重量产生的力矩,然后在控制指令里把这个力矩抵消掉。

静态重力矩的计算,核心就一句话:重力在关节轴线上产生的力矩。

对于单关节来说,公式很简单:

τ_gravity = m * g * L * sin(θ)

其中:

  • m — 连杆质量
  • g — 重力加速度
  • L — 质心到关节轴的距离
  • θ — 连杆与水平面的夹角

但实际项目中,机器人是多连杆串联结构。每个关节的重力矩,不仅受自身连杆影响,还受后面所有连杆和负载的影响。我习惯用递推法来计算:

  1. 从末端开始,逐级向前计算每个连杆的质心位置和重力矩
  2. 将后一级的力矩累加到前一级
  3. 最终得到每个关节的总重力补偿力矩

关键点:静态重力矩只与关节位置有关,与速度、加速度无关。所以它是个位置相关的函数,可以离线计算好,查表使用。

我在项目中遇到过一个问题:机械臂在某个姿态下,重力矩突然变得很大,导致电机过载。后来排查发现,是质心参数标定不准。所以,质心参数的准确性,直接决定了重力补偿的效果。

4.2 库仑+粘滞摩擦模型

摩擦补偿,比重力补偿要麻烦一些。为什么?因为摩擦是非线性的,而且方向总是与运动方向相反。

常用的摩擦模型是库仑+粘滞摩擦模型:

τ_friction = τ_coulomb * sign(ω) + B * ω

其中:

  • τ_coulomb — 库仑摩擦力矩(常数)
  • sign(ω) — 速度方向的符号函数
  • B — 粘滞摩擦系数
  • ω — 关节角速度

这个模型虽然简单,但实际用起来效果不错。我个人的经验是:

  • 库仑摩擦主要影响低速时的启停性能。你想想看,电机刚启动时,要克服的静摩擦力往往比动摩擦力大得多。
  • 粘滞摩擦则随着速度增加而线性增大。高速运行时,这部分占主导。

小技巧:实际标定时,可以让机器人以不同速度匀速运动,记录力矩值。然后做线性拟合,就能得到库仑摩擦系数和粘滞摩擦系数。

我曾经在调试一个协作机器人时,发现低速时抖动特别严重。查了半天,原来是库仑摩擦补偿值给大了,导致过补偿。嗯,这里要注意:摩擦补偿宁小勿大,过补偿会引起震荡。

4.3 前馈补偿实现

有了重力矩和摩擦力矩的计算方法,接下来就是怎么把它们用起来。

前馈补偿的思路很简单:在PID反馈控制的基础上,把已知的干扰力矩提前加到控制指令里。这样,控制器就不需要等误差出现再去调整了。

我画了一张图,帮你理解整个控制回路:

期望位置 + PID 控制器 + 电机 +负载 位置反馈 前馈补偿计算 关节位置/速度 前馈路径 虚线表示前馈信号

前馈补偿的实现步骤:

  1. 获取当前关节位置和速度 — 从编码器读取
  2. 计算重力补偿力矩 — 根据关节位置查表或实时计算
  3. 计算摩擦补偿力矩 — 根据关节速度和摩擦模型计算
  4. 叠加到控制输出 — 在PID输出基础上加上前馈量

代码实现大概是这样的:

// 前馈补偿计算函数
float computeFeedforward(float position, float velocity) {
    // 1. 重力补偿
    float gravity_torque = computeGravity(position);
    
    // 2. 摩擦补偿
    float friction_torque = COULOMB_FRICTION * sign(velocity) 
                          + VISCOUS_FRICTION * velocity;
    
    // 3. 总前馈量
    float feedforward = gravity_torque + friction_torque;
    
    return feedforward;
}

// 控制循环中调用
void controlLoop() {
    float pos = readEncoder();
    float vel = readVelocity();
    
    float pid_output = computePID(setpoint, pos);
    float ff_output = computeFeedforward(pos, vel);
    
    float final_torque = pid_output + ff_output;
    setMotorTorque(final_torque);
}

注意事项:

  • 前馈补偿不能完全替代反馈控制。反馈是兜底的,前馈是锦上添花的。
  • 摩擦模型参数需要定期标定,因为机械磨损会导致参数变化。
  • 重力补偿在低速时效果明显,高速时惯性力占主导,重力影响相对变小。

我记得有一次,在调试一个六自由度机械臂时,重力补偿参数没调好,结果机械臂在某个姿态下突然往下掉,差点砸到人。从那以后,我每次做重力补偿都会先做空载验证:让机械臂在无负载情况下,各个关节能否保持任意位置。如果会滑落,说明补偿不够;如果会震荡,说明补偿过了。

好了,这一节的内容就到这里。重力补偿和摩擦补偿,说白了就是把已知的干扰提前抵消掉,让PID控制器只处理那些未知的、非线性的部分。这样,控制精度和响应速度都能上一个台阶。

核心要点回顾:

  • 静态重力矩只与关节位置有关,可离线计算
  • 库仑+粘滞摩擦模型简单实用,参数可通过匀速运动标定
  • 前馈补偿与PID反馈结合,能显著提升控制性能
  • 补偿参数宁小勿大,过补偿比欠补偿更危险

可可精品资料库