sentry-chassis
机甲大师哨兵机器人麦轮底盘固件:Linux ARM 主控 + 4 × GM3508(C620 电调),CAN 接入(SocketCAN 或串口 slcan),tokio 异步架构。
架构一览
| crate | 职责 | 平台 |
|---|---|---|
motor-core |
电机抽象:能力 trait、MotorState、PID / 速度环 / 位置环 |
纯逻辑,全平台 |
can-link |
CAN 传输抽象:CanFrame + CanLink 通道对(无协议知识) |
纯逻辑,全平台 |
dji-esc |
C620/C610 CAN 协议:帧编解码、多圈累计、EscBus 异步驱动 |
纯逻辑,全平台 |
dji-esc-sim |
被控对象仿真:摩擦 / 延迟 / 负载模型、场景与离线评估 harness、异步假电调 | 纯逻辑,全平台 |
dji-esc-socketcan |
SocketCAN 后端:真实 CAN 接口 ↔ 内存通道桥接 | Linux |
dji-esc-slcan |
slcan 串口后端:CANable 等 USB 适配器 ↔ 内存通道桥接 | 全平台 |
mecanum |
麦轮正 / 逆运动学(纯数学) | 全平台 |
chassis-config |
chassis.toml schema:解析、校验、写回(守护进程与整定工具共用) |
全平台 |
chassis-bench |
台架:激励场景、安全包络、真机试验采样 + chassis-spin / socketcan-spin |
全平台(SocketCAN 工具需 Linux) |
chassis-tune |
速度环 PID 自动整定:参数空间搜索 + 指标 / 成本 + 报告(仿真 / 真机)+ 版本化超参数预设 | 全平台 |
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)。
运输后端 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 循环天然满足)。
开发
需要 Rust stable(仓库通过 rust-toolchain.toml 锁定)。
cargo test --workspace # 单测 + 闭环仿真测试(无需硬件)
cargo run -p chassisd -- --mock # 无硬件全链路演示
just tune-smoke # 自动整定冒烟(确定性,无需硬件,CI 同款)
just lint # fmt + clippy(与 CI 同标准)
Linux 虚拟 CAN(vcan0)集成测试
just vcan-test # 或见 justfile 内的 modprobe / ip link 命令
台架:四轮 500 rpm 旋转测试(slcan)
实车台架验证工具 chassis-spin:四轮同时以固定转子转速旋转(默认 500 rpm,
轮端 = 转子 ÷ 减速比 ≈ 26 rpm),带缓升、过速保护、上电门控与安全停机。
# 本机直接跑(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、电流)和同一套硬约束
(过速 / 长时间饱和 / 不收敛直接判罚,不参与权重折衷)。
# 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),因此可以直接拿实车配置当输入:
# 用 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,无需交叉工具链:
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(chassisd/chassis-bench均可),无需ip link。
实车运行:/tmp/chassisd --config /tmp/chassis.toml --interface can0。板上运行样例见
deploy/chassisd.service,配置样例见
config/chassis.toml.example。
注意:电调未上电 / CAN 线未接时,SocketCAN 侧会因无 ACK 进入 bus-off(可用
ip -d link show can0查看),chassisd 侧表现为四电机反馈离线、强制零电流—— 这正是安全设计的预期行为。