feat: 添加了自动超参数整定

This commit is contained in:
Horldsence
2026-09-23 00:42:26 +08:00
parent 7d87987e41
commit 680adae339
56 changed files with 13664 additions and 245 deletions
+124 -14
View File
@@ -1,19 +1,33 @@
# sentry-chassis
机甲大师哨兵机器人麦轮底盘固件:Linux ARM 主控 + 4 × GM3508(C620 电调),SocketCAN 接入,tokio 异步架构。
机甲大师哨兵机器人麦轮底盘固件:Linux ARM 主控 + 4 × GM3508(C620 电调),CAN 接入(SocketCAN 或串口 slcan),tokio 异步架构。
## 架构一览
| crate | 职责 | 平台 |
| --- | --- | --- |
| [`motor-core`](crates/motor-core) | 电机抽象:`Motor` trait、`MotorState`、PID / 速度环控制器 | 纯逻辑,全平台 |
| [`dji-esc`](crates/dji-esc) | C620/C610 CAN 协议:帧编解码、多圈累计、`EscBus` 异步驱动、仿真器 | 纯逻辑,全平台 |
| [`motor-core`](crates/motor-core) | 电机抽象:能力 trait、`MotorState`、PID / 速度环 / 位置环 | 纯逻辑,全平台 |
| [`can-link`](crates/can-link) | CAN 传输抽象:`CanFrame` + `CanLink` 通道对(无协议知识) | 纯逻辑,全平台 |
| [`dji-esc`](crates/dji-esc) | C620/C610 CAN 协议:帧编解码、多圈累计、`EscBus` 异步驱动 | 纯逻辑,全平台 |
| [`dji-esc-sim`](crates/dji-esc-sim) | 被控对象仿真:摩擦 / 延迟 / 负载模型、场景与**离线评估 harness**、异步假电调 | 纯逻辑,全平台 |
| [`dji-esc-socketcan`](crates/dji-esc-socketcan) | SocketCAN 后端:真实 CAN 接口 ↔ 内存通道桥接 | Linux |
| [`dji-esc-slcan`](crates/dji-esc-slcan) | slcan 串口后端:CANable 等 USB 适配器 ↔ 内存通道桥接 | 全平台 |
| [`mecanum`](crates/mecanum) | 麦轮正 / 逆运动学(纯数学) | 全平台 |
| [`chassis-config`](crates/chassis-config) | `chassis.toml` schema:解析、校验、写回(守护进程与整定工具共用) | 全平台 |
| [`chassis-bench`](crates/chassis-bench) | 台架:激励场景、安全包络、真机试验采样 + `chassis-spin` / `socketcan-spin` | 全平台(SocketCAN 工具需 Linux) |
| [`chassis-tune`](crates/chassis-tune) | **速度环 PID 自动整定**:参数空间搜索 + 指标 / 成本 + 报告(仿真 / 真机)+ 版本化**超参数预设** | 全平台 |
| [`chassisd`](crates/chassisd) | 底盘守护进程:配置、1kHz 控制循环、安全逻辑、`--mock` 模式 | 全平台(实车需 Linux) |
分层原则:`motor-core` 与 `dji-esc` 不做任何真实 I/O——CAN 端口被抽象为一对 tokio 通道(`CanLink`),
因此协议、运动学与控制逻辑可以在 macOS / CI 上完整测试;真实总线只出现在最外层。
分层原则:`motor-core`、`dji-esc`、`dji-esc-sim` 不做任何真实 I/O——CAN 端口被抽象为一对 tokio 通道
(`CanLink`),因此协议、运动学、控制与整定逻辑可以在 macOS / CI 上完整测试;真实总线只出现在最外层
(`dji-esc-socketcan` / `dji-esc-slcan`,以及组合它们的 `chassis-bench` / `chassisd`)。
> 运输后端 crate(`dji-esc-slcan` / `dji-esc-socketcan`)只做桥接,**不含应用**;
> 台架程序住在 `chassis-bench`,自动整定住在 `chassis-tune`。
> **命令是租约**:`EscMotor::set_velocity` / `set_effort_raw` / `set_position` 每次调用即续租,
> 超过 `BusOptions::command_timeout`(默认 50ms)未刷新,驱动强制 0 电流。
> 控制循环必须**逐拍重发**同一个设定值(`chassisd` 的 1kHz 循环天然满足)。
## 开发
@@ -22,6 +36,7 @@
```sh
cargo test --workspace # 单测 + 闭环仿真测试(无需硬件)
cargo run -p chassisd -- --mock # 无硬件全链路演示
just tune-smoke # 自动整定冒烟(确定性,无需硬件,CI 同款)
just lint # fmt + clippy(与 CI 同标准)
```
@@ -31,31 +46,126 @@ just lint # fmt + clippy(与 CI 同标准)
just vcan-test # 或见 justfile 内的 modprobe / ip link 命令
```
### 部署到目标板(armv7,实测:创龙 T153 / Buildroot)
## 台架:四轮 500 rpm 旋转测试(slcan)
实车台架验证工具 `chassis-spin`:四轮同时以固定**转子**转速旋转(默认 500 rpm,
轮端 = 转子 ÷ 减速比 ≈ 26 rpm),带缓升、过速保护、上电门控与安全停机。
```sh
# 本机直接跑(CANable2 在 /dev/ttyACM0)
cargo run --release -p chassis-bench --bin chassis-spin -- --device /dev/ttyACM0
# 只验证链路与反馈,不发非零电流(接线排查首选)
cargo run --release -p chassis-bench --bin chassis-spin -- --device /dev/ttyACM0 --dry-run
# 目标板(T153,armv7):交叉编译 → 推送 → 运行
just bench-spin # 默认 root@192.168.2.2 + /dev/ttyACM0 + 500 rpm
just bench-check # 同上,但只做 dry-run
```
安全与使用要点:
- **轮子必须架空或整车固定**;ctrl-c 随时安全停机(先 0 电流再关总线)。
- 上电门控:四个电调都上报新鲜反馈前绝不下发速度;只接了部分电调时用 `--allow-partial` 降级。
- 过速保护:任一电调超过 `--max-rpm`(默认 目标 × 2 + 200)持续 60ms 即立即停机。
- 空载台架的合适整定与带载完全不同:默认 `kp=2 ki=10 ff=0 --current-limit 1500`,
空载**不要**加前馈(会直接把轮子推到最高速度)。
## 自动整定(chassis-tune)
手动试凑 `kp/ki/kd/ff` 既慢又难复现。`chassis-tune` 把这件事变成**参数空间搜索**:
种子化分层粗扫(`rayon` 并行)→ 以 top-k 为起点做多起点 `argmin` 局部精修(Nelder-Mead / PSO),
每次评估都用同一套指标(上升时间、超调、调节时间、稳态误差、IAE、电流)和同一套硬约束
(过速 / 长时间饱和 / 不收敛直接判罚,不参与权重折衷)。
```sh
# 0) 看有哪些超参数预设(只读;预设文件见 config/tune.toml)
cargo run -p chassis-tune -- presets
# 1) 仿真搜索(默认,不碰硬件;同 seed 结果逐位一致)
cargo run --release -p chassis-tune -- sweep --samples 512 --out-dir target/tune
# 1b) 用预设跑:超参数(区间 / 场景 / 权重 / 阈值 / 预算 / 安全包络)进版本管理
# 优先级:内置默认 < 预设文件 < 显式 CLI(逐字段覆盖)
cargo run --release -p chassis-tune -- sweep \
--preset config/tune.toml --preset-name bench_loaded
# 2) 只复算一组给定增益(CI / 回归用,按验收阈值给退出码:0 通过 / 1 未通过 / 2 参数错)
cargo run -p chassis-tune -- validate --gains 2,10,0,0
# 3) 台架复验(**轮子会转**:必须架空或整车固定、急停可及)
cargo run --release -p chassis-tune -- sweep \
--preset config/tune.toml --preset-name bench_noload \
--device /dev/ttyACM0 --esc-id 1 --i-know-the-wheel-spins
```
随仓库提供的预设(`config/tune.toml`):
| 预设 | 后端 | 用途 |
| --- | --- | --- |
| `sim_bench_model`(默认) | 仿真 | 台架量级模型全量搜索:评审 / CI / 代码回归基准 |
| `sim_ideal` | 仿真 | 理想模型秒级回归(结果**不可直接上车**) |
| `bench_noload` | 真机 | 空载台架,小样本局部搜索,前馈固定 0 |
| `bench_loaded` | 真机 | 带载(整车落地),前馈区间上调 |
| `field_updown` | 真机 | 实战验收:升 / 降 / 回零双向,阈值收紧 |
预设**不能**携带 `current_limit` / `direction` / `gear_ratio`(写了直接报错)——
安全与机械约束只来自 `chassis.toml` 或显式 CLI。
产物(`--out-dir`):`trials.csv`(全部候选与判定)、`best.toml`(可粘贴的增益片段)、
`best-trace.csv`、`report.md`、`summary.json`;台架模式另有 `hil-validation.csv`(同一组增益的重复性复验)。
加 `--features plot` 还会输出 `best.svg` 三联图。
整定工具与守护进程**共用同一份配置 schema**(`chassis-config`),因此可以直接拿实车配置当输入:
```sh
# 用 chassis.toml 里的限流 / 电调 ID / 方向 / 减速比(这些**不参与搜索**),
# 打印与现有增益的成本对比,并把结果写回一份新配置
cargo run --release -p chassis-tune -- sweep \
--config config/chassis.toml.example --motor front_left \
--write-config target/chassis.tuned.toml
```
要点:
- **仿真整定只保证在被控对象模型内最优**。模型里的摩擦 / 延迟是量级估计,且不含测量噪声,
因此仿真最优解可能偏激进;交付前必须用同一 `--scenario` 跑一次 `--backend bench` 复验。
- 最优解贴到参数空间边界时报告会明确提示——那是"约束在决定结果",应放宽 `--kp` / `--ki` 再搜。
- 台架搜索串行执行(只有一条总线),每次试验后强制 0 电流并静默 `--between-trials-ms`;
过速 / 过温 / 掉线 / 超时 / ctrl-c 任一命中即停机并收工。
- `current_limit`、`direction`、`gear_ratio` 属于安全与机械约束,**不参与搜索**。
- 换一组工况先加**预设**(`config/tune.toml`)而不是复制一长串命令行:
`chassis-tune presets` 查看、`--preset-name` 选用、CLI 只覆盖本次要变的项。
## 部署到目标板(armv7,实测:创龙 T153 / Ubuntu 22.04)
二进制为 musl 静态链接,不依赖板端 libc,无需交叉工具链:
```sh
just deploy # 编译 + 推送 + mock 试运行(just deploy root@169.254.63.4)
just deploy # 编译 + 推送 + mock 试运行(默认 root@192.168.2.2)
# 或手动:
cargo build --release -p chassisd --target armv7-unknown-linux-musleabihf
scp target/armv7-unknown-linux-musleabihf/release/chassisd root@169.254.63.4:/tmp/
scp target/armv7-unknown-linux-musleabihf/release/chassisd root@192.168.2.2:/tmp/
```
板端拉起 CAN(C620 标准 1Mbps;`restart-ms` 让 bus-off 后自动恢复):
板端 CAN 有两条互斥路径:
```sh
ip link set can0 up type can bitrate 1000000 restart-ms 100
```
- **SocketCAN**(板载原生 CAN 控制器,走 `can0`/`can1`):
`ip link set can0 up type can bitrate 1000000 restart-ms 100`,配 `--interface can0`。
- **slcan**(USB 适配器,如 CANable2 在 CDC ACM 下枚举为 `/dev/ttyACM0`):
用 [`dji-esc-slcan`](crates/dji-esc-slcan)(`chassisd` / [`chassis-bench`](crates/chassis-bench) 均可),无需 `ip link`。
实车运行:`/tmp/chassisd --config /tmp/chassis.toml --interface can0`。板上运行样例见
[`deploy/chassisd.service`](deploy/chassisd.service),配置样例见
[`config/chassis.toml.example`](config/chassis.toml.example)。
> 注意:电调未上电 / CAN 线未接时,控制器会因无 ACK 进入 bus-off(可用
> 注意:电调未上电 / CAN 线未接时,SocketCAN 侧会因无 ACK 进入 bus-off(可用
> `ip -d link show can0` 查看),chassisd 侧表现为四电机反馈离线、强制零电流——
> 这正是安全设计的预期行为。
## 文档
- [架构设计](docs/architecture.md)——分层、CAN 协议要点、单位与方向约定、测试策略
- [**底盘开发文档**](docs/chassis.md)——硬件接线、坐标与单位约定、控制与安全设计、配置参考、
**标定与上车流程**、自动整定与超参数预设、台架工具、故障排查(开发 / 调试 / 上车先看这份)
- [架构设计](docs/architecture.md)——分层、CAN 协议要点、单位与方向约定、被控对象模型、参数空间搜索、测试策略
- [整体架构规划](ARCHITECTURE.md)——全系统(含云台 / 发射 / IMU / 实时性)的 crate 划分与阶段计划