refactor: enforce layered crates and Rust audit gates

This commit is contained in:
Horldsence
2026-09-24 13:00:03 +08:00
parent af151525d1
commit 8a582fc102
67 changed files with 3918 additions and 581 deletions
+21 -7
View File
@@ -280,7 +280,7 @@ effort_raw = clamp( PID(target_rpm, measured_rpm, dt) + feedforward × target_rp
| 一起动就飞 | 前馈过大 or 限流远大于实际所需 | ff → 0、限流贴近实际 |
| 稳态有静差 | 摩擦未被积分吃掉 | 检查 `ki` 是否被抗饱和长期冻结 |
### 7.4 被控对象模型(`sim-harness::motor_model`)
### 7.4 被控对象模型(`motor-model::MotorPlant`)
逐拍离散(`dt` 秒,电调坐标系:正电流 → 正转速):
@@ -299,7 +299,7 @@ effort_raw = clamp( PID(target_rpm, measured_rpm, dt) + feedforward × target_rp
## 8. 配置参考(chassis.toml)
样例:[`config/chassis.toml.example`](../config/chassis.toml.example)。
schema 由 [`chassis-config`](../crates/chassis-config) 定义,**守护进程与整定工具共用同一份**——
schema 由 [`chassis-config`](../crates/config/chassis) 定义,**守护进程与整定工具共用同一份**——
这样"整定工具用的限流"和"守护进程用的限流"不可能悄悄不一致。
### 8.1 顶层
@@ -308,11 +308,23 @@ schema 由 [`chassis-config`](../crates/chassis-config) 定义,**守护进程
| --- | --- |
| `[can] interface` | 底盘总线 SocketCAN 接口名(如 `can0`) |
| `[can.function] interface` | 预留的功能总线(云台 / 拨弹),必须与底盘总线**不同名** |
| `[remote]` | 可选 DR16/D-BUS 遥控输入;缺省时保持静止 |
| `[chassis]` | 控制循环与安全超时、速度上限 |
| `[mecanum]` | `half_length` / `half_width` / `wheel_radius`(米) |
| `[[motor]]` × 4 | 顺序固定 FL / FR / RL / RR |
### 8.2 `[chassis]`(缺省值)
### 8.2 `[remote]`(可选)
| 键 | 默认 | 含义 |
| --- | --- | --- |
| `kind` | 必填 | 当前支持 `dr16` |
| `device` | `/dev/ttyS2` | D-BUS UART 设备 |
| `timeout_ms` | 100 | 合法帧断流后立即失能 |
| `deadband` | 0.05 | 摇杆满量程死区,之后使用平方曲线 |
| `ramp_ms` | 500 | 零到满量程逐轴斜坡;失能/断流立即归零 |
| `invert_vx/vy/omega` | false | 实车方向校正 |
### 8.3 `[chassis]`(缺省值)
| 键 | 默认 | 含义 |
| --- | --- | --- |
@@ -322,7 +334,7 @@ schema 由 [`chassis-config`](../crates/chassis-config) 定义,**守护进程
| `motor_command_timeout_ms` | 50 | 驱动层命令租约(必须 ≥ `control_period_ms`) |
| `max_vx` / `max_vy` / `max_omega` | 3.0 / 3.0 / 6.0 | 速度限幅(m/s、m/s、rad/s) |
### 8.3 `[[motor]]`
### 8.4 `[[motor]]`
| 键 | 含义 |
| --- | --- |
@@ -334,12 +346,14 @@ schema 由 [`chassis-config`](../crates/chassis-config) 定义,**守护进程
| `current_limit` | effort 限幅(raw),同时是 PID 钳位点 |
| `kp` / `ki` / `kd` / `feedforward` | 速度环增益(整定的产物写回这里) |
### 8.4 校验规则(`Config::validate`)
### 8.5 校验规则(`Config::validate`)
- 电机数必须**恰好 4**;麦轮几何必须为正;四个超时必须 > 0;
`motor_command_timeout_ms ≥ control_period_ms`;速度上限 > 0;`gear_ratio > 0`;
- 底盘总线**只允许一种协议族**(四轮不能混用 C620 / C610);
- 功能总线接口名不得与底盘总线相同(双 CAN 物理隔离);
- `[remote]` 若启用:设备名非空,`timeout_ms` / `ramp_ms` > 0,`deadband ∈ [0, 0.5)`,
且遥控断流超时不得晚于底盘指令超时;
- `deny_unknown_fields`:**拼错的键直接报错**,不会被静默忽略。
---
@@ -441,7 +455,7 @@ chassis-tune sweep --preset config/tune.toml --samples 128 # CLI 覆盖预
| `field_updown` | bench | **up-down** 1200 rpm | 实战验收:升 / 降 / 回零双向,阈值收紧到 12% / 3% |
**预设 schema**(`version = 1`,未知键报错,见
[`crates/tuning/src/lib.rs`](../crates/tuning/src/lib.rs)):
[`crates/tooling/tuning/src/lib.rs`](../crates/tooling/tuning/src/lib.rs)):
```toml
version = 1
@@ -588,7 +602,7 @@ cargo run --release -p spin -- motor -- --interface can0 --dry-run
| 整定 | 指标(合成轨迹解析解)、参数空间(界内 / 确定性 / 对数分布 / 分层覆盖)、成本(硬约束罚值)、搜索(同 seed 逐位复现、优于手调基线)、报告(CSV/TOML/JSON 往返) | 全平台(CI 跑 `just tune-smoke`) |
| **预设** | schema 往返、逐字段覆盖、优先级(CLI > 预设 > 内置)、未知键 / 越界 / 缺失报错、**`config/tune.toml` 全部预设可解算**、命名与后端一致、安全参数不可注入 | 全平台 |
| vcan 集成 | vcan0 双 socket 收发,真实内核 CAN 栈 | Linux(`#[ignore]`,CI 显式跑) |
| 实车台架 | `spin chassis` 四轮定速:链路/反馈、方向、转速稳态、过速保护、安全停机;`chassis-tune --backend bench` 逐次试验 + 重复性复验 | armv7 + slcan/SocketCAN(人工) |
| 实车台架 | `spin chassis` 四轮定速:链路/反馈、方向、转速稳态、过速保护、安全停机;`spin rc` 只读监视 DR16;`chassis-tune --backend bench` 逐次试验 + 重复性复验 | armv7 + slcan/SocketCAN(人工) |
| 交叉检查 | `aarch64-unknown-linux-gnu` 全 workspace check;armv7 静态构建 `chassisd` | CI |
### 13.2 每个阶段完成后的门禁(`just lint` + 以下)
+50
View File
@@ -0,0 +1,50 @@
# 依赖分层与 Trait 边界
`config/dependency-policy.toml` 是依赖规则的唯一机器可读来源。crate 名称保持不变,manifest 按 `crates/<layer>/<domain>` 组织,并在 `[package.metadata.sentry-chassis]` 中声明 `layer`。
## 单向分层
```text
contract can/imu
protocol imu/motor/remote
transport can/serial
device imu/motor/esc/remote
control algorithm/chassis/motor
experiment trace
model motor
simulation motor
tooling tuning
config chassis
application bench/daemon/tools/tuning
verification integration
```
依赖只能从高层指向低层;正常依赖和 dev 依赖都必须如此。跨层集成测试集中在 `verification/integration`,不允许测试回边渗入低层 crate。
## Trait 组织
- `protocol/motor`:`MotorProtocol`、`EffortScale`、`FeedbackFields`,只处理线上的命令、反馈、帧 ID 和量程。
- `device/motor`:`MotorSpec`、`MotorFeedback`、`EffortDrive`、`VelocityDrive`、`PositionDrive`、`Disable`,只处理机械型号和设备能力。
- `device/esc`:`EscConfig<S>`、`EscMotor<S>`、`EscBus<S>` 通过 `MotorSpec::Protocol` 组合协议能力;电流路径要求 `CurrentEscDrive`,GM6020 使用独立的 `VoltageEscDrive` 路径。
- `model/motor`:`MotorPlant`、`DcMotorPlant<S>`,只处理动态模型和反馈量化。
`Gm3508`、`M2006`、`Gm6020` 是 marker type;型号事实、协议族和控制能力由关联类型组合,不在 bus 内用运行时 `match` 判断。
## 外部库边界
外部依赖必须从根 `workspace.dependencies` 继承,并在 policy 的 `external_roles` 中声明用途。异步/传输库只进入 transport/device;配置和 CLI 库只进入 config/application;搜索、并行、绘图库只进入 tuning/application;`approx`、`proptest` 只允许作为测试依赖。
## 审查脚本
`scripts/audit-rules.rs` 是单文件 Rust `cargo-script`。脚本通过内嵌 manifest 声明
`serde`、`serde_json`、`toml` 和 `regex`,不需要额外 Python 工具链。运行时使用
Nightly 的 `-Zscript`;workspace 本身仍由 `rust-toolchain.toml` 固定 Stable。
```sh
cargo +nightly -Zscript scripts/audit-rules.rs
cargo +nightly -Zscript scripts/audit-rules.rs --self-test
```
## 变更流程
新增 crate、内部边或外部库时,必须同步更新 `config/dependency-policy.toml`、crate 的 layer 声明、架构文档和 `Cargo.lock`。运行 `just audit`,提交时由 `.githooks/pre-commit` 执行同一规则。
+70
View File
@@ -0,0 +1,70 @@
# DT7 + DR16 遥控底盘接入
这里的 `dt16` 目录沿用现有资料目录名;硬件是 **DT7 遥控器 + DR16 接收机**。接收机通过
D-BUS 输出 18 字节帧,软件中的协议名称统一为 `DR16`。
## 协议与接线
- DR16 `DBUS` 接 T153 原生 UART RX,默认设备 `/dev/ttyS2`。
- UART 参数固定为 `100000 baud, 8 data bits, even parity, 1 stop bit`,无流控。
- 接收机 `VCC/GND/DBUS` 使用 3-Pin 线;确认 T153 UART RX 电平与 DBUS 信号兼容后再上电。
- 本实现的字段布局参考 DT7/DR16 手册和 `RoboMaster/RoboRTS-Firmware` 的 DR16 解码,
Rust 代码为独立重写,不复制参考仓库源码。
## 摇杆与安全语义
| 输入 | 通道 | 底盘动作 |
| --- | --- | --- |
| 左摇杆上下 | `T/ch3` | 前后平移,上为前进 |
| 左摇杆左右 | `R/ch4` | 旋转,右为顺时针(负 omega) |
| 右摇杆左右 | `A/ch1` | 左右平移,右为右移(负 vy) |
| 右摇杆上下 | `E/ch2` | 本次不绑定动作 |
| S1 上档 | wire value `1` | 允许运动 |
| S1 中/下档 | wire value `3`/`2` | 立即停车 |
摇杆满量程为协议中心值 ±660。5% 死区外使用平方曲线,满杆对应
`chassis.max_vx/max_vy/max_omega`。速度从零到满量程使用 `ramp_ms = 500` 的逐轴斜坡;
S1 离开上档、合法帧断流超过 `timeout_ms = 100`、串口关闭时立即归零,不走斜坡。
## 配置
在 `/etc/chassisd/chassis.toml` 增加:
```toml
[remote]
kind = "dr16"
device = "/dev/ttyS2"
timeout_ms = 100
deadband = 0.05
ramp_ms = 500
invert_vx = false
invert_vy = false
invert_omega = false
```
如果某个轴的实车方向相反,只翻转对应的 `invert_*`。`chassisd --rc-device /dev/ttyS2`
可以覆盖配置中的设备节点;没有 `[remote]` 段时守护进程保持安全静止。
## 只读监视
先不要让车轮着地,使用只读命令观察帧和方向:
```sh
cargo run --release -p spin -- rc --device /dev/ttyS2
```
输出包含帧龄、A/E/T/R 原始值、S1/S2 位置和显示用 `vx/vy/omega`(默认满量程 3.0/3.0/6.0)。它不打开 CAN,也不驱动电机。
## 实车验收
1. S1 置中档或下档,执行 `spin rc --device /dev/ttyS2`,确认帧龄约 14 ms、四个通道随摇杆变化、S1 上档 wire value 为 `1`。
2. 架空四轮,执行 `chassisd --dry-run --config /etc/chassisd/chassis.toml`,确认 UART 与四个电调反馈正常。
3. S1 上档后低速验证:左杆上/下 = 前/后,右杆左/右 = 左/右平移,左杆左/右 = 逆/顺时针。
4. 运动中把 S1 拨离上档,必须立即停车。
5. 运动中关闭遥控器或拔掉 DBUS,必须在 100 ms 内停车。
6. 若方向相反,修改对应 `invert_*` 后重复步骤 3,再落地低速复验。
## 参考资料
- `DT7&DR16_RC_System_User_Manual_v2.00_cn.pdf`
- [RoboMaster/RoboRTS-Firmware](https://github.com/RoboMaster/RoboRTS-Firmware)