动作分发概述
相关源文件
生成此 wiki 页面时使用了以下文件作为上下文:
Action Dispatch 包实现了一个基于拉取的动作分发层,位于 AI 推理服务和 ros2_control 硬件接口之间。它提供队列管理、基于水位线的推理触发,以及面向 ACT、Diffusion Policy 等 action chunking 模型的跨帧时序平滑。
有关生成动作的推理流水线,请参见 推理流水线。有关硬件控制和执行,请参见 硬件集成。
目的与范围
Action Dispatch 连接离散模型推理(延迟可变)和连续机器人控制(固定频率)。系统会:
维护 FIFO 动作队列,并在队列低于水位线阈值时触发新推理 src/action_dispatch/action_dispatch/action_dispatcher_node.py:43-82。
实现跨帧时序平滑,保证连续动作 chunk 之间平滑过渡 src/action_dispatch/action_dispatch/action_dispatcher_node.py:110-121。
通过
TopicExecutor向ros2_control控制器高频流式发送命令 src/action_dispatch/action_dispatch/action_dispatcher_node.py:153-156。支持带显式启动、停止逻辑和底盘速度控制的 Navigation Mode src/action_dispatch/action_dispatch/action_dispatcher_node.py:93-106。
来源: src/action_dispatch/action_dispatch/action_dispatcher_node.py:3-9, src/action_dispatch/README.md:3-8
IB-Robot 架构中的系统位置
graph TB
subgraph "Inference Layer (inference_service)"
Policy["LeRobotPolicyNode<br/>(lerobot_policy_node.py)"]
ActionServer["DispatchInfer<br/>Action Server"]
Policy --> ActionServer
end
subgraph "Action Dispatch Layer (action_dispatch)"
Dispatcher["ActionDispatcherNode<br/>(action_dispatcher_node.py)"]
Queue["Action Queue<br/>(collections.deque)"]
Smoother["TemporalSmootherManager<br/>(temporal_smoother.py)"]
Executor["TopicExecutor<br/>(topic_executor.py)"]
Dispatcher -->|"watermark < threshold"| ActionClient["DispatchInfer<br/>Action Client"]
ActionClient -->|"goal"| ActionServer
ActionServer -->|"result: VariantsList"| Dispatcher
Dispatcher --> Smoother
Smoother --> Queue
Queue -->|"pop @ control_frequency"| Executor
end
subgraph "Control Layer (ros2_control)"
Controllers["arm_position_controller<br/>gripper_position_controller"]
Hardware["SO101SystemHardware<br/>(so101_hardware)"]
Executor -->|"Float64MultiArray"| Controllers
Controllers --> Hardware
end
图:系统上下文中的 Action Dispatch
Action Dispatch 充当机器人的“小脑”,确保动作按硬件控制频率平滑执行。它消费 DispatchInfer action 返回的 VariantsList 结果,并将其映射到 robot_config 中定义的具体硬件控制器 src/robot_config/config/robots/so101_single_arm.yaml:116-123。
来源: src/action_dispatch/README.md:13-42, src/action_dispatch/action_dispatch/action_dispatcher_node.py:43-157, src/robot_config/config/robots/so101_single_arm.yaml:88-124
基于拉取的队列架构
运行原理
Action Dispatch 使用基于拉取的设计。分发器维护动作队列,并在剩余动作低于水位线时主动请求新的推理。
graph LR
subgraph "ActionDispatcherNode Loop @ control_frequency"
Start["Start Cycle"] --> Check{"Queue Length<br/>< watermark?"}
Check -->|"Yes"| Trigger["Trigger Inference<br/>(send_goal_async)"]
Check -->|"No"| Skip["Skip Inference"]
Trigger --> Pop
Skip --> Pop
Pop["Pop Next Action<br/>from _queue"] --> Execute["TopicExecutor.execute()"]
Execute --> Publish["Publish to<br/>joint command topics"]
Publish --> Start
end
subgraph "Async Result Handling"
Goal["DispatchInfer.Goal"] --> Result["_result_cb()"]
Result --> Decode["TensorMsgConverter.from_variants"]
Decode --> Smooth["TemporalSmootherManager.update"]
Smooth --> Enqueue["Refill _queue"]
end
Trigger -.->|"non-blocking"| Goal
Enqueue -.->|"fills queue"| Check
图:基于拉取的控制流
关键设计决策:
水位线触发:当队列大小低于
watermark_threshold时触发推理 src/action_dispatch/action_dispatch/action_dispatcher_node.py:80。异步 Action Client:对
DispatchInferaction 使用send_goal_async(),避免阻塞高频控制循环 src/action_dispatch/action_dispatch/action_dispatcher_node.py:159-161。动作对齐:当新的动作 chunk 到达时,分发器计算推理延迟期间已执行的动作数量(
_plan_length_at_inference_start),并据此对齐新的 chunk src/action_dispatch/action_dispatch/action_dispatcher_node.py:108-109。
来源: src/action_dispatch/action_dispatch/action_dispatcher_node.py:54-124, src/action_dispatch/README.md:84-129
子页面
动作分发器节点:介绍
ActionDispatcherNode实现、控制循环和DispatchInferaction client 逻辑。时序平滑:深入说明
TemporalSmoother算法、指数加权和跨帧动作 chunk 对齐。Topic 与 Action 执行器:介绍
TopicExecutor(将 tensor 映射到Float64MultiArray)和基于轨迹的ActionExecutor。
核心组件
ActionDispatcherNode
实现基于拉取分发器的主 ROS 2 节点。它协调 TopicExecutor 和 TemporalSmootherManager src/action_dispatch/action_dispatch/action_dispatcher_node.py:43-56。
Control Hz:硬件命令的可配置频率,例如 ACT 为 20Hz,teleop 为 100Hz src/robot_config/config/robots/so101_single_arm.yaml:123。
Watermark:触发新推理请求的阈值,例如 50 个动作,确保队列在高延迟分布式推理期间不会耗尽 src/robot_config/config/robots/so101_single_arm.yaml:122。
来源: src/action_dispatch/action_dispatch/action_dispatcher_node.py:54-157, src/robot_config/config/robots/so101_single_arm.yaml:116-124
TemporalSmoother
实现跨帧指数加权平滑。它混合连续推理周期中重叠的动作 chunk,防止运动抖动 src/action_dispatch/action_dispatch/action_dispatcher_node.py:35-37。
Ensemble Coeff:决定重叠区间中新旧动作的权重分配 src/action_dispatch/action_dispatch/action_dispatcher_node.py:75。
来源: src/action_dispatch/README.md:108-115, src/action_dispatch/action_dispatch/action_dispatcher_node.py:110-121
TopicExecutor
使用 contract action specs 将动作 tensor 索引映射到关节名称,并发布到 ros2_control 命令 topic src/action_dispatch/action_dispatch/action_dispatcher_node.py:38。
Contract Loading:通过
robot_config.loader自动从机器人配置加载关节映射 src/action_dispatch/action_dispatch/action_dispatcher_node.py:126-135。
来源: src/action_dispatch/action_dispatch/action_dispatcher_node.py:153-156
ROS 接口
发布的 Topics
~/queue_size(std_msgs/Int32):队列中剩余动作的当前数量。~/smoothing_enabled(std_msgs/Bool):时序平滑状态。
Services
~/reset:清空动作队列并重置内部状态。~/toggle_smoothing:运行时切换时序平滑。
Actions
/act_inference_node/DispatchInfer:用于从LeRobotPolicyNode拉取新动作 chunk 的 client 接口 src/action_dispatch/action_dispatch/action_dispatcher_node.py:62-64, src/inference_service/inference_service/lerobot_policy_node.py:148-158。
来源: src/action_dispatch/action_dispatch/action_dispatcher_node.py:58-82, src/inference_service/inference_service/lerobot_policy_node.py:27-34