Project 2: bandwidth, decoupling, parameter mismatch, and disturbance observer Project 2:带宽、解耦、参数失配与基础扰动观测器
From frequency domain to time domain: bandwidth, decoupling, and robustness 从频域到时域:带宽、解耦与鲁棒性
A well-tuned controller is not just "fast." It must balance speed, stability, and robustness to model uncertainty. This project asks you to quantify these tradeoffs through simulation. 一个调好的控制器不只是"快"。它必须在速度、稳定性和对模型不确定性的鲁棒性之间取得平衡。本项目要求你通过仿真量化这些权衡。
Part 1: Sweep bandwidthPart 1:扫描带宽
Vary FOC_desired_VLBW_HZ, measure rise time, overshoot, and steady-state error from the speed step response.改变 FOC_desired_VLBW_HZ,从速度阶跃响应中提取上升时间、超调量和稳态误差。
Part 2: Toggle decouplingPart 2:开关前馈解耦
Enable / disable feedforward decoupling and compare control performance. Answer: what are the side effects?开启/关闭前馈解耦,比较控制性能。回答:前馈解耦有什么副作用?
Part 3: Parameter mismatchPart 3:参数失配
Make the controller's motor parameters differ from the plant. Observe how decoupling degrades under mismatch.让控制器的电机参数与实际不同,观察解耦在参数失配下如何退化。
Code entry points and setup references代码入口与环境参考
Clone:Clone: https://github.com/horychen/ee275.git
README:README: README / environment setup
git clone https://github.com/horychen/ee275.git
cd ee275/simulation
python tutorials_ep6_svpwm.py
simulation/tutorials_ep6_svpwm.py
- Feedforward decoupling: search for
bool_apply_decoupling_voltages_to_current_regulation(around line 695).前馈解耦:搜索bool_apply_decoupling_voltages_to_current_regulation(约第 695 行)。 - Speed/disturbance observer: search for
DYNAMICS_SpeedObserver(around line 417).速度/扰动观测器:搜索DYNAMICS_SpeedObserver(约第 417 行)。 Simulation_Benchmarkclass: around line 1307. This is your main entry point.Simulation_Benchmark类:约第 1307 行。这是你的主要入口。- Example
d_user_inputdictionary: around line 1475.示例d_user_input字典:约第 1475 行。
simulation/tuner.py
tunner_wrapper(d)— auto-tunes PI gains whenCL_SERIES_KPisNone.tunner_wrapper(d)——当CL_SERIES_KP为None时自动整定 PI 参数。iterate_for_desired_bandwidth()— iterates current-loop BW to achieve desired speed-loop BW.iterate_for_desired_bandwidth()——迭代电流环带宽以达到期望的速度环带宽。FOC_deltacontrols the damping ratio of the speed loop.FOC_delta控制速度环的阻尼比。FOC_desired_VLBW_HZis the target speed-loop bandwidth in Hz.FOC_desired_VLBW_HZ是目标速度环带宽(Hz)。
Variables you should know至少要熟悉这些变量
Base configuration dictionary基础配置字典
Use this as your starting point. The key fields you will modify are highlighted in comments.以此为出发点。你需要修改的关键字段在注释中标出。
d = {
'CL_TS': 1e-4,
'VL_EXE_PER_CL_EXE': 5,
'MACHINE_SIMULATIONs_PER_SAMPLING_PERIOD': 1,
'TIME_SLICE': 0.2,
'NUMBER_OF_SLICES': 6,
'init_npp': 22,
'init_IN': 1.3*6/1.414,
'init_R': 0.035, # <-- Part 3: change this for mismatch
'init_Ld': 0.036e-3, # <-- Part 3: change this for mismatch
'init_Lq': 0.036e-3, # <-- Part 3: change this for mismatch
'init_KE': 0.0125,
'init_Rreq': 0.0,
'init_Js': 0.44e-4, # <-- Part 3: change this for mismatch
'DC_BUS_VOLTAGE': 5,
'user_system_input_code':
"if ii < 1: CTRL.cmd_idq[0] = 0.0; CTRL.cmd_rpm = 50\n"
"elif ii < 5: ACM.TLoad = 0.2\n"
"elif ii < 100: CTRL.cmd_rpm = -50",
'CTRL.bool_apply_speed_closed_loop_control': True,
'CTRL.bool_apply_decoupling_voltages_to_current_regulation': False, # <-- Part 2
'CTRL.bool_apply_sweeping_frequency_excitation': False,
'CTRL.bool_overwrite_speed_commands': True,
'CTRL.bool_zero_id_control': True,
'FOC_delta': 15, # <-- Part 1: damping factor
'FOC_desired_VLBW_HZ': 120, # <-- Part 1: sweep this
'FOC_CL_KI_factor_when__bool_apply_decoupling_voltages_to_current_regulation__is_False': 10,
'CL_SERIES_KP': None, # None = auto-tune
'CL_SERIES_KI': None,
'VL_SERIES_KP': None,
'VL_SERIES_KI': None,
'VL_LIMIT_OVERLOAD_FACTOR': 3.0,
'disp.Kp': 0, 'disp.Ki': 0, 'disp.Kd': 0,
'disp.tau': 0, 'disp.OutLimit': 0, 'disp.IntLimit': 0,
}
How does bandwidth affect time-domain performance? 带宽如何影响时域性能?
Background: PI auto-tuning背景:PI 自动整定
When CL_SERIES_KP is None, the Simulation_Benchmark class calls tuner.tunner_wrapper(d), which iterates to find current-loop and speed-loop PI gains that achieve the desired bandwidths. The key formulas are:
当 CL_SERIES_KP 为 None 时,Simulation_Benchmark 类会调用 tuner.tunner_wrapper(d),通过迭代找到满足期望带宽的电流环和速度环 PI 参数。核心公式:
where $\delta$ is FOC_delta (a damping-like factor) and $\omega_{ci}$ is the current-loop bandwidth in rad/s.
其中 $\delta$ 即 FOC_delta(类似阻尼比的参数),$\omega_{ci}$ 为电流环带宽(rad/s)。
Step response metrics阶跃响应指标
FOC_desired_VLBW_HZ (e.g., 20, 40, 60, 80, 100, 120 Hz). For each value, run the simulation, extract the speed step response, and compute rise time, overshoot, and steady-state error. Plot all three metrics vs. bandwidth on one figure (3 subplots).
编写 Python 脚本,遍历多个 FOC_desired_VLBW_HZ 值(如 20, 40, 60, 80, 100, 120 Hz)。每次运行仿真,从速度阶跃响应中提取上升时间、超调量和稳态误差,然后将三个指标对带宽的关系画在一张图上(3 个子图)。
Code skeleton代码骨架
import copy
from tutorials_ep6_svpwm import Simulation_Benchmark
bandwidths = [20, 40, 60, 80, 100, 120]
results = {'rise_time': [], 'overshoot': [], 'ss_error': []}
for bw in bandwidths:
d_run = copy.deepcopy(d) # use a fresh copy each time
d_run['FOC_desired_VLBW_HZ'] = bw
d_run['CL_SERIES_KP'] = None # force re-tune
d_run['CL_SERIES_KI'] = None
d_run['VL_SERIES_KP'] = None
d_run['VL_SERIES_KI'] = None
sim = Simulation_Benchmark(d_run)
speed = sim.gdd['CTRL.omega_r_mech']
time = sim.global_machine_times
# TODO: extract rise time, overshoot, steady-state error
# Hint: find the step region, identify y_ss, then compute metrics
# results['rise_time'].append(tr)
# results['overshoot'].append(os_pct)
# results['ss_error'].append(ess)
FOC_delta acts like a damping ratio — smaller delta means more aggressive (less damped) response. Try sweeping FOC_delta too and observe.
更高的带宽通常意味着更快的上升时间,但可能增加超调。FOC_delta 类似阻尼比——更小的 delta 意味着更激进(欠阻尼)的响应。也可以尝试扫描 FOC_delta。
When the system responds faster, what is the cost?当系统响应更快时,代价是什么?
Think about overshoot, noise sensitivity, voltage saturation, and stability margin.考虑超调、噪声敏感性、电压饱和和稳定裕度。
When the system is more stable (larger delta), what is lost?当系统更稳定时(更大的 delta),损失了什么?
Think about tracking performance, disturbance rejection speed, and transient error.考虑跟踪性能、抗扰速度和暂态误差。
What does feedforward decoupling do, and what are its side effects? 前馈解耦的作用与副作用
Physics: cross-coupling in the dq frame物理:dq 坐标系中的交叉耦合
The dq-frame voltage equations of a PMSM are: PMSM 的 dq 坐标系电压方程为:
The underbraced terms act as disturbances to the PI current regulators. Feedforward decoupling adds compensation voltages to cancel them: 下划线部分是对 PI 电流调节器的扰动。前馈解耦通过补偿电压来抵消它们:
This corresponds to lines 696–699 in tutorials_ep6_svpwm.py.
这对应 tutorials_ep6_svpwm.py 的第 696–699 行。
Decoupling OFF解耦关闭
The PI must reject the cross-coupling as a disturbance. The code compensates by multiplying the current-loop $K_i$ by FOC_CL_KI_factor... (default: 10), boosting integral action.PI 调节器必须将交叉耦合当作扰动来抑制。代码通过将电流环 $K_i$ 乘以 FOC_CL_KI_factor...(默认 10)来加强积分作用。
Decoupling ON解耦开启
Cross-coupling is cancelled by feedforward. PI uses nominal $K_i$. But the feedforward relies on accurate knowledge of $L_d$, $L_q$, $K_E$ stored in CTRL.交叉耦合由前馈补偿抵消。PI 使用标称 $K_i$。但前馈依赖于 CTRL 中存储的 $L_d$、$L_q$、$K_E$ 的准确性。
Code: toggle decoupling代码:切换解耦
# Experiment A: Decoupling OFF
d_off = copy.deepcopy(d)
d_off['CTRL.bool_apply_decoupling_voltages_to_current_regulation'] = False
sim_off = Simulation_Benchmark(d_off)
# Experiment B: Decoupling ON
d_on = copy.deepcopy(d)
d_on['CTRL.bool_apply_decoupling_voltages_to_current_regulation'] = True
sim_on = Simulation_Benchmark(d_on)
Does feedforward decoupling have side effects?前馈解耦是否有副作用?
What happens when the motor parameters used in the feedforward ($L_d$, $L_q$, $K_E$) are inaccurate? Does the feedforward then help or hurt?当前馈中使用的电机参数($L_d$、$L_q$、$K_E$)不准确时会怎样?此时前馈是帮助还是损害?
Why does the code boost $K_i$ when decoupling is OFF?为什么解耦关闭时代码会增大 $K_i$?
Find FOC_CL_KI_factor_when__bool_apply_decoupling_voltages_to_current_regulation__is_False in the code. Explain its purpose.在代码中找到 FOC_CL_KI_factor_when__...,解释其作用。
What happens when the controller's model does not match reality? 当控制器的模型与实际不匹配时会发生什么?
The idea思路
In Simulation_Benchmark, both CTRL (controller) and ACM (plant) are initialized from the same d dictionary. The feedforward decoupling uses CTRL.Lq and CTRL.KA to compute the compensation voltages. If these values are wrong (i.e., they don't match the actual plant), the feedforward injects errors instead of cancelling disturbances.
在 Simulation_Benchmark 中,CTRL(控制器)和 ACM(被控对象)都从同一个 d 字典初始化。前馈解耦使用 CTRL.Lq 和 CTRL.KA 来计算补偿电压。如果这些值是错误的(即与实际被控对象不匹配),前馈就会注入误差而非抵消扰动。
Step 2: Save the tuned gains and set them explicitly (not
None).Step 3: Change
init_R, init_Ld, init_Lq, init_Js in the d dictionary.Step 4: Run again — since gains are explicit, the tuner won't re-run, but both CTRL and ACM will be initialized with the new (mismatched) parameters.
This means the PI gains were designed for the original plant, but the controller's internal model (
CTRL.Lq, CTRL.KA) and the plant (ACM.Lq, ACM.KA) now both have the new values. The mismatch is between the PI gains and the actual plant dynamics.
第 1 步:用正确参数运行整定器得到 PI 参数。第 2 步:保存整定结果,显式设置(不用
None)。第 3 步:修改
d 字典中的 init_R、init_Ld、init_Lq、init_Js。第 4 步:重新运行——由于增益已显式指定,整定器不会重新运行,但 CTRL 和 ACM 都会用新的(失配的)参数初始化。
这意味着 PI 增益是为原始被控对象设计的,但控制器内部模型和被控对象现在都有了新值。失配发生在 PI 增益和实际被控对象动态之间。
Code: parameter mismatch experiment代码:参数失配实验
import copy
# Step 1: Tune with correct parameters
d_baseline = copy.deepcopy(d)
d_baseline['CL_SERIES_KP'] = None # auto-tune
sim_matched = Simulation_Benchmark(d_baseline)
# Step 2: Save tuned gains
saved_gains = {
'CL_SERIES_KP': d_baseline['CL_SERIES_KP'],
'CL_SERIES_KI': d_baseline['CL_SERIES_KI'],
'VL_SERIES_KP': d_baseline['VL_SERIES_KP'],
'VL_SERIES_KI': d_baseline['VL_SERIES_KI'],
}
# Step 3: Run with parameter mismatch
d_mismatch = copy.deepcopy(d)
d_mismatch.update(saved_gains) # use pre-tuned gains, skip re-tuning
d_mismatch['init_R'] = d['init_R'] * 1.5 # +50% resistance (thermal)
d_mismatch['init_Ld'] = d['init_Ld'] * 0.7 # -30% inductance (saturation)
d_mismatch['init_Lq'] = d['init_Lq'] * 0.7
d_mismatch['init_Js'] = d['init_Js'] * 2.0 # +100% inertia (load)
sim_mismatched = Simulation_Benchmark(d_mismatch)
- Scenario A: Matched parameters + decoupling ON (baseline)场景 A:参数匹配 + 解耦开启(基准)
- Scenario B: Mismatched parameters + decoupling ON场景 B:参数失配 + 解耦开启
- Scenario C: Mismatched parameters + decoupling OFF场景 C:参数失配 + 解耦关闭
Why does parameter mismatch hurt decoupling more than no-decoupling?为什么参数失配对解耦的伤害大于无解耦?
Without decoupling, the PI handles cross-coupling as a generic disturbance. With decoupling, wrong parameters mean you actively inject the wrong compensation.没有解耦时,PI 将交叉耦合当作一般扰动处理。有解耦时,错误的参数意味着你在主动注入错误的补偿。
Which parameters are most sensitive?哪些参数最敏感?
Try varying R, L, J separately. Which one causes the most degradation? Can you explain from the equations?尝试分别改变 R、L、J,哪一个引起的退化最严重?能否从方程解释?
Predict disturbances and actively compensate 预测扰动并主动补偿
The speed observer in the code (DYNAMICS_SpeedObserver, line 417) estimates not only rotor speed but also a disturbance state xS[2], which represents the total disturbance — including load torque and modeling errors. When the disturbance feedforward is enabled, this estimate is actively fed forward to the speed controller, compensating for disturbances before the PI regulator has to react.
代码中的速度观测器(DYNAMICS_SpeedObserver,第 417 行)不仅估计转子速度,还估计扰动状态 xS[2],它代表总扰动——包括负载转矩和建模误差。启用扰动前馈时,该估计值会主动前馈给速度控制器,在 PI 调节器反应之前就补偿扰动。
Observer dynamics观测器动态
where $e_\theta = \theta_d - \hat{\theta}_d$ is the position estimation error and $\ell_1, \ell_2, \ell_3$ are observer gains (configured via omega_ob).
其中 $e_\theta = \theta_d - \hat{\theta}_d$ 是位置估计误差,$\ell_1, \ell_2, \ell_3$ 是观测器增益(通过 omega_ob 配置)。
How to enable如何启用
# After creating Simulation_Benchmark with bool_start_simulation=False,
# modify CTRL before running:
CTRL.index_separate_speed_estimation = 1 # use observer for speed
CTRL.use_disturbance_feedforward_rejection = 1 # feed xS[2] forward
# Mode 2: CTRL.use_disturbance_feedforward_rejection = 2
# adds correction: xS[2] + ell2 * output_error (faster but noisier)
- Enable the observer and disturbance feedforward. Apply a step load torque and show that the observer estimates
xS[2]converge to the true load. Compare speed recovery with and without feedforward.启用观测器和扰动前馈。施加阶跃负载转矩,展示观测器估计xS[2]收敛到真实负载。对比有无前馈时的速度恢复。 - Under parameter mismatch + decoupling ON (Scenario B from Part 3), enable the observer. Does the disturbance estimate partially compensate for the decoupling error caused by wrong parameters? Show waveforms comparing observer ON vs OFF under mismatch.在参数失配 + 解耦开启(Part 3 的场景 B)下,启用观测器。扰动估计是否能部分补偿由错误参数引起的解耦误差?展示失配下观测器开启 vs 关闭的波形对比。
Why can an observer compensate for modeling errors?观测器为什么能补偿建模误差?
The observer lumps all unmodeled dynamics (load torque, friction, parameter errors) into a single disturbance state. Explain why this works and what its limitations are.观测器将所有未建模动态(负载转矩、摩擦、参数误差)归入单一扰动状态。解释这为何有效,以及其局限性。
Mode 1 vs Mode 2: which is better?模式 1 vs 模式 2:哪个更好?
use_disturbance_feedforward_rejection = 1 uses xS[2] directly; mode 2 adds ell2 * output_error. Compare both. When does the extra correction help, and when does it introduce noise?use_disturbance_feedforward_rejection = 1 直接用 xS[2];模式 2 增加了 ell2 * output_error。对比两者,额外校正何时有益,何时引入噪声?
index_separate_speed_estimation and use_disturbance_feedforward_rejection, you need to modify the CTRL object after it is created. Use bool_start_simulation=False in Simulation_Benchmark, then call get_global_objects() to get CTRL, modify it, and run the simulation loop manually. Study lines 1403–1457 of tutorials_ep6_svpwm.py for reference.
要设置 index_separate_speed_estimation 和 use_disturbance_feedforward_rejection,需要在 CTRL 对象创建后修改它。在 Simulation_Benchmark 中使用 bool_start_simulation=False,然后调用 get_global_objects() 获取 CTRL,修改后手动运行仿真循环。参考 tutorials_ep6_svpwm.py 的第 1403–1457 行。
Required content of the Markdown reportMarkdown 报告要求
- Bandwidth vs. performance metrics — rise time, overshoot, steady-state error as functions of
FOC_desired_VLBW_HZ.带宽 vs. 性能指标——上升时间、超调量、稳态误差关于FOC_desired_VLBW_HZ的曲线。 - Decoupling ON vs. OFF — waveform comparison at the same bandwidth.解耦开启 vs. 关闭——相同带宽下的波形对比。
- Three-scenario comparison — matched+decouple, mismatched+decouple, mismatched+no-decouple.三场景对比——匹配+解耦、失配+解耦、失配+无解耦。
- Observer disturbance compensation —
xS[2]convergence under load step, and observer ON vs OFF under parameter mismatch.观测器扰动补偿——负载阶跃下xS[2]的收敛,以及参数失配下观测器开启 vs 关闭的对比。
Mandatory必须包含
Suggested report structure建议结构
- Introduction and objectives引言与目标
- Part 1: Bandwidth sweep methodology and resultsPart 1:带宽扫描方法与结果
- Part 2: Decoupling analysisPart 2:解耦分析
- Part 3: Robustness under parameter mismatchPart 3:参数失配下的鲁棒性
- Part 4: Observer-based disturbance compensationPart 4:基于观测器的扰动补偿
- Conclusion结论
Project 3: 4th-order observer, disturbance feedforward, and time-varying load analysis Project 3:四阶观测器、扰动前馈与时变负载分析
From constant disturbance to time-varying disturbance 从恒定扰动到时变扰动
The mechanical equation机械方程
Define the total disturbance $d_{to}$ as everything the controller does not model: 定义总扰动 $d_{to}$ 为控制器未建模的所有内容:
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$。
Gains placed at $(s + \omega_{ob})^3$:增益配置在 $(s + \omega_{ob})^3$:
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$。
Gains placed at $(s + \omega_{ob})^4$:增益配置在 $(s + \omega_{ob})^4$:
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。
- Modify
get_global_objects()intutorials_ep6_svpwm.pyso that after creatingCTRL, you can overwriteCTRL.ell1–CTRL.ell4based on a new config keyd['observer_order'](3 or 4).修改tutorials_ep6_svpwm.py中的get_global_objects(),在创建CTRL后,根据新的配置键d['observer_order'](3 或 4)重写CTRL.ell1–CTRL.ell4。 - Set
CTRL.index_separate_speed_estimation = 1to enable the observer.设置CTRL.index_separate_speed_estimation = 1来启用观测器。 - Verify with a step load: both 3rd-order and 4th-order should track a constant
ACM.TLoad = 0.2with zero steady-state error inxS[2].用阶跃负载验证:三阶和四阶都应以零稳态误差跟踪恒定ACM.TLoad = 0.2的xS[2]。
The_Motor_Controller is a @jitclass. You cannot add new fields. But ell1–ell4 and xS[0:5] already exist — no spec changes needed. You can freely overwrite their values after construction.
The_Motor_Controller 是 @jitclass,不能添加新字段。但 ell1–ell4 和 xS[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$ 电流:
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)
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 证明四阶观测器能跟踪斜坡扰动
| Scenario场景 | Observer观测器 | Feedforward前馈 | Expected result预期结果 |
|---|---|---|---|
| A | 3rd-order | OFF | Baseline, PI only基准,仅 PI |
| B | 3rd-order | ON | FF helps but cannot eliminate ramp lagFF 有帮助但无法消除斜坡滞后 |
| C | 4th-order | OFF | Better estimation, no compensation更好的估计,但无补偿 |
| D | 4th-order | ON | Best: 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_rpmvs actual speedCTRL.omega_r_mech[rpm]子图 1:速度给定CTRL.cmd_rpmvs 实际速度CTRL.omega_r_mech[rpm] - Subplot 2: Actual load
ACM.TLoadvs estimated disturbanceCTRL.xS[2](note: opposite sign)子图 2:实际负载ACM.TLoadvs 估计扰动CTRL.xS[2](注意:符号相反) - Subplot 3: Estimated rate
CTRL.xS[3]— should converge to the ramp slope for 4th-order子图 3:估计变化率CTRL.xS[3]——四阶时应收敛到斜坡斜率
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: 闭环系统的输出可以分解为三条通道:
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?对比三阶和四阶观测器系统的阶跃响应(上升时间、超调)。观测器阶数是否影响跟踪性能?为什么?
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?在斜坡负载下,三阶和四阶(均开前馈)的稳态速度误差分别是多少?你能从内模原理推导理论误差吗?
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] 中的噪声。在相同带宽下,四阶观测器是否比三阶更嘈杂?权衡是什么?
- Add the Bode plot obtained from sweeping the transfer path $\hat{T}_L / T_L$, where the input is the actual load torque and the output is the observer-estimated load torque.补充对传递路径 $\hat{T}_L / T_L$ 进行扫频后得到的伯德图,其中输入为实际负载转矩,输出为观测器估计的负载转矩。
- At $\omega = 0$ rpm and load-torque amplitude $0.15\,\mathrm{N\cdot m}$, perform a load-torque frequency sweep and include both the resulting Bode plot and the corresponding time-domain waveforms.在 $\omega = 0$ rpm、负载转矩幅值为 $0.15\,\mathrm{N\cdot m}$ 的条件下,对负载转矩进行扫频,并给出对应的伯德图和时域波形图。
Required content of the Markdown reportMarkdown 报告要求
- Step load comparison — 4 scenarios (A–D), speed + disturbance estimate waveforms.阶跃负载对比——4 种场景(A–D),速度 + 扰动估计波形。
- Ramp load comparison — 4 scenarios (A–D), speed + disturbance estimate + rate estimate waveforms.斜坡负载对比——4 种场景(A–D),速度 + 扰动估计 + 变化率估计波形。
- Code diff — show the exact lines you modified in
tutorials_ep6_svpwm.py.代码差异——展示你在tutorials_ep6_svpwm.py中修改的确切行。 - Bode plot of $\hat{T}_L / T_L$ — frequency response from actual load torque to estimated load torque.$\hat{T}_L / T_L$ 的伯德图——从实际负载转矩到估计负载转矩的频率响应。
- Load-torque sweep at $\omega = 0$ rpm, amplitude $0.15\,\mathrm{N\cdot m}$ — include both the Bode plot and the time-domain waveforms.$\omega = 0$ rpm、幅值 $0.15\,\mathrm{N\cdot m}$ 的负载转矩扫频——同时包含伯德图和时域波形图。
Mandatory必须包含
FOC() with correct unit conversion.前馈接入 FOC(),单位转换正确。Suggested report structure建议结构
- Background: why higher-order observer背景:为什么需要高阶观测器
- Code modifications (with diff)代码修改(附差异)
- Step load experiments and analysis阶跃负载实验与分析
- Ramp load experiments and analysis斜坡负载实验与分析
- Bode analysis and load-torque sweep results伯德图分析与负载转矩扫频结果
- Conclusion结论
How to submit 提交方式
Please submit Markdown according to the course announcement. 请按课程通知提交 Markdown。
This page does not provide online upload. 本页面不提供在线上传。