Skip to content

Framework Internals

konodoki edited this page Jul 28, 2026 · 19 revisions

框架底层运行原理

本页按启动和每帧执行顺序描述当前实现。

1. remote_controller

读取 YAML
  -> 校验 sources/controls/outputs
  -> 注册并创建候选 InputDriver
  -> InputDeviceManager 周期探测
  -> 选择唯一活动设备
  -> InputMapper 计算 controls
  -> MotionCommandsAdapter 写消息
  -> 发布 motion_commands

设备选择考虑 priorityready_timeout_msloss_timeout_mscooldown_ms 以及全局扫描/稳定时间。Driver 只生产 raw signal,业务组合留在 YAML。

edge 只在条件由 false 变 true 时触发;level 持续反映条件;analog 每帧写连续值。

2. 平台适配层与框架启动

BxiExample
  -> 读取 ROS 参数和系统状态机 YAML
  -> 创建 ROS subscription / publisher / service client
  -> 实现 ControlPlatformAdapter 的三个平台方法
  -> 创建 RobotControlRuntime

RobotControlRuntime
  -> 创建 RobotControlFramework
       -> load_mod_runtime()
       -> build_robot_states()
       -> 绑定状态并创建 RobotStateMachine
       -> 创建 RemoteEventAdapter
  -> 创建 ControlScheduler 和低频维护线程

BxiExample 不再持有 ModRuntime、状态实例或状态机,也不再代理 set_motor_target()request_state() 和模型预热等框架能力。这些由 RobotControlFramework 作为 RobotControlContext 的实现统一提供。BxiExample 只实现启动检查、观测快照和电机帧发送,具体迁移方法见机器人平台适配指南

RobotControlRuntime 通过 ControlPlatformAdapter 隔离传感器和电机总线,同时保留一条直接的每周期调用路径。控制时钟由独立的 ControlScheduler 管理,不由 ROS Timer 驱动。

3. Mod 动态模块

每个清单先校验 schema、id、版本和 API。依赖拓扑排序后,入口模块或 factory: module:Class 引用以由 Mod id 确定的私有包名导入,使相对 import 可用并隔离不同 Mod 的模块命名空间。

加载失败会关闭新资源、移除动态模块、恢复过渡插件注册,并撤销 Python exports 和对应的 sys.path 修改。

4. 配置合成

系统 YAML 先复制为 base config,mod_paths 不进入最终状态机配置。随后按依赖顺序合成:

  • states
  • remote_events
  • speed_profiles
  • Mod transition_profiles
  • routes/actions 生成的 states.*.transitions.on_event
  • nodes 生成的 Python 节点规格

所有本地名称在这一阶段限定为 mod-id/local-name。输入冲突、未使用事件、未知目标、priority/index、profile 和 initial state 都在返回运行时前校验。

5. 状态构建

构建器不再扫描类。它遍历合成状态:

  1. 使用显式 id,或对完整名称计算 CRC32 int31。
  2. 创建 StateBuildContext
  3. 调用显式 Mod factory,或由类的 dataclass Params 生成约定 factory。
  4. 拒绝未知参数。
  5. 设置 speed profile 和 manifest。

6. ResourceManager

注册时只保存 key、owner、Mod 根和 factory。ResourceHandle.get() 第一次调用才构造实例;context.asset() 负责限定资产必须位于本 Mod 的 assets/。关闭运行时会逆序调用实例的 close()

7. 每个控制周期

RobotControlRuntime 到达绝对时间释放点
  -> 调用 BxiExample.snapshot_control_inputs()
       -> 在同一把观测锁内更新长期复用的 JointStateBuffer 和传感器缓冲
       -> 返回稳定 RobotObservation 并取出已排队 events
  -> framework.update(observation, events, dt)
       -> 更新 RobotControlContext 的当前周期快照
       -> state_machine.update(dt, events)
       -> Transition 或当前状态生成最终 MotorFrame
  -> 调用 BxiExample.publish_motor_frame()
       -> 把 MotorFrame 写入 ActuatorCmds 并发布
  -> BxiExample 按频率发布 state_machine_info

RobotObservation.joints 是带 JointLayoutJointStateView。平台适配层长期持有观测和 数组,每周期只原地更新;它们不能引用生命周期不确定的 ROS 消息内存。Framework 首次看到 输入布局时编译名称映射,之后只执行数组映射。框架返回 MotorFrame | None,其中 MotorFrame.layout 明确输出关节语义;有输出时由平台适配层决定如何发送,没有输出时不发 新的电机命令。

8. 状态切换

Transition 是状态机在源状态和目标状态之间创建的一次切换 Session。它在目标状态正式进入前暂时负责每周期的电机输出,用来处理两边 qpos/kp/kd 不连续时的保持、增益渐变或帧混合;instant Session 则立即完成。

plan.validate_states(source, target)
target.on_prepare(ctx, source)
session = plan.create_session(...)

每帧:session.update(ctx, dt)

完成:
source.on_exit(ctx)
current = target
target.on_enter(ctx)

活动过渡被中断或 Session 抛错时调用目标 on_prepare_cancel(),当前状态仍是源状态。

9. action

mod.yaml 顶层 actions 生成只含 action 的事件规则,不切换状态。每条 action 必须声明非空的 manifest.label。状态机先查全局 handler,再调用当前状态的 on_action(ctx, name);都未处理会报错。

10. 图验证和状态信息

状态机验证未知目标、未声明事件、过渡能力、不可达状态和无出边状态。DOT/Mermaid 导出来自同一合成配置。

状态信息话题包含当前状态、pending/active transition、本周期事件以及 states、actions、profiles 和 remote events 快照。graph.actions[] 中的 manifest 会像 state manifest 一样展开,label 可直接用于界面显示。

Mod 节点状态位于顶层 nodes[]。进程内节点加入主 MultiThreadedExecutor;独立进程节点由 runner 加载同一个 Mod entrypoint。State 生命周期节点在目标状态准备前启动,过渡取消时回收,切换完成后释放源状态不再需要的节点。

11. 固定运行时

Mod、资源、动态模块和状态图只在节点启动时构建。启动失败会清理已经创建的资源、模块和注册项;启动成功后运行时保持不变。修改系统 YAML、Mod 或资产后必须重启节点,控制循环不扫描文件,也不动态替换状态机。

12. 扩展边界

  • 新动作:Mod 状态 + 工厂 + 清单。
  • 新模型:Mod 资源工厂。
  • 新业务过渡:Mod 的 ModDefinition.transition_plugins 显式注册。
  • 新后台 ROS 节点:Mod nodes + Python NodeBuildContext 工厂。
  • 新通用过渡:framework/transitions/
  • 新设备:InputDriverBase 工厂。
  • 新消息适配:MotionCommandsAdapter

13. 公共 API 边界

客户 Mod 只导入 bxi_example_py_elf3.framework.mod_apiframework/runtime 保存 RobotControlFramework、Mod loader、ResourceManager、状态构建器、状态机和 Transition 注册/编译逻辑。公开生命周期使用 RobotControlContext Protocol,不直接绑定 BxiExample。旧包路径已移除,不提供兼容转发层。

ctx.ros_node 是为必须创建 ROS subscription、service 或 timer 的高阶 Mod 保留的显式逃生口。普通状态不应使用它;一旦使用,该 Mod 就是主动选择 ROS 集成,而不是框架的主控制链路依赖 ROS。

相关文档

Clone this wiki locally