Coding Project 3 / Observer & Disturbance Feedforward

Can a higher-order observer predict time-varying disturbances? 高阶观测器能否预测时变扰动?

In Project 2 you used the observer to estimate constant load torque. But real disturbances change over time — ramp loads, sinusoidal friction, parameter drift. A 3rd-order observer assumes disturbance is constant and cannot track a ramp. In this project, you will enable the 4th-order observer, wire in feedforward compensation, and prove the difference with simulation. 在 Project 2 中你用观测器估计了恒定负载转矩。但真实扰动会随时间变化——斜坡负载、正弦摩擦、参数漂移。三阶观测器假设扰动恒定,无法跟踪斜坡。本项目中你将启用四阶观测器、接入前馈补偿,并通过仿真证明两者的差异。

Core scripts核心脚本
simulation/tutorials_ep6_svpwm.py
Keywords关键词
ESO / GPIO / ramp load / feedforward / disturbance rejection
Prerequisite前置要求
Coding Project 2编程作业 2
Report format报告形式
PDF

From constant disturbance to time-varying disturbance 从恒定扰动到时变扰动

The mechanical equation机械方程

$$J \frac{d\omega_m}{dt} = T_{em} - T_L - B\omega_m$$

Define the total disturbance $d_{to}$ as everything the controller does not model: 定义总扰动 $d_{to}$ 为控制器未建模的所有内容:

$$d_{to} = -\frac{T_L + B\omega_m + (J - J_n)\dot{\omega}_m}{J_n / n_{pp}}$$

An observer that estimates $d_{to}$ can feed it forward to cancel the disturbance before the PI regulator reacts. The question is: how well can the observer track $d_{to}$ when it changes over time? 估计 $d_{to}$ 的观测器可以将其前馈,在 PI 调节器反应之前就抵消扰动。问题是:当 $d_{to}$ 随时间变化时,观测器能跟踪得多好?

3rd-order observer: assumes constant disturbance三阶观测器:假设扰动恒定

States: $[\hat{\theta}_d,\ \hat{\omega}_r,\ \hat{d}_{to}]$. The internal model assumes $\dot{d}_{to} = 0$.状态:$[\hat{\theta}_d,\ \hat{\omega}_r,\ \hat{d}_{to}]$。内部模型假设 $\dot{d}_{to} = 0$。

$$\begin{aligned} \dot{\hat{\theta}}_d &= \ell_1 e_\theta + \hat{\omega}_r \\ \dot{\hat{\omega}}_r &= \ell_2 e_\theta + (T_{em} + \hat{d}_{to}) \frac{n_{pp}}{J_s} \\ \dot{\hat{d}}_{to} &= \ell_3 e_\theta \end{aligned}$$

Gains placed at $(s + \omega_{ob})^3$:增益配置在 $(s + \omega_{ob})^3$:

$$\ell_1 = 3\omega_{ob},\quad \ell_2 = 3\omega_{ob}^2,\quad \ell_3 = \omega_{ob}^3 \frac{J_s}{n_{pp}},\quad \ell_4 = 0$$
Limitation局限性 Because $\dot{\hat{d}}_{to}$ is driven only by the correction $\ell_3 e_\theta$, the estimate of $d_{to}$ always lags behind a ramp disturbance. The steady-state estimation error is proportional to the ramp slope divided by $\omega_{ob}$. 由于 $\dot{\hat{d}}_{to}$ 仅由校正项 $\ell_3 e_\theta$ 驱动,对 $d_{to}$ 的估计总是滞后于斜坡扰动。稳态估计误差与斜坡斜率除以 $\omega_{ob}$ 成正比。

4th-order observer: models ramp disturbance四阶观测器:建模斜坡扰动

States: $[\hat{\theta}_d,\ \hat{\omega}_r,\ \hat{d}_{to},\ \hat{p}_{to}]$. The internal model assumes $\dot{d}_{to} = p_{to}$, $\dot{p}_{to} = 0$.状态:$[\hat{\theta}_d,\ \hat{\omega}_r,\ \hat{d}_{to},\ \hat{p}_{to}]$。内部模型假设 $\dot{d}_{to} = p_{to}$,$\dot{p}_{to} = 0$。

$$\begin{aligned} \dot{\hat{\theta}}_d &= \ell_1 e_\theta + \hat{\omega}_r \\ \dot{\hat{\omega}}_r &= \ell_2 e_\theta + (T_{em} + \hat{d}_{to}) \frac{n_{pp}}{J_s} \\ \dot{\hat{d}}_{to} &= \ell_3 e_\theta + \hat{p}_{to} \\ \dot{\hat{p}}_{to} &= \ell_4 e_\theta \end{aligned}$$

Gains placed at $(s + \omega_{ob})^4$:增益配置在 $(s + \omega_{ob})^4$:

$$\ell_1 = 4\omega_{ob},\quad \ell_2 = 6\omega_{ob}^2,\quad \ell_3 = 4\omega_{ob}^3 \frac{J_s}{n_{pp}},\quad \ell_4 = \omega_{ob}^4$$
Key advantage核心优势 The extra state $\hat{p}_{to}$ estimates the rate of change of the disturbance. For a ramp load ($T_L = at$), $\hat{p}_{to} \to a$ and $\hat{d}_{to}$ tracks the ramp with zero steady-state error. 额外状态 $\hat{p}_{to}$ 估计扰动的变化率。对于斜坡负载($T_L = at$),$\hat{p}_{to} \to a$,$\hat{d}_{to}$ 以稳态误差跟踪斜坡。

3rd-order under ramp load三阶在斜坡负载下

$\hat{d}_{to}$ lags behind $d_{to}$. Speed drops continuously. PI compensates slowly via integral action.$\hat{d}_{to}$ 滞后于 $d_{to}$。速度持续下降。PI 通过积分作用缓慢补偿。

4th-order under ramp load四阶在斜坡负载下

$\hat{d}_{to}$ tracks $d_{to}$ with zero steady-state error. Feedforward cancels the ramp. Speed stays on target.$\hat{d}_{to}$ 以零稳态误差跟踪 $d_{to}$。前馈抵消斜坡。速度保持目标值。

Where to find and modify the observer观测器代码位置与修改点

1. Observer gains initialization1. 观测器增益初始化

In The_Motor_Controller.__init__ (around line 165), the observer gains are selected by an if/elif/else chain. Currently the 3rd-order branch is active:The_Motor_Controller.__init__(约第 165 行),观测器增益通过 if/elif/else 链选择。当前三阶分支生效:

omega_ob = 100  # [rad/s]
if False:    # 2nd-order speed observer
    ...
elif False:  # 2nd-order position observer
    ...
elif True:   # 3rd-order  <--- CURRENTLY ACTIVE
    self.ell1 = 3 * omega_ob
    self.ell2 = 3 * omega_ob**2
    self.ell3 = omega_ob**3 * init_Js/init_npp
else:        # 4th-order  <--- YOU NEED TO ACTIVATE THIS
    self.ell1 = 4 * omega_ob
    self.ell2 = 6 * omega_ob**2
    self.ell3 = 4 * omega_ob**3 * init_Js/init_npp
    self.ell4 = omega_ob**4

2. Observer dynamics (already supports 4th-order)2. 观测器动态方程(已支持四阶)

def DYNAMICS_SpeedObserver(x, CTRL):
    fx = np.zeros(6)
    output_error = angle_diff(CTRL.theta_d, x[0])
    fx[0] = CTRL.ell1*output_error + x[1]           # theta
    fx[1] = CTRL.ell2*output_error + (CTRL.Tem + x[2]) * CTRL.npp/CTRL.Js  # omega
    fx[2] = CTRL.ell3*output_error + x[3]           # d_to
    fx[3] = CTRL.ell4*output_error + 0.0             # p_to (rate)
    return fx

When ell4 = 0 (3rd-order), x[3] stays zero. When ell4 > 0 (4th-order), x[3] estimates the rate of disturbance change.ell4 = 0(三阶)时,x[3] 保持为零。当 ell4 > 0(四阶)时,x[3] 估计扰动变化率。

3. The missing link: feedforward is not wired in!3. 缺失的环节:前馈未接入!

In FOC() (line 638), the speed controller output goes directly to cmd_idq[1]:FOC()(第 638 行),速度控制器输出直接赋给 cmd_idq[1]

# Current code (line 638-639):
if CTRL.bool_apply_speed_closed_loop_control == True:
    CTRL.cmd_idq[1] = reg_speed.Out    # feedforward NOT added!

The observer computes total_disrubance_feedforward (line 757-761) but it is never used. You must wire it in.观测器计算了 total_disrubance_feedforward(第 757-761 行),但从未使用。你需要将其接入。

4. Watch data for plotting4. 画图用的观测数据

sim.gdd['CTRL.xS[2]']       # estimated disturbance (d_to)
sim.gdd['CTRL.xS[3]']       # estimated rate (p_to)
sim.gdd['ACM.TLoad']         # actual load torque
sim.gdd['CTRL.omega_r_mech'] # measured speed [rpm]
sim.gdd['CTRL.cmd_rpm']      # speed command [rpm]

Switch from 3rd-order to 4th-order observer 从三阶切换到四阶观测器

You need a way to select observer order from the d configuration dictionary, without hard-coding if True/if False in source code. 你需要一种方法,从 d 配置字典选择观测器阶数,而不是在源代码中硬编码 if True/if False

Task 1任务 1
  1. Modify get_global_objects() in tutorials_ep6_svpwm.py so that after creating CTRL, you can overwrite CTRL.ell1CTRL.ell4 based on a new config key d['observer_order'] (3 or 4).修改 tutorials_ep6_svpwm.py 中的 get_global_objects(),在创建 CTRL 后,根据新的配置键 d['observer_order'](3 或 4)重写 CTRL.ell1CTRL.ell4
  2. Set CTRL.index_separate_speed_estimation = 1 to enable the observer.设置 CTRL.index_separate_speed_estimation = 1 来启用观测器。
  3. Verify with a step load: both 3rd-order and 4th-order should track a constant ACM.TLoad = 0.2 with zero steady-state error in xS[2].用阶跃负载验证:三阶和四阶都应以零稳态误差跟踪恒定 ACM.TLoad = 0.2xS[2]
numba constraintnumba 约束 The_Motor_Controller is a @jitclass. You cannot add new fields. But ell1ell4 and xS[0:5] already exist — no spec changes needed. You can freely overwrite their values after construction. The_Motor_Controller@jitclass不能添加新字段。但 ell1ell4xS[0:5] 已经存在——不需要修改 spec。你可以在构造后自由覆写它们的值。

Connect the observer output to the speed controller 将观测器输出连接到速度控制器

The observer estimates disturbance $\hat{d}_{to}$ in torque-like units. To use it as a feedforward, convert to $i_q$ current: 观测器估计的扰动 $\hat{d}_{to}$ 单位类似转矩。要用作前馈,需转换为 $i_q$ 电流:

$$i_{q,ff} = \frac{\hat{d}_{to}}{1.5\, n_{pp}\, K_A}$$
Task 2: Modify FOC()任务 2:修改 FOC() Change line 638-639 of tutorials_ep6_svpwm.py from: tutorials_ep6_svpwm.py 第 638-639 行从:
# BEFORE:
CTRL.cmd_idq[1] = reg_speed.Out

# AFTER:
CTRL.cmd_idq[1] = reg_speed.Out
if CTRL.use_disturbance_feedforward_rejection > 0:
    if CTRL.KA > 0:
        CTRL.cmd_idq[1] += CTRL.total_disrubance_feedforward / (1.5 * CTRL.npp * CTRL.KA)
Sign convention符号约定 In the plant: $J\dot{\omega} = T_{em} - T_L$. In the observer: $\dot{\hat{\omega}} \propto T_{em} + \hat{d}_{to}$. So $\hat{d}_{to} \approx -T_L$ (negative of load torque). Adding $\hat{d}_{to}/(1.5\,n_{pp}\,K_A)$ to $i_q^*$ produces a negative current that cancels the load effect. Verify this in your plots: when $T_L > 0$, xS[2] should be negative. 在被控对象中:$J\dot{\omega} = T_{em} - T_L$。在观测器中:$\dot{\hat{\omega}} \propto T_{em} + \hat{d}_{to}$。所以 $\hat{d}_{to} \approx -T_L$(负载转矩的负值)。将 $\hat{d}_{to}/(1.5\,n_{pp}\,K_A)$ 加到 $i_q^*$ 上会产生电流来抵消负载效应。请在图中验证:当 $T_L > 0$ 时,xS[2] 应为负。

Prove the 4th-order observer can track ramp disturbance 证明四阶观测器能跟踪斜坡扰动

Task 3: Run 4 scenarios under ramp load任务 3:在斜坡负载下运行 4 种场景
Scenario场景 Observer观测器 Feedforward前馈 Expected result预期结果
A3rd-orderOFFBaseline, PI only基准,仅 PI
B3rd-orderONFF helps but cannot eliminate ramp lagFF 有帮助但无法消除斜坡滞后
C4th-orderOFFBetter estimation, no compensation更好的估计,但无补偿
D4th-orderONBest: zero estimation error, full compensation最佳:零估计误差,完全补偿

Ramp load torque setup斜坡负载转矩设置

# In user_system_input_code:
"CTRL.cmd_rpm = 50\n"
"if ii >= 2: ACM.TLoad = 0.05 * (ii - 2) * d['TIME_SLICE']"

This creates a linearly increasing load starting at time slice 2. Adjust the slope (0.05) so the motor doesn't stall.这将从时间片 2 开始创建线性增加的负载。调整斜率(0.05)使电机不会堵转。

What to plot for each scenario每个场景需要画什么

  • Subplot 1: Speed command CTRL.cmd_rpm vs actual speed CTRL.omega_r_mech [rpm]子图 1:速度给定 CTRL.cmd_rpm vs 实际速度 CTRL.omega_r_mech [rpm]
  • Subplot 2: Actual load ACM.TLoad vs estimated disturbance CTRL.xS[2] (note: opposite sign)子图 2:实际负载 ACM.TLoad vs 估计扰动 CTRL.xS[2](注意:符号相反)
  • Subplot 3: Estimated rate CTRL.xS[3] — should converge to the ramp slope for 4th-order子图 3:估计变化率 CTRL.xS[3]——四阶时应收敛到斜坡斜率
Task 4: Also test step load for comparison任务 4:同时测试阶跃负载作为对比 Repeat scenarios A–D with a step load (ACM.TLoad = 0.2 at some time). Show that both observers handle step load well, but only 4th-order handles ramp. This demonstrates that the 4th-order advantage is specifically for time-varying disturbances. 用阶跃负载(某时刻 ACM.TLoad = 0.2)重复场景 A–D。展示两种观测器都能很好地处理阶跃负载,但只有四阶能处理斜坡。这证明四阶的优势专门针对时变扰动。

Tracking, disturbance rejection, and noise: the three-way tradeoff 跟踪、抗扰与噪声:三方权衡

A closed-loop system's output can be decomposed into three paths: 闭环系统的输出可以分解为三条通道:

$$\Omega(s) = \underbrace{\Phi_r(s)}_{\text{tracking}}\,\Omega^*(s) + \underbrace{\Phi_d(s)}_{\text{disturbance}}\,d_n(s) + \underbrace{\Phi_n(s)}_{\text{noise}}\,(-s\delta_p(s))$$
Q1

Command tracking指令跟踪

Compare step response (rise time, overshoot) between 3rd and 4th-order observer systems. Does the observer order affect tracking performance? Why or why not?对比三阶和四阶观测器系统的阶跃响应(上升时间、超调)。观测器阶数是否影响跟踪性能?为什么?

Q2

Disturbance rejection扰动抑制

Under ramp load, what is the steady-state speed error for 3rd-order vs 4th-order (both with feedforward ON)? Can you derive the theoretical error from the internal model principle?在斜坡负载下,三阶和四阶(均开前馈)的稳态速度误差分别是多少?你能从内模原理推导理论误差吗?

Q3

Noise sensitivity噪声敏感性

Higher-order observers amplify noise more. Try increasing omega_ob and observe the noise in xS[2] and xS[3]. Is the 4th-order observer noisier than 3rd-order at the same bandwidth? What is the tradeoff?高阶观测器放大更多噪声。尝试增大 omega_ob,观察 xS[2]xS[3] 中的噪声。在相同带宽下,四阶观测器是否比三阶更嘈杂?权衡是什么?

Q4

Observer bandwidth selection观测器带宽选择

Try omega_ob = 50, 100, 200, 400 for the 4th-order observer. Plot disturbance estimation error vs noise level. What is the optimal omega_ob? Does it differ from the 3rd-order optimal?对四阶观测器尝试 omega_ob = 50, 100, 200, 400。画扰动估计误差 vs 噪声水平的图。最优 omega_ob 是多少?与三阶的最优值不同吗?

Connection to Project 2与 Project 2 的联系 In Project 2 Part 3, you tested parameter mismatch. The observer's disturbance estimate $\hat{d}_{to}$ includes parameter mismatch effects (since $d_{to}$ lumps all unmodeled dynamics). Try combining 4th-order observer + feedforward + parameter mismatch from Project 2. Does the higher-order observer compensate mismatch better than the 3rd-order? 在 Project 2 Part 3 中你测试了参数失配。观测器的扰动估计 $\hat{d}_{to}$ 包含参数失配效应(因为 $d_{to}$ 涵盖了所有未建模动态)。尝试将四阶观测器 + 前馈 + Project 2 的参数失配结合起来。高阶观测器是否比三阶更好地补偿失配?

Required content of the final PDF report最终 PDF 报告要求

The final PDF must contain these 4 core figures最终 PDF 必须包含这 4 张核心图
  1. Step load comparison — 4 scenarios (A–D), speed + disturbance estimate waveforms.阶跃负载对比——4 种场景(A–D),速度 + 扰动估计波形。
  2. Ramp load comparison — 4 scenarios (A–D), speed + disturbance estimate + rate estimate waveforms.斜坡负载对比——4 种场景(A–D),速度 + 扰动估计 + 变化率估计波形。
  3. Observer bandwidth sweep — effect of omega_ob on estimation accuracy and noise for both observer orders.观测器带宽扫描——omega_ob 对两种阶数的估计精度和噪声的影响。
  4. Code diff — show the exact lines you modified in tutorials_ep6_svpwm.py.代码差异——展示你在 tutorials_ep6_svpwm.py 中修改的确切行。

Mandatory必须包含

Working 4th-order observer with configurable order selection.可配置阶数选择的四阶观测器。
Feedforward wired into FOC() with correct unit conversion.前馈接入 FOC(),单位转换正确。
4-scenario comparison under both step and ramp loads.阶跃和斜坡负载下的 4 场景对比。
Direct answers to Q1–Q4.逐条回答 Q1–Q4。

Suggested report structure建议结构

  1. Background: why higher-order observer背景:为什么需要高阶观测器
  2. Code modifications (with diff)代码修改(附差异)
  3. Step load experiments and analysis阶跃负载实验与分析
  4. Ramp load experiments and analysis斜坡负载实验与分析
  5. Bandwidth sweep and noise discussion带宽扫描与噪声讨论
  6. Conclusion结论

Online submission is currently disabled.当前暂不支持在线提交。 Please prepare your report as a PDF. 请先准备 PDF 报告。