Files
linux_sentry_chassis/.zcode/plans/plan-sess_5bb01b23-baf7-4632-be6e-f8a5bf9ab890.md
2026-09-22 20:05:16 +08:00

6.0 KiB
Raw Permalink Blame History

麦轮底盘仓库基础搭建方案(Linux ARM 主控 + 4×GM3508/C620)

已确认决策

  • 主控:Linux ARM 板,CAN 经 SocketCAN (can0) 接入(USB转CAN / CAN HAT)
  • 并发模型:tokio 异步
  • 架构:5 crate 分层,通用职能命名(不含仓库名 sentry-chassis,无 rm- 前缀;五个名字已在 crates.io 确认全部未占用)

关键协议事实(编码实现依据,来自 C620 官方手册调研)

  • 控制:ID 0x200 携带电调 1–4 的电流命令,0x1FF 携带 5–8;每电机 i16 大端,±16384 ↔ ±20A(C620)
  • 反馈:ID 0x200+电调ID(0x201–0x208),8 字节 = 机械角(0..8191, u16) + 转速 rpm(i16) + 转矩电流(i16) + 温度℃(i8)
  • C620 只闭电流环,速度环/位置环须在主控侧用 PID 实现;GM3508 减速比 3591/187 ≈ 19.2

仓库结构(Cargo workspace,虚拟清单,删除现有 src/main.rs)

sentry-chassis/
├── Cargo.toml                  # [workspace] resolver="3" + workspace.package/dependencies/lints
├── rust-toolchain.toml         # stable + rustfmt/clippy 组件
├── rustfmt.toml / clippy.toml
├── justfile                    # lint / test / vcan-test / run-mock
├── .github/workflows/ci.yml
├── README.md / LICENSE(MIT) / docs/architecture.md / deploy/chassisd.service
└── crates/
    ├── motor-core/        # 电机抽象层(纯逻辑,无 IO)
    ├── dji-esc/           # C620/C610 协议层(帧编解码 + 异步驱动,纯逻辑可全平台测)
    ├── dji-esc-socketcan/ # SocketCAN 后端(Linux only,非 Linux 编译为空壳)
    ├── mecanum/           # 麦轮正逆运动学(纯数学)
    └── chassisd/          # 守护进程二进制(组装一切,支持 --mock 无硬件运行)

各 crate 设计

1. motor-core — 抽象与控制(依赖:仅 tokio/thiserror)

  • MotorState:转子原始角、连续累计角(多圈)、转子 rpm、电流、温度、减速比换算的轮端速度
  • Motor trait:id() / state() / set_velocity(rpm) / set_current_raw(i16) / disable(),句柄可克隆、内部共享状态,供 chassisd 与测试用 mock 泛化
  • Pid(f32,显式 dt):输出限幅、积分抗饱和(clamping)、测量值微分 + 一阶低通滤波
  • VelocityController:速度环封装(由驱动层按反馈节拍调用)

2. dji-esc — DJI 电调协议(依赖 motor-core + tokio)

  • 自带最小 CanFrame{ id, data:[u8;8] } 与异步 CanPort trait(send/recv)——不依赖 socketcan,测试用 channel 实现
  • 纯函数编解码:encode_current_frame(0x200/0x1FF 分组、大端、饱和 ±16384)、decode_feedback(0x201–0x208),C620/C610 双型号量程
  • TurnTracker:0..8191 → 连续多圈角(正反向回绕处理)
  • EscBus<P: CanPort>:spawn 收发任务;rx 分发反馈到各 C620Motor 句柄(含方向翻转、速度 PID tick),tx 每 1kHz 汇装两帧控制报文;EscConfig{ esc_id, 型号, 减速比, 方向, 电流限幅 }
  • 反馈超时检测(离线 → 电流清零)

3. dji-esc-socketcan — SocketCAN 后端(依赖 dji-esc + socketcan v4 "tokio" feature)

  • SocketCanPort::open("can0") 实现 CanPort;socketcan Frame ↔ CanFrame 转换
  • crate 主体 #[cfg(target_os="linux")],macOS 上编译为空壳 → 全 workspace 可在 mac 开发机直接 build/test

4. mecanum — 麦轮运动学(纯数学,零依赖)

  • Mecanum{ lx, ly, wheel_radius },ISO 约定(x前 y左 ω逆正,45°辊子)
  • inverse(Twist) -> [4] 轮角速度(FL/FR/RL/RR)、forward([4]) -> Twist(伪逆)、rpm↔rad/s 换算

5. chassisd — 守护进程(依赖以上全部 + clap/serde/toml/tracing)

  • CLI:--interface can0 --config chassis.toml --mock
  • --mock:进程内 CanPort + 一阶电机模型,无硬件/macOS 可跑通全链路
  • 1kHz 控制循环:Twist → mecanum 逆解 → 4 路 set_velocity;TwistSource trait(当前 Zero/Mock 实现,遥控器后续接入)
  • 安全:命令超时清零、反馈离线清零、上电等首帧反馈后才使能;tracing 日志、ctrl-c 优雅退出、systemd 部署样例

底层库配置(workspace.dependencies 统一管理)

tokio(rt-multi-thread,macros,sync,time) / socketcan v4+tokio(仅 Linux target 依赖;若 4.0 有问题回退 3.6.2)/ thiserror / tracing + tracing-subscriber / serde+toml(配置) / clap(bin) / proptest+approx(dev)。[workspace.lints]:clippy pedantic 子集 + 库 crate 禁 unwrap/expect。

充分测试策略

  1. 单元(全平台):编解码官方字节级样例与边界值(±16384 饱和、负值、全部 ID 路由)、多圈回绕序列、PID(阶跃/限幅/抗饱和恢复/微分滤波)、运动学(纯平移/纯旋转/对角线/零点 + proptest 往返一致性)、配置解析
  2. 闭环仿真(全平台):mock CanPort + 一阶电机模型(电流→rpm 增益与限速),4 电机速度环收敛、群帧组装、离线安全、--mock 守护进程全链路(tokio::time::pause 控时)
  3. vcan 集成(Linux 专属,#[ignore] + CI 显式跑):vcan0 上双 socket 收发,真实内核 CAN 栈回环验证
  4. CI(GitHub Actions):fmt --check / clippy -D warnings / test / doc / vcan job(modprobe vcan)/ aarch64-unknown-linux-gnu 交叉 check(目标板架构)/ llvm-cov 覆盖率

实施步骤

  1. 工作区脚手架:根 Cargo.toml(虚拟清单)、toolchain/lint/fmt 配置、删 src/main.rs、README、docs、justfile、CI、LICENSE
  2. motor-core:类型 + Motor trait + PID + 单测
  3. dji-esc:CanFrame/CanPort、编解码、TurnTracker、EscBus 异步驱动、闭环仿真测试
  4. dji-esc-socketcan:CanPort 实现 + vcan 集成测试
  5. mecanum:正逆解 + proptest
  6. chassisd:配置/CLI/mock 模式/控制循环/安全逻辑 + 测试、deploy 样例
  7. 本机验证:cargo fmt / clippy / test 全绿(macOS 上 Linux 专属测试自动跳过)