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 final PDF report最终 PDF 报告要求
- 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结论
Online submission is currently disabled.当前暂不支持在线提交。 Please prepare your report as a PDF. The upload form is intentionally hidden for now. 请先准备 PDF 报告。上传区域目前已隐藏。