3. 前馈-反馈复合控制在伺服系统中的应用
任务定义
伺服系统位置跟踪中,传统PID反馈控制存在固有滞后,当输入轨迹连续变化时会产生跟随误差。本案例设计一个前馈-反馈复合控制器:前馈通道基于参考轨迹的加速度信息提供补偿力矩,反馈通道采用PID修正残余误差,目标是使电机实际位置对给定参考轨迹的跟踪误差显著小于纯PID控制。
系统模型与控制结构
被控对象为直流伺服电机,简化为二阶模型:J·θ'' + b·θ' = Kt·u,其中J=0.01 kg·m²为转动惯量,b=0.1 N·m·s/rad为粘性阻尼系数,Kt=1 N·m/A为力矩常数,u为控制输入(电流),θ为电机角度。控制结构如下:
前馈补偿器取被控对象模型的逆:G_ff(s) = J·s² + b·s,其输入为参考轨迹θ_ref,输出为前馈电流u_ff。反馈PID根据跟踪误差e=θ_ref−θ输出u_pid。总控制量为u = u_ff + u_pid。理想情况下,前馈通道单独即可实现零误差跟踪,反馈通道仅用于抑制模型失配和外部扰动。
Python实现
以下代码在Python中完成复合控制器仿真,并与纯PID控制对比。仿真采用梯形速度轨迹作为参考输入,离散化步长1ms。
import numpy as np
import matplotlib.pyplot as plt
# ---------- 系统参数 ----------
J = 0.01 # 转动惯量 kg·m²
b = 0.1 # 粘性阻尼 N·m·s/rad
Kt = 1.0 # 力矩常数 N·m/A
dt = 0.001 # 采样周期 1ms
T = 3.0 # 仿真时长 3s
t = np.arange(0, T, dt)
N = len(t)
# ---------- 参考轨迹:梯形速度曲线 ----------
v_max = 2.0 # 最大速度 rad/s
a_acc = 5.0 # 加速度 rad/s²
t_acc = v_max / a_acc # 加速时间 0.4s
t_const = 1.0 # 匀速时间
t_dec = t_acc # 减速时间
t_total = t_acc + t_const + t_dec # 1.8s
theta_ref = np.zeros(N)
vel_ref = np.zeros(N)
acc_ref = np.zeros(N)
for i in range(1, N):
ti = t[i]
if ti < t_acc:
acc_ref[i] = a_acc
vel_ref[i] = a_acc * ti
elif ti < t_acc + t_const:
acc_ref[i] = 0
vel_ref[i] = v_max
elif ti < t_total:
acc_ref[i] = -a_acc
vel_ref[i] = v_max - a_acc * (ti - t_acc - t_const)
else:
acc_ref[i] = 0
vel_ref[i] = 0
theta_ref[i] = theta_ref[i-1] + vel_ref[i] * dt
# ---------- 控制器参数 ----------
Kp, Ki, Kd = 50.0, 100.0, 0.5 # PID参数
# ---------- 仿真函数 ----------
def simulate(use_ff):
theta = 0.0
omega = 0.0
integral = 0.0
prev_error = 0.0
theta_hist = np.zeros(N)
err_hist = np.zeros(N)
for i in range(N):
# 跟踪误差
error = theta_ref[i] - theta
integral += error * dt
derivative = (error - prev_error) / dt
prev_error = error
# PID输出
u_pid = Kp * error + Ki * integral + Kd * derivative
# 前馈输出(使用参考加速度和速度)
u_ff = 0.0
if use_ff:
u_ff = J * acc_ref[i] + b * vel_ref[i]
# 总控制量
u = u_pid + u_ff
# 电机模型更新(欧拉法)
alpha = (Kt * u - b * omega) / J
omega += alpha * dt
theta += omega * dt
theta_hist[i] = theta
err_hist[i] = error
return theta_hist, err_hist
# ---------- 运行两种控制 ----------
theta_pid, err_pid = simulate(use_ff=False)
theta_ff, err_ff = simulate(use_ff=True)
# ---------- 计算最大误差和RMS误差 ----------
max_err_pid = np.max(np.abs(err_pid))
max_err_ff = np.max(np.abs(err_ff))
rms_err_pid = np.sqrt(np.mean(err_pid**2))
rms_err_ff = np.sqrt(np.mean(err_ff**2))
print(f"纯PID: 最大误差={max_err_pid:.4f} rad, RMS误差={rms_err_pid:.4f} rad")
print(f"前馈+PID: 最大误差={max_err_ff:.4f} rad, RMS误差={rms_err_ff:.4f} rad")
# ---------- 绘图 ----------
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
ax1.plot(t, theta_ref, 'k--', label='参考轨迹', linewidth=1.5)
ax1.plot(t, theta_pid, 'b-', label='纯PID', alpha=0.7)
ax1.plot(t, theta_ff, 'r-', label='前馈+PID', alpha=0.7)
ax1.set_ylabel('位置 (rad)')
ax1.legend()
ax1.grid(True, alpha=0.3)
ax2.plot(t, err_pid, 'b-', label='纯PID误差', alpha=0.7)
ax2.plot(t, err_ff, 'r-', label='前馈+PID误差', alpha=0.7)
ax2.set_xlabel('时间 (s)')
ax2.set_ylabel('跟踪误差 (rad)')
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('servo_tracking.png', dpi=100)
plt.show()
运行与验证
依赖:numpy、matplotlib。运行命令:python servo_control.py。
验证方法:程序执行后,终端输出两种控制器的最大误差和RMS误差数值;同时生成servo_tracking.png图像,包含位置跟踪对比和误差对比两个子图。
判定标准:满足以下条件即验证通过:
- 程序无异常退出,输出两组误差指标;
- 前馈+PID的最大误差和RMS误差均小于纯PID对应值;
- 误差曲线图中,前馈+PID的误差幅值明显低于纯PID,尤其在加速和减速阶段(0~0.4s和1.4~1.8s)差异显著。
预期输出(由代码逻辑直接推出):纯PID在加减速阶段因积分滞后产生较大跟踪误差;加入前馈补偿后,由于前馈项直接提供加速所需力矩,误差大幅减小。匀速段两者误差均趋近于零。