335 lines
10 KiB
TOML
335 lines
10 KiB
TOML
# chassis-tune 超参数预设
|
||
#
|
||
# 一次整定的结果不只取决于被控对象与种子,还取决于"搜什么区间、用哪个场景、
|
||
# 什么算好、什么算达标、搜多细"。这份文件把这些**实验条件**固化下来:
|
||
# 评审一次、长期复用、任何机器上都能复现同一组默认行为。
|
||
#
|
||
# 用法:
|
||
# chassis-tune presets # 列出本文件全部预设
|
||
# chassis-tune sweep --preset config/tune.toml # 用 default_preset
|
||
# chassis-tune sweep --preset config/tune.toml --preset-name bench_loaded
|
||
# chassis-tune sweep --preset-name bench_loaded # 缺省路径即本文件
|
||
# chassis-tune sweep --preset config/tune.toml --samples 128 # CLI 覆盖预设的单项
|
||
#
|
||
# 优先级:内置默认 < 本文件的预设 < 显式命令行参数(逐字段覆盖)。
|
||
# 本文件里没写的项一律沿用内置默认,因此预设只需写"与默认不同"的部分——
|
||
# 但为了让评审者一眼看全工况,下面每个预设都写全了关键项。
|
||
#
|
||
# **安全边界**:current_limit / direction / gear_ratio / 电调 ID / 串口设备名
|
||
# 不属于超参数,本文件**不接受**这些键(写了会直接报错)。它们只来自
|
||
# chassis.toml 或显式 CLI——否则预设文件就成了绕过限流的口子。
|
||
#
|
||
# schema:见 crates/chassis-tune/src/preset.rs(version = 1,未知键报错)。
|
||
|
||
version = 1
|
||
default_preset = "sim_bench_model"
|
||
|
||
# ---------------------------------------------------------------- 离线:台架量级模型
|
||
# 默认预设。评审、CI 冒烟、改完代码回归都用它:不碰硬件,结果可复现。
|
||
[preset.sim_bench_model]
|
||
description = "离线 · 台架量级模型(静/库仑摩擦 + 2 拍延迟):全量搜索,评审与回归的基准"
|
||
|
||
[preset.sim_bench_model.space]
|
||
# kp 覆盖手调基线 2 与仿真最优 8 两侧;对数刻度保证小增益也被采样到。
|
||
kp = { min = 0.5, max = 30.0, scale = "log" }
|
||
# ki 允许精确取 0(纯比例在某些工况已经够用)。
|
||
ki = { min = 0.1, max = 100.0, scale = "log0" }
|
||
# kd 半概率取 0:速度环加微分对量化噪声敏感,先让搜索自己决定要不要。
|
||
kd = { min = 0.01, max = 3.0, scale = "log0" }
|
||
# 前馈上限 2.5 覆盖带载所需的 ≈1.77(raw/rpm)。
|
||
feedforward = { min = 0.01, max = 2.5, scale = "log0" }
|
||
|
||
[preset.sim_bench_model.scenario]
|
||
profile = "ramp-and-hold"
|
||
target_rpm = 1500.0
|
||
ramp_ms = 200.0
|
||
hold_ms = 1800.0
|
||
dt_us = 1000.0
|
||
|
||
[preset.sim_bench_model.cost]
|
||
# 跟得上、不过冲最重要;电流只作次要惩罚(省电流不是目的,避免烧电调才是)。
|
||
settle = 1.0
|
||
overshoot = 1.0
|
||
iae = 0.5
|
||
effort = 0.1
|
||
|
||
[preset.sim_bench_model.acceptance]
|
||
max_overshoot_pct = 20.0
|
||
max_ss_error_pct = 5.0
|
||
|
||
[preset.sim_bench_model.search]
|
||
seed = 20260101
|
||
samples = 512
|
||
top_k = 8
|
||
solver = "nelder-mead"
|
||
max_iters = 200
|
||
particles = 24
|
||
max_evals = 4000
|
||
threads = 0
|
||
|
||
[preset.sim_bench_model.sim]
|
||
plant = "gm3508-bench"
|
||
# 域随机化:单点模型调出来的增益对增益/时间常数/延迟高度敏感,
|
||
# 因此默认在 8 个成员的集成上做鲁棒优化,而不是对着一条理想曲线最优化。
|
||
ensemble = 8
|
||
robust_weight = 0.5
|
||
gain_pct = 0.2
|
||
tau_pct = 0.3
|
||
delay_ticks_max = 3
|
||
friction_pct = 0.5
|
||
|
||
[preset.sim_bench_model.bench]
|
||
# 离线预设不用台架,但安全包络仍写全,方便临时切 --backend bench 预演。
|
||
max_rpm = 3000.0
|
||
max_temp_c = 70
|
||
trial_timeout_ms = 6000
|
||
between_trials_ms = 500
|
||
startup_timeout_ms = 5000
|
||
continue_on_abort = false
|
||
validate_runs = 3
|
||
|
||
# ---------------------------------------------------------------- 离线:理想模型
|
||
# 无摩擦、无延迟的一阶模型:跑得快,适合改完控制逻辑后的秒级回归,
|
||
# **不要**拿它的结果直接上车(模型里没有摩擦与延迟,最优解会偏激进)。
|
||
[preset.sim_ideal]
|
||
description = "离线 · 理想一阶模型(无摩擦无延迟):秒级回归用,结果不可直接上车"
|
||
|
||
[preset.sim_ideal.space]
|
||
kp = { min = 0.5, max = 30.0, scale = "log" }
|
||
ki = { min = 0.1, max = 100.0, scale = "log0" }
|
||
kd = { min = 0.01, max = 3.0, scale = "log0" }
|
||
feedforward = { min = 0.01, max = 2.5, scale = "log0" }
|
||
|
||
[preset.sim_ideal.scenario]
|
||
profile = "ramp-and-hold"
|
||
target_rpm = 1500.0
|
||
ramp_ms = 200.0
|
||
hold_ms = 1800.0
|
||
dt_us = 1000.0
|
||
|
||
[preset.sim_ideal.cost]
|
||
settle = 1.0
|
||
overshoot = 1.0
|
||
iae = 0.5
|
||
effort = 0.1
|
||
|
||
[preset.sim_ideal.acceptance]
|
||
max_overshoot_pct = 20.0
|
||
max_ss_error_pct = 5.0
|
||
|
||
[preset.sim_ideal.search]
|
||
seed = 20260101
|
||
samples = 128
|
||
top_k = 4
|
||
solver = "nelder-mead"
|
||
max_iters = 100
|
||
particles = 16
|
||
max_evals = 1000
|
||
threads = 0
|
||
|
||
[preset.sim_ideal.sim]
|
||
plant = "gm3508"
|
||
# 理想模型本身就是确定的,单成员即可。
|
||
ensemble = 1
|
||
robust_weight = 0.0
|
||
gain_pct = 0.0
|
||
tau_pct = 0.0
|
||
delay_ticks_max = 0
|
||
friction_pct = 0.0
|
||
|
||
[preset.sim_ideal.bench]
|
||
max_rpm = 3000.0
|
||
max_temp_c = 70
|
||
trial_timeout_ms = 6000
|
||
between_trials_ms = 500
|
||
startup_timeout_ms = 5000
|
||
continue_on_abort = false
|
||
validate_runs = 3
|
||
|
||
# ---------------------------------------------------------------- 台架:空载
|
||
# 轮子架空(无地面载荷)。摩擦小、静差靠积分压制,前馈**必须为 0**:
|
||
# 空载加前馈会把轮子直接推到最高转速。目标转速也压低,便于观察与急停。
|
||
[preset.bench_noload]
|
||
description = "真机台架 · 空载(轮子架空):小样本局部搜索,禁用前馈,目标 800 rpm"
|
||
# 真机后端:仍然需要 --i-know-the-wheel-spins 才会真的驱动电机。
|
||
backend = "bench"
|
||
|
||
[preset.bench_noload.space]
|
||
# 空载好解在手调基线(kp≈2, ki≈10)附近,区间收紧以提高样本密度。
|
||
kp = { min = 0.2, max = 12.0, scale = "log" }
|
||
ki = { min = 0.1, max = 50.0, scale = "log0" }
|
||
kd = { min = 0.01, max = 1.0, scale = "log0" }
|
||
# 固定为 0:单点区间 + 线性刻度 = 搜索时该轴恒定。
|
||
feedforward = { min = 0.0, max = 0.0, scale = "linear" }
|
||
|
||
[preset.bench_noload.scenario]
|
||
profile = "ramp-and-hold"
|
||
target_rpm = 800.0
|
||
ramp_ms = 300.0
|
||
hold_ms = 1700.0
|
||
dt_us = 1000.0
|
||
|
||
[preset.bench_noload.cost]
|
||
settle = 1.0
|
||
overshoot = 1.0
|
||
iae = 0.5
|
||
effort = 0.1
|
||
|
||
[preset.bench_noload.acceptance]
|
||
# 空载量化噪声相对目标更大,放宽到 25%,避免"为了 0.5% 的稳态误差过冲"。
|
||
max_overshoot_pct = 25.0
|
||
max_ss_error_pct = 8.0
|
||
|
||
[preset.bench_noload.search]
|
||
seed = 20260101
|
||
# 只有一条总线,每次试验 2s,24 次 ≈ 1 分钟:够做局部精修,不够铺满空间。
|
||
samples = 24
|
||
top_k = 3
|
||
solver = "nelder-mead"
|
||
max_iters = 40
|
||
particles = 12
|
||
max_evals = 40
|
||
threads = 1
|
||
|
||
[preset.bench_noload.sim]
|
||
# 真机后端不用这些,但保留"最接近台架的模型",方便先离线预演再上车。
|
||
plant = "gm3508-bench"
|
||
ensemble = 8
|
||
robust_weight = 0.5
|
||
gain_pct = 0.2
|
||
tau_pct = 0.3
|
||
delay_ticks_max = 3
|
||
friction_pct = 0.5
|
||
|
||
[preset.bench_noload.bench]
|
||
# 目标是 800,过速保护留足裕量但远低于电调上限。
|
||
max_rpm = 2000.0
|
||
max_temp_c = 60
|
||
trial_timeout_ms = 6000
|
||
between_trials_ms = 500
|
||
startup_timeout_ms = 5000
|
||
continue_on_abort = false
|
||
# 同一组增益跑 3 次看重复性;离散度大说明参数贴着噪声,不该上车。
|
||
validate_runs = 3
|
||
|
||
# ---------------------------------------------------------------- 台架:带载
|
||
# 整车落地 / 配重(有地面摩擦与惯量)。静差明显,前馈开始有意义(覆盖 ≈1.77)。
|
||
[preset.bench_loaded]
|
||
description = "真机台架 · 带载(整车落地/配重):前馈区间上调,目标 1200 rpm,超调收紧"
|
||
backend = "bench"
|
||
|
||
[preset.bench_loaded.space]
|
||
kp = { min = 0.5, max = 30.0, scale = "log" }
|
||
ki = { min = 0.5, max = 100.0, scale = "log0" }
|
||
kd = { min = 0.01, max = 3.0, scale = "log0" }
|
||
# 带载需要前馈抵消摩擦:下限不为 0,让搜索必须考虑它。
|
||
feedforward = { min = 0.5, max = 2.5, scale = "log" }
|
||
|
||
[preset.bench_loaded.scenario]
|
||
profile = "ramp-and-hold"
|
||
target_rpm = 1200.0
|
||
ramp_ms = 300.0
|
||
hold_ms = 2200.0
|
||
dt_us = 1000.0
|
||
|
||
[preset.bench_loaded.cost]
|
||
settle = 1.0
|
||
overshoot = 1.0
|
||
iae = 0.5
|
||
effort = 0.1
|
||
|
||
[preset.bench_loaded.acceptance]
|
||
# 带载下超调意味着实际位移过冲,收紧到 15%。
|
||
max_overshoot_pct = 15.0
|
||
max_ss_error_pct = 5.0
|
||
|
||
[preset.bench_loaded.search]
|
||
seed = 20260101
|
||
samples = 32
|
||
top_k = 4
|
||
solver = "nelder-mead"
|
||
max_iters = 60
|
||
particles = 16
|
||
max_evals = 80
|
||
threads = 1
|
||
|
||
[preset.bench_loaded.sim]
|
||
plant = "gm3508-bench"
|
||
ensemble = 8
|
||
robust_weight = 0.5
|
||
gain_pct = 0.2
|
||
tau_pct = 0.3
|
||
delay_ticks_max = 3
|
||
friction_pct = 0.5
|
||
|
||
[preset.bench_loaded.bench]
|
||
max_rpm = 2500.0
|
||
max_temp_c = 70
|
||
trial_timeout_ms = 8000
|
||
between_trials_ms = 800
|
||
startup_timeout_ms = 5000
|
||
continue_on_abort = false
|
||
validate_runs = 3
|
||
|
||
# ---------------------------------------------------------------- 实战验收:双向
|
||
# 上车前的最后一道关:升速 → 保持 → 降速 → 保持(回零),验的是双向跟随与
|
||
# 回零能力,比单向斜坡更接近实战。样本很少(围绕现有增益做局部复算),
|
||
# 因为此时**不该**再大改增益,只想确认现有一组在两个方向上都不出问题。
|
||
[preset.field_updown]
|
||
description = "真机实战验收 · 升降速双向(回零):小样本复验,超调与稳态误差收紧"
|
||
backend = "bench"
|
||
|
||
[preset.field_updown.space]
|
||
kp = { min = 0.5, max = 30.0, scale = "log" }
|
||
ki = { min = 0.5, max = 100.0, scale = "log0" }
|
||
kd = { min = 0.01, max = 3.0, scale = "log0" }
|
||
feedforward = { min = 0.5, max = 2.5, scale = "log" }
|
||
|
||
[preset.field_updown.scenario]
|
||
profile = "up-down"
|
||
target_rpm = 1200.0
|
||
ramp_ms = 400.0
|
||
hold_ms = 800.0
|
||
dt_us = 1000.0
|
||
|
||
[preset.field_updown.cost]
|
||
# 双向场景里稳态误差(尤其回零)比调节时间更重要。
|
||
settle = 1.0
|
||
overshoot = 1.0
|
||
iae = 1.0
|
||
effort = 0.1
|
||
|
||
[preset.field_updown.acceptance]
|
||
max_overshoot_pct = 12.0
|
||
max_ss_error_pct = 3.0
|
||
|
||
[preset.field_updown.search]
|
||
seed = 20260101
|
||
samples = 16
|
||
top_k = 2
|
||
solver = "nelder-mead"
|
||
max_iters = 30
|
||
particles = 12
|
||
max_evals = 40
|
||
threads = 1
|
||
|
||
[preset.field_updown.sim]
|
||
plant = "gm3508-bench"
|
||
ensemble = 8
|
||
robust_weight = 0.5
|
||
gain_pct = 0.2
|
||
tau_pct = 0.3
|
||
delay_ticks_max = 3
|
||
friction_pct = 0.5
|
||
|
||
[preset.field_updown.bench]
|
||
max_rpm = 2500.0
|
||
max_temp_c = 70
|
||
# 双向场景总时长翻倍,超时也翻倍。
|
||
trial_timeout_ms = 10000
|
||
between_trials_ms = 1000
|
||
startup_timeout_ms = 5000
|
||
continue_on_abort = false
|
||
# 验收阶段多跑几次,重复性不过关就不签字。
|
||
validate_runs = 5
|