Coding Project 2 / PI Tuning & Robustness

How does bandwidth interact with decoupling and parameter mismatch? 带宽设计如何与前馈解耦和参数失配相互作用?

In Project 1 you explored frequency-domain sweeps. Now you shift to time-domain step response metrics — rise time, overshoot, steady-state error — and investigate how feedforward decoupling and model accuracy affect performance. You will sweep bandwidths, toggle decoupling, introduce parameter mismatch, and optionally enable a load torque observer. 在 Project 1 中你分析了频域扫频。现在转向时域阶跃响应指标——上升时间、超调量、稳态误差——并研究前馈解耦和模型精度如何影响控制性能。你需要扫描带宽、切换解耦、引入参数失配,还可以选做负载转矩观测器。

Core scripts核心脚本
simulation/tuner.py
simulation/tutorials_ep6_svpwm.py
Keywords关键词
bandwidth / rise time / overshoot / decoupling / mismatch
Expected output建议产出
figures + analysis + code图 + 分析 + 代码
Report format报告形式
PDF

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代码入口与环境参考

Recommended repository推荐参考仓库
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_Benchmark class: around line 1307. This is your main entry point.Simulation_Benchmark 类:约第 1307 行。这是你的主要入口。
  • Example d_user_input dictionary: around line 1475.示例 d_user_input 字典:约第 1475 行。

simulation/tuner.py

  • tunner_wrapper(d) — auto-tunes PI gains when CL_SERIES_KP is None.tunner_wrapper(d)——当 CL_SERIES_KPNone 时自动整定 PI 参数。
  • iterate_for_desired_bandwidth() — iterates current-loop BW to achieve desired speed-loop BW.iterate_for_desired_bandwidth()——迭代电流环带宽以达到期望的速度环带宽。
  • FOC_delta controls the damping ratio of the speed loop.FOC_delta 控制速度环的阻尼比。
  • FOC_desired_VLBW_HZ is the target speed-loop bandwidth in Hz.FOC_desired_VLBW_HZ 是目标速度环带宽(Hz)。

Variables you should know至少要熟悉这些变量

FOC_delta FOC_desired_VLBW_HZ CL_SERIES_KP / KI VL_SERIES_KP / KI CTRL.bool_apply_decoupling_voltages_to_current_regulation index_separate_speed_estimation use_disturbance_feedforward_rejection init_R / init_Ld / init_Lq / init_Js

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_KPNone 时,Simulation_Benchmark 类会调用 tuner.tunner_wrapper(d),通过迭代找到满足期望带宽的电流环和速度环 PI 参数。核心公式:

$$K_{p,i}=2\pi L\,\text{BW}_c,\qquad K_{i,i}=\frac{R}{L}$$
$$K_{i,\omega}=\frac{\omega_{ci}}{\delta^2},\qquad K_{p,\omega}=\frac{J_s/n_{pp}}{1.5\,n_{pp}K_A}\,\delta\, K_{i,\omega}$$

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阶跃响应指标

$$t_r = t_{90\%} - t_{10\%} \quad\text{(rise time)}$$
$$\text{Overshoot} = \frac{y_{\max} - y_{ss}}{y_{ss}} \times 100\%$$
$$e_{ss} = |y_{ss} - y_{\text{ref}}| \quad\text{(steady-state error)}$$
Task 1: Bandwidth sweep任务 1:带宽扫描 Write a Python script that loops over multiple values of 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)
Think about this思考这些问题 Higher bandwidth generally means faster rise time but may increase overshoot. 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
Q1

When the system responds faster, what is the cost?当系统响应更快时,代价是什么?

Think about overshoot, noise sensitivity, voltage saturation, and stability margin.考虑超调、噪声敏感性、电压饱和和稳定裕度。

Q2

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 坐标系电压方程为:

$$u_d = R\,i_d + L_d \frac{di_d}{dt} \underbrace{- \omega_e L_q\, i_q}_{\text{cross-coupling}}$$
$$u_q = R\,i_q + L_q \frac{di_q}{dt} + \underbrace{\omega_e (K_E + L_d\, i_d)}_{\text{cross-coupling + back-EMF}}$$

The underbraced terms act as disturbances to the PI current regulators. Feedforward decoupling adds compensation voltages to cancel them: 下划线部分是对 PI 电流调节器的扰动。前馈解耦通过补偿电压来抵消它们:

$$u_{d,\text{ff}} = -\omega_e L_q\, i_q^*,\qquad u_{q,\text{ff}} = +\omega_e (K_A + L_q\, i_d^*)$$

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$ 的准确性。

Task 2: Decoupling comparison任务 2:解耦对比 At the same bandwidth, run the simulation with decoupling ON and OFF. Compare speed tracking, $i_d$ / $i_q$ current waveforms, and $u_d$ / $u_q$ voltage waveforms. Show at least 2 figures (one per setting). Discuss which setting performs better and under what conditions. 在相同带宽下,分别开启和关闭解耦运行仿真。对比速度跟踪、$i_d$ / $i_q$ 电流波形和 $u_d$ / $u_q$ 电压波形。至少展示 2 张图(每种设置一张)。讨论哪种设置更好,以及在什么条件下。

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)
Q3

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$)不准确时会怎样?此时前馈是帮助还是损害?

Q4

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.LqCTRL.KA 来计算补偿电压。如果这些值是错误的(即与实际被控对象不匹配),前馈就会注入误差而非抵消扰动。

Key insight: how to introduce mismatch关键点:如何引入参数失配 Step 1: Run the tuner with correct parameters to get PI gains.
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_Rinit_Ldinit_Lqinit_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)
Hint: what to compare提示:比较什么 The most revealing comparison is between decoupling ON vs OFF under the same mismatch. If decoupling makes things worse under mismatch, that proves the feedforward is injecting errors based on wrong parameters. 最有说明力的对比是在相同失配下,解耦开启 vs 关闭。如果失配时解耦反而更差,就证明了前馈基于错误参数在注入误差。
Task 3: Three-scenario comparison任务 3:三场景对比
  1. Scenario A: Matched parameters + decoupling ON (baseline)场景 A:参数匹配 + 解耦开启(基准)
  2. Scenario B: Mismatched parameters + decoupling ON场景 B:参数失配 + 解耦开启
  3. Scenario C: Mismatched parameters + decoupling OFF场景 C:参数失配 + 解耦关闭
Compare speed tracking and current waveforms across all three scenarios. Explain why Scenario B may perform worse than Scenario C. 对比三种场景下的速度跟踪和电流波形。解释为什么场景 B 可能比场景 C 更差
Q5

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 将交叉耦合当作一般扰动处理。有解耦时,错误的参数意味着你在主动注入错误的补偿。

Q6

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观测器动态

$$\dot{\hat{\theta}}_d = \ell_1 e_\theta + \hat{\omega}_r$$
$$\dot{\hat{\omega}}_r = \ell_2 e_\theta + \frac{T_{em} + \hat{T}_L}{J_s / n_{pp}}$$
$$\dot{\hat{T}}_L = \ell_3 e_\theta$$

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)
Task 4: Observer-based disturbance compensation任务 4:基于观测器的扰动补偿
  1. 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] 收敛到真实负载。对比有无前馈时的速度恢复。
  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 关闭的波形对比。
Q7

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.观测器将所有未建模动态(负载转矩、摩擦、参数误差)归入单一扰动状态。解释这为何有效,以及其局限性。

Q8

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。对比两者,额外校正何时有益,何时引入噪声?

Implementation note实现说明 To set 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_estimationuse_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 报告要求

The final PDF must contain these 4 core figures最终 PDF 必须包含这 4 张核心图
  1. Bandwidth vs. performance metrics — rise time, overshoot, steady-state error as functions of FOC_desired_VLBW_HZ.带宽 vs. 性能指标——上升时间、超调量、稳态误差关于 FOC_desired_VLBW_HZ 的曲线。
  2. Decoupling ON vs. OFF — waveform comparison at the same bandwidth.解耦开启 vs. 关闭——相同带宽下的波形对比。
  3. Three-scenario comparison — matched+decouple, mismatched+decouple, mismatched+no-decouple.三场景对比——匹配+解耦、失配+解耦、失配+无解耦。
  4. Observer disturbance compensationxS[2] convergence under load step, and observer ON vs OFF under parameter mismatch.观测器扰动补偿——负载阶跃下 xS[2] 的收敛,以及参数失配下观测器开启 vs 关闭的对比。

Mandatory必须包含

Bandwidth sweep code and resulting plot (Part 1).带宽扫描代码和结果图(Part 1)。
Decoupling ON/OFF comparison with discussion (Part 2).解耦开启/关闭对比及讨论(Part 2)。
Parameter mismatch experiment with at least R and L varied (Part 3).参数失配实验,至少改变 R 和 L(Part 3)。
Observer disturbance compensation with load step and mismatch (Part 4).观测器扰动补偿,含负载阶跃和参数失配(Part 4)。
Direct answers to Q1–Q8, not figures without explanation.逐条回答 Q1–Q8,不能只放图不解释。

Suggested report structure建议结构

  1. Introduction and objectives引言与目标
  2. Part 1: Bandwidth sweep methodology and resultsPart 1:带宽扫描方法与结果
  3. Part 2: Decoupling analysisPart 2:解耦分析
  4. Part 3: Robustness under parameter mismatchPart 3:参数失配下的鲁棒性
  5. Part 4: Observer-based disturbance compensationPart 4:基于观测器的扰动补偿
  6. Conclusion结论

Online submission is currently disabled.当前暂不支持在线提交。 Please prepare your report as a PDF. The upload form is intentionally hidden for now. 请先准备 PDF 报告。上传区域目前已隐藏。