# 架构设计 ## 分层 ``` ┌─────────────────────────────────────────────┐ │ chassisd(守护进程) │ │ 配置 / CLI / 1kHz 控制循环 / 安全逻辑 / 日志 │ └──────┬───────────────────────────┬──────────┘ │ mecanum(麦轮正逆解) │ ▼ ▼ ┌────────────┐ ┌──────────────────┐ │ motor-core │◄─实现 trait──│ dji-esc │ │ Motor trait│ │ C620/C610 协议 │ │ MotorState │ │ EscBus 异步驱动 │ │ Pid │ │ TurnTracker 多圈 │ └────────────┘ └────────┬─────────┘ │ CanLink(tokio mpsc 通道对) ▼ ┌──────────────────────────┐ │ dji-esc-socketcan(Linux) │ │ socketcan ↔ CanLink 桥接 │ └──────────────────────────┘ ``` 核心解耦点:`CanLink` 是一对 tokio 通道(发送 / 接收 `CanFrame`)。`dji-esc` 的协议状态机 只面向通道工作,因此: - 测试中用内存通道 + 一阶电机模型(`dji_esc::sim`)构成闭环仿真,全平台可跑; - `dji-esc-socketcan` 把真实 SocketCAN 接口桥接到通道,只在实车上出现; - 未来更换总线介质(串口转 CAN、MCU 转发)只需新增一个桥接 crate。 ## DJI 电调 CAN 协议要点(C620 手册) | 项目 | 值 | | --- | --- | | 控制帧 ID | `0x200`(电调 1–4)、`0x1FF`(电调 5–8) | | 控制帧格式 | 8 字节 = 4 × i16 大端电流命令,按电调 ID 顺序 | | C620 电流标度 | ±16384 ↔ ±20 A | | C610 电流标度 | ±10000 ↔ ±10 A(M2006 组合,接硬件前需核对) | | 反馈帧 ID | `0x200 + 电调ID`(`0x201`–`0x208`) | | 反馈帧格式 | u16 角度(0..8191) + i16 转速rpm + i16 转矩电流 + i8 温度℃,均大端 | | 反馈频率 | 每电调 1kHz | C620 内部**只闭电流环**:转速 / 位置环由主控侧 PID 实现(`motor-core::Pid`, 挂在 `EscBus` 的 1kHz 发送节拍上)。GM3508 减速比 3591 / 187 ≈ 19.203。 ## 单位与方向约定 - 机器人坐标系:ISO 约定——x 前、y 左、ω 逆时针为正(见 `mecanum`)。 - `Motor` 接口呈现的是**物理量**(安装方向修正后): `EscConfig::direction = -1` 时,驱动层在写命令与读反馈时统一翻转符号, 上层永远以"轮子正转 = 底盘前进方向"的正向工作。 - `MotorState::rotor_speed_rpm` 为电机转子转速;轮端转速 = 转子转速 / 减速比。 - 电流一律以协议原始值(raw)为主,安培换算通过 `EscModel` 常量提供。 ## 安全设计 1. **上电门控**:底盘循环在收到任一电机首帧反馈前不下发速度命令。 2. **反馈离线**:任一电机反馈超时(默认 100ms)→ 该电机命令强制 0 电流并告警。 3. **命令超时**:上层 twist 命令超时(默认 200ms)→ 目标速度归零。 4. 所有超时可经 `chassis.toml` 配置。 ## 测试策略 | 层级 | 内容 | 平台 | | --- | --- | --- | | 单元测试 | 帧编解码字节级样例 / 饱和、多圈回绕、PID(阶跃、抗饱和、滤波)、运动学解析解 + 属性测试 | 全平台 | | 闭环仿真 | 内存通道 + 一阶电机模型:4 电机速度环收敛、群帧组装、离线安全、守护进程全链路 | 全平台 | | vcan 集成 | vcan0 双 socket 收发,真实内核 CAN 栈 | Linux(`#[ignore]`,CI 显式跑) | | 交叉检查 | `aarch64-unknown-linux-gnu` 全 workspace check | CI | ## 部署 `chassisd` 为单二进制守护进程:`--interface can0 --config /etc/chassisd/chassis.toml`。 systemd 样例见 `deploy/chassisd.service`。板端接口就绪依赖: USB 转 CAN(gs_usb / candleLight)或 SPI CAN HAT(MCP2515)驱动加载后的 `can0`。