跳转到内容

Chassis::Steering4

cpkg add Chassis::Steering4

文档

Steering4

Steering4 是四舵轮底盘的 Motion 实现。它和 Mecanum4 / Omni4 的差别不在于对外接口,而在于“底盘能否立即进入可控状态”这件事上存在明显的启动阶段。

主 README 只要求上层理解 IChassisMotion::isReady() 的意义;如果具体使用 Steering4,则需要额外理解这里的校准和轮组行为。

适用场景

  • 四个轮组都同时具备驱动轴和舵向轴。
  • 上层希望仍然把整个底盘当作统一 Motion 使用,而不是自己分别控制四个舵轮。
  • 启动时可能需要先完成舵向零点校准,再允许控制器接管。

对外仍然暴露的统一语义

Steering4 仍然遵守 IChassisMotion 语义:

  • enable() / disable():使能或失能四个轮组。
  • forwardGetVelocity():返回当前估算到的车体速度。
  • isReady():在未启用校准时恒为 true;启用校准时只有全部轮组校准完成后才为 true

这也是为什么上层应依赖 isReady(),而不是假设“底盘一旦 enable 就一定可控”。

配置结构

Steering4::Config 分成两部分:

  • 底盘公共几何参数:radiusdistance_xdistance_y
  • 每个轮组自己的 Wheel 配置:SteeringWheel::ConfigSteeringWheel::CalibrationConfig

几何参数单位如下:

  • radius:驱动轮半径,单位 mm
  • distance_x:前后轮距,单位 mm
  • distance_y:左右轮距,单位 mm

每个轮组都包含两类底层对象:

  • drive_motor:轮向速度控制器
  • steer_motor:舵向位置控制器

如果启用校准,还要提供:

  • calib_cfg.steer_motor:校准阶段用于慢速寻零的舵向速度控制器
  • calib_cfg.photogate:光电门 GPIO
  • calib_cfg.photogate_active_state:光电门有效电平

如果使用光电门校准,photogate 对应的 EXTI 需要在 CubeMX 中配置为双边沿触发。当前实现默认“进入光电门区域”和“离开光电门区域”这两个边缘都会产生回调,否则下面的两次触发状态机假设就不成立。

启动与校准流程

推荐接入顺序:

  1. 构造 Steering4
  2. 调用 enable()
  3. 如果 enable_calibration == true,调用 startCalibration()
  4. 周期调用 update()
  5. 等待 isReady() 返回 true
  6. 再交给 Controller 正常发速度或位姿目标

当前校准逻辑的实际行为:

  • 若一开始光电门已触发,轮组直接进入低速精捕阶段。
  • 若一开始未触发,轮组先高速寻门,再在第一次触发后降速精捕。
  • 第二次触发时,校准电机停下,舵向电机角度被复位到零点,随后重新使能舵向位置环和轮向速度环。

之所以不是“命中一次光电门就立刻完成校准”,是因为光电门通常对应一个有宽度的遮挡区,轮组转过该区域时会先后遇到两个边缘。当前实现用第一次触发说明“已经找到门”,随后降速继续转动,并把第二次触发固定为真正记零的边缘。这样可以避免零点有时取在进入边缘、有时取在离开边缘,减少重复上电后的零点漂移。

因此,如果使用 STM32 + CubeMX 接线方式,光电门 EXTI 不应只配上升沿或只配下降沿,而应配置为 Rising/Falling 双边沿触发。否则当前状态机拿不到完整的两个边缘事件,可能导致校准流程停在中间状态,或者零点边缘定义与预期不一致。

Steering4::applyVelocity()!isReady() 时会直接返回,不会下发速度。这是有意设计,不是“忘记控制”。它的目的是防止校准期间被上层误发运动指令。

轮组速度与舵向优化

每个轮组的目标由一个平面速度向量计算得到:

  • 目标角度 angle:轮子应该指向的行进方向,单位 deg
  • 目标速度 speed:轮向速度,单位 rpm

为了减少舵向电机无意义的大角度旋转,SteeringWheel::toBestVelocity() 会自动选择更短的等效解:

  • 如果把舵向多转接近 180 度更慢,就直接改为反向驱动轮向速度
  • 如果跨整圈更近,就会自动给目标角度加减 360

这意味着上层不需要自己实现“翻轮”或“最短转角”逻辑,只要按普通底盘速度输入即可。

还有一个故意保守的处理:

  • 当某个轮组的目标线速度接近零时,当前实现会保留该轮组现有舵向角,只把轮向速度设为零,避免静止时来回摆头。

轮序和几何方向

轮序在 Steering4::WheelType 中固定为:

  • FrontRight
  • FrontLeft
  • RearLeft
  • RearRight

坐标方向与主 README 一致:

  • x 指向车体前方
  • y 指向车体左侧
  • yaw / wz 逆时针为正

底层配置和线速度分解都基于这套方向约定,接线或建模时不要自行换轴而不改配置。

周期调用建议

  • update():放在运动控制快环中。它不仅负责驱动各轮控制器更新,也负责在非校准阶段刷新底盘反馈速度。
  • startCalibration():只应在 enable() 成功后调用,且当前实现只打算执行一次启动校准。

如果上层已经有别的绝对零点建立方式,也可以把 enable_calibration 设为 false,让 Steering4 退化成“始终 ready 的四舵轮运动学层”。

一个常见例子是:舵向电机本身采用带双编码器的云台电机,掉电后能够依赖内部绝对参考完成零点恢复。此时本仓库不必再额外接入光电门做启动校准,只需要保证 steer_offset 与这套硬件恢复出来的绝对零点定义一致即可。

与主 README 的边界

主 README 负责告诉你“为什么 Motion 允许 not-ready”。本文件负责告诉你 Steering4 具体在什么情况下 not-ready、什么时候会忽略速度命令、以及校准阶段到底在做什么。