refactor: 重构架构并整理仓库
This commit is contained in:
@@ -1,171 +1,61 @@
|
||||
# sentry-chassis
|
||||
|
||||
机甲大师哨兵机器人麦轮底盘固件:Linux ARM 主控 + 4 × GM3508(C620 电调),CAN 接入(SocketCAN 或串口 slcan),tokio 异步架构。
|
||||
RoboMaster 哨兵机器人麦轮底盘:Linux ARM 主控、4 × GM3508/C620、SocketCAN 或 SLCAN、tokio 异步运行时。
|
||||
|
||||
## 架构一览
|
||||
架构规范见 [`ARCHITECTURE.md`](ARCHITECTURE.md)。workspace 由 21 个职责单一 crate 组成,不使用 `rm-` 前缀,crate 内源码保持扁平。
|
||||
|
||||
| crate | 职责 | 平台 |
|
||||
| --- | --- | --- |
|
||||
| [`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`、`dji-esc-sim` 不做任何真实 I/O——CAN 端口被抽象为一对 tokio 通道
|
||||
(`CanLink`),因此协议、运动学、控制与整定逻辑可以在 macOS / CI 上完整测试;真实总线只出现在最外层
|
||||
(`dji-esc-socketcan` / `dji-esc-slcan`,以及组合它们的 `chassis-bench` / `chassisd`)。
|
||||
- `can` / `imu`:基础接口。
|
||||
- `motor-protocol` / `delta10-protocol`:纯协议编解码。
|
||||
- `socketcan` / `slcan` / `delta10`:硬件驱动。
|
||||
- `motor` / `esc-bus`:设备契约与安全总线运行时。
|
||||
- `pid` / `motor-control` / `mecanum`:纯控制算法。
|
||||
- `motor-model` / `experiment` / `sim-harness` / `tuning`:仿真与自动整定。
|
||||
- `chassis-config` / `bench` / `chassisd` / `spin` / `chassis-tune`:配置、台架和应用入口。
|
||||
|
||||
> 运输后端 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 循环天然满足)。
|
||||
`esc-bus` 不依赖控制算法。应用把 `motor-control::MotorPolicy` 作为
|
||||
`motor::EffortPolicy` 传入总线,从而保持依赖无环。
|
||||
|
||||
## 开发
|
||||
|
||||
需要 Rust stable(仓库通过 `rust-toolchain.toml` 锁定)。
|
||||
|
||||
```sh
|
||||
cargo test --workspace # 单测 + 闭环仿真测试(无需硬件)
|
||||
cargo run -p chassisd -- --mock # 无硬件全链路演示
|
||||
just tune-smoke # 自动整定冒烟(确定性,无需硬件,CI 同款)
|
||||
just lint # fmt + clippy(与 CI 同标准)
|
||||
cargo test --workspace --all-targets
|
||||
cargo run -p chassisd -- --mock
|
||||
cargo run -p spin -- chassis --device /dev/ttyACM0 --dry-run
|
||||
cargo run -p chassis-tune -- presets --preset config/tune.toml
|
||||
just lint
|
||||
just tune-smoke
|
||||
```
|
||||
|
||||
### Linux 虚拟 CAN(vcan0)集成测试
|
||||
底盘控制频率为 1 kHz。命令是 50 ms 租约,上层必须逐拍重发目标值。
|
||||
|
||||
## 台架
|
||||
|
||||
```sh
|
||||
just vcan-test # 或见 justfile 内的 modprobe / ip link 命令
|
||||
# 四轮 500 rpm 转子,slcan
|
||||
cargo run --release -p spin -- chassis --device /dev/ttyACM0 --rpm 500
|
||||
|
||||
# 单电机 SocketCAN 验证
|
||||
cargo run --release -p spin -- motor can0 1 1000 10
|
||||
```
|
||||
|
||||
## 台架:四轮 500 rpm 旋转测试(slcan)
|
||||
轮子必须架空或整车固定,急停可及。工具默认限流、限时并支持 ctrl-c 安全停机。
|
||||
|
||||
实车台架验证工具 `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
|
||||
--preset config/tune.toml --preset-name sim_bench_model \
|
||||
--samples 512 --out-dir target/tune
|
||||
```
|
||||
|
||||
随仓库提供的预设(`config/tune.toml`):
|
||||
仿真搜索不接触硬件。真机后端会转动轮子,必须显式传入
|
||||
`--i-know-the-wheel-spins`。详细接线、标定和排障见
|
||||
[`docs/chassis.md`](docs/chassis.md)。
|
||||
|
||||
| 预设 | 后端 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| `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 试运行(默认 root@192.168.2.2)
|
||||
# 或手动:
|
||||
cargo build --release -p chassisd --target armv7-unknown-linux-musleabihf
|
||||
scp target/armv7-unknown-linux-musleabihf/release/chassisd root@192.168.2.2:/tmp/
|
||||
```
|
||||
|
||||
板端 CAN 有两条互斥路径:
|
||||
|
||||
- **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 线未接时,SocketCAN 侧会因无 ACK 进入 bus-off(可用
|
||||
> `ip -d link show can0` 查看),chassisd 侧表现为四电机反馈离线、强制零电流——
|
||||
> 这正是安全设计的预期行为。
|
||||
|
||||
## 文档
|
||||
|
||||
- [**底盘开发文档**](docs/chassis.md)——硬件接线、坐标与单位约定、控制与安全设计、配置参考、
|
||||
**标定与上车流程**、自动整定与超参数预设、台架工具、故障排查(开发 / 调试 / 上车先看这份)
|
||||
- [架构设计](docs/architecture.md)——分层、CAN 协议要点、单位与方向约定、被控对象模型、参数空间搜索、测试策略
|
||||
- [整体架构规划](ARCHITECTURE.md)——全系统(含云台 / 发射 / IMU / 实时性)的 crate 划分与阶段计划
|
||||
仓库不使用 unsafe 或 libc FFI。生产调度策略由
|
||||
[`deploy/chassisd.service`](deploy/chassisd.service) 的 systemd 指令设置。
|
||||
std 程序不调用 `mlockall`。
|
||||
|
||||
Reference in New Issue
Block a user