Skip to content

Architecture

konodoki edited this page Jul 26, 2026 · 21 revisions

架构总览

当前架构把平台适配、控制框架、动作实现和模型资产分层。BxiExample 只处理 ROS 和硬件边界;RobotControlFramework 拥有 Mod、状态、Transition、Context 和状态机。状态侧的部署单元是 Mod,不再依赖中央状态类文件。

总数据流

手柄 / 键盘 / CRSF / 自定义设备
  -> InputDeviceManager
  -> InputDriver
  -> sources -> controls -> outputs
  -> communication/msg/MotionCommands
  -> BxiExample 的 ROS subscription
  -> RobotControlFramework 内的 RemoteEventAdapter 生成 events
  -> BxiExample 采集 RobotObservation 并取出 events
  -> RobotControlFramework.update(observation, events, dt)
       -> RobotStateMachine
       -> Transition / RobotControlState
       -> MotorFrame
  -> BxiExample 将 MotorFrame 转换为 ActuatorCmds
  -> 机器人硬件

这条边界的核心约定很简单:平台每周期给框架一份完整观测和事件,框架返回最终电机帧。框架不创建硬件消息,不发布电机话题,也不负责机器人 reset。因此更换消息类型、总线或硬件平台时,状态图和 Mod 不需要跟着改。

当 route 要求切换状态时,RobotStateMachine 会在源状态和目标状态之间执行 Transition。它负责切换期间的电机帧,避免两边 qpos/kp/kd 不连续时直接换帧产生突跳;完成后目标 RobotControlState 才接管正常更新。

配置和代码的加载流:

elf3_state_machine.yaml(系统配置)
  + 内置 mods/
  + mod_paths 中的客户 Mod
  -> 发现 mod.yaml
  -> 校验依赖并排序
  -> 加载 entrypoint
  -> 注册惰性资源、状态工厂和 Python 节点
  -> 合成 states/events/routes/actions/nodes/profiles
  -> 构建 RobotStateMachine
  -> 按 Mod/State 生命周期管理节点

文件分层

src/remote_controller/
  config/xbox_default.yaml
  include/remote_controller/
  src/

src/bxi_example_py_elf3/
  config/elf3_state_machine.yaml       # 系统级配置
  mods/
    com.bxi.basic_actions/
      mod.yaml                         # 状态图贡献
      plugin.py                        # 工厂和资源注册
      *_state.py                       # 状态实现
      assets/                          # 该 Mod 私有资产
    com.bxi.back_flip/
    com.bxi.forward_flip/
    com.bxi.ballet/
  bxi_example_py_elf3/
    bxi_example_demo.py               # ROS/硬件适配层
    mod_api/                          # 面向 Mod 作者的稳定公共 API
      context.py
      frame.py
      state.py
      states.py
      resource.py
      mod.py
      transition.py
      geometry.py
    _runtime/
      controller.py                  # 单一控制框架入口
      ...                            # 加载、合成、状态机和注册表
    inference/
    transitions/                       # 内置过渡类型

运行时对象

对象 责任
RobotControlFramework 启动和关闭整个控制运行时,接收 RobotObservation/events 并返回 MotorFrame
ModRuntime 保存合成配置、状态工厂、资源管理器、已加载 Mod 和动态模块
ResourceManager 注册、惰性创建、缓存和关闭资源
StateBuildContext 为状态工厂提供名称、稳定 state id 和强类型参数读取
RobotStateMachine 处理事件、延迟、过渡、状态生命周期和图导出
RemoteEventAdapter MotionCommands 槽位变化转成 Mod 事件

Mod 只能依赖 mod_apiBxiExample 通过一个 RobotControlFramework 使用 _runtime,不再自己组装 loader、状态和状态机。项目不再提供旧 utils 扩展入口,错误的依赖会在开发阶段直接暴露。

命名空间

Mod 清单中的本地名称会自动限定:

Mod id:       com.example.wave
state:        wave
event:        activate
resource:     com.example.wave/policy

运行时状态:  com.example.wave/wave
运行时事件:  com.example.wave/activate

同一 Mod 内的 from: waveto: waveevent: activate 会自动限定。跨 Mod 引用必须写完整名称,并通过 requires 声明依赖。

修改边界

新增动作:

  • 新建或扩展一个 Mod。
  • mod.yaml 声明状态、事件、路由和 action。
  • 简单状态用 factory: module:Class;需要资源和扩展注册时再由 plugin.py 返回工厂。
  • 模型放进该 Mod 的 assets/ 并注册资源。
  • 在遥控器 YAML 中输出清单所使用的 btn_N=value

新增过渡:

  • 框架通用过渡放入包内 transitions/
  • 业务专用过渡放在对应 Mod 中,并由 ModDefinition.transition_plugins 显式注册。
  • profile 可放系统 YAML;Mod 私有 profile 放 mod.yaml,会自动加命名空间。

新增输入协议:

  • 先判断是否仅靠遥控器 YAML 能完成。
  • 必须读新设备时再实现 InputDriverBase 和工厂。
  • Driver 只产生 raw signal,不直接写状态名。

公开发布:

  • 在要整体移除的 Mod 清单中设置 visibility: protected
  • tools/sanitize_release.py 删除整个目录并验证保留 Mod 的依赖闭包。

下一步

Clone this wiki locally