Files
linux_sentry_chassis/config/tune.toml
T

335 lines
10 KiB
TOML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 = 1500
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