ROS2多机械臂系统Zenoh通信权限与路由配置技术问询
ROS2+Zenoh多机械臂通信控制问题
系统背景
我们正在开发一款搭载多台同款机械臂的ROS2机器人,机器人本体及每台机械臂均配备独立控制PC,在Docker环境中运行ROS2,所有PC通过固定IP互联。
通信需求
- 大部分topic无需跨PC传输
- 机器人仅需向所有机械臂统一发布少量特定topic
- 机械臂仅需向机器人发布少量特定topic
- 机械臂之间严禁任何topic通信
当前尝试方案
此前采用FastDDS实现通信逻辑,因可靠性问题计划切换为Zenoh,当前方案:
- 每台控制PC运行独立Zenoh客户端路由器,统一连接至一台中央Zenoh路由器
- 中央路由器配置过滤器仅允许
/relay/*类topic通行 - 机器人用
/robot命名空间做内部通信,通过/relay命名空间与机械臂通信 - 所有机械臂用
/arm命名空间做内部通信,通过/relay命名空间与机器人通信
当前问题
该方案可实现机器人与机械臂间的通信,但机械臂发往机器人的通信可被其他机械臂发现,带来不必要的开销与混淆。
核心疑问
- 采用过滤路由器是否是限制通信的合理方案?
- 是否可将特定命名空间/topic仅发布至指定IP或客户端路由器?或仅允许特定IP地址间的通信?
当前使用的Zenoh配置文件
{ /// Router mode configuration mode: "router", listen: { endpoints: [ "tcp/[::]:7448" ], timeout_ms: 0, exit_on_failure: true, retry: { period_init_ms: 1000, period_max_ms: 4000, period_increase_factor: 2, }, }, /// Connect to the specified remote routers connect: { timeout_ms: { router: -1, peer: -1, client: 0 }, endpoints: [ // Router runs on robot PC, so IP 127.0.0.1 refers to robot PC "tcp/127.0.0.1:7447", // Robot arms IP "tcp/192.168.2.100:7447", "tcp/192.168.3.100:7447", "tcp/192.168.4.100:7447", "tcp/192.168.5.100:7447" ], exit_on_failure: { router: false, peer: false, client: true }, retry: { period_init_ms: 1000, period_max_ms: 4000, period_increase_factor: 1, }, }, /// Configure access control to only allow relay traffic access_control: { enabled: true, default_permission: "deny", rules: [ { id: "allow_only_relay", permission: "allow", messages: [ "put", "delete", "declare_subscriber", "query", "reply", "declare_queryable", "liveliness_token", "liveliness_query", "declare_liveliness_subscriber" ], flows: [ "ingress", "egress" ], key_exprs: [ // Make listening to relay topics possible "*/relay/**", // Make relay topics discoverable "@ros2_lv/**/%relay/**" ], } ], /// list of subjects: subjects: [ { // Interface identifier id: "all_interfaces", }, ], /// apply rule to subject in the policies list policies: [ { rules: [ "allow_only_relay" ], subjects: [ "all_interfaces" ], }, ], }, /// Standard router configuration from defaults scouting: { timeout: 3000, delay: 500, multicast: { enabled: false, address: "224.0.0.224:7446", interface: "auto", ttl: 1, autoconnect: { router: [], peer: [ "router", "peer" ], client: [ "router" ] }, autoconnect_strategy: { router: { to_router: "always", to_peer: "always" } }, listen: true, }, gossip: { enabled: true, multihop: false, target: { router: [ "router", "peer" ], peer: [ "router" ] }, autoconnect: { router: [], peer: [ "router", "peer" ] }, autoconnect_strategy: { router: { to_router: "always", to_peer: "always" } }, }, }, timestamping: { enabled: { router: true, peer: true, client: true }, drop_future_timestamp: false, }, queries_default_timeout: 60000, routing: { router: { peers_failover_brokering: false, }, peer: { mode: "peer_to_peer", }, interests: { timeout: 10000, }, }, transport: { unicast: { open_timeout: 60000, accept_timeout: 60000, accept_pending: 10000, max_sessions: 10000, max_links: 1, lowlatency: false, qos: { enabled: true, }, compression: { enabled: false, }, }, multicast: { join_interval: 2500, max_sessions: 1000, qos: { enabled: false, }, compression: { enabled: false, }, }, link: { tx: { sequence_number_resolution: "32bit", lease: 60000, keep_alive: 2, } } } }
解答
问题1:过滤路由器是否是限制通信的合理方案?
是,但当前配置粒度不足。现有规则仅允许/relay/**相关topic通行,未区分通信的来源与目标,导致所有接入中央路由器的节点都能看到/relay下的全部数据,包括机械臂之间的交叉可见。
这种中央路由器管控流量的核心思路是正确的——避免节点间直接通信,但需要细化访问控制规则,结合来源身份或IP限制流量流向。
问题2:能否将特定命名空间/topic仅发布至指定IP或客户端路由器?
可以,通过Zenoh的访问控制规则扩展和路由策略配置实现,具体有两种方向:
方向1:基于IP的访问控制细化
修改中央路由器的access_control配置,为机器人和每个机械臂的IP创建独立subject,再针对不同subject设置差异化规则:
- 为机器人PC的IP(如
127.0.0.1)创建subject,允许它向所有机械臂IP发送/relay/**消息,同时接收所有机械臂发往/relay/**的消息 - 为每个机械臂的IP创建独立subject,仅允许它们向机器人IP发送
/relay/**消息,且只能接收来自机器人IP的/relay/**消息,禁止接收其他机械臂的消息
示例配置片段:
"subjects": [ { "id": "robot_pc", "ip": "127.0.0.1" }, { "id": "arm_1", "ip": "192.168.2.100" }, { "id": "arm_2", "ip": "192.168.3.100" } ], "rules": [ // 机器人可向所有机械臂发消息,也能接收所有机械臂的消息 { "id": "robot_relay_full", "permission": "allow", "messages": ["put", "delete", "declare_subscriber", ...], "flows": ["ingress", "egress"], "key_exprs": ["*/relay/**", "@ros2_lv/**/%relay/**"], "subjects": ["robot_pc"] }, // 机械臂只能向机器人发消息 { "id": "arm_relay_to_robot", "permission": "allow", "messages": ["put", "delete", ...], "flows": ["egress"], "key_exprs": ["*/relay/**", "@ros2_lv/**/%relay/**"], "subjects": ["arm_1", "arm_2"], "targets": ["robot_pc"] }, // 机械臂只能接收机器人的消息 { "id": "arm_relay_from_robot", "permission": "allow", "messages": ["declare_subscriber", ...], "flows": ["ingress"], "key_exprs": ["*/relay/**", "@ros2_lv/**/%relay/**"], "subjects": ["arm_1", "arm_2"], "sources": ["robot_pc"] } ], "policies": [ { "rules": ["robot_relay_full", "arm_relay_to_robot", "arm_relay_from_robot"], "subjects": ["robot_pc", "arm_1", "arm_2"] } ]
方向2:基于Zenoh路由的点对点定向转发
若不想依赖IP控制,可在中央路由器的routing配置中,设置/relay主题的定向转发规则:
- 所有机械臂发往
/relay的消息,仅转发给机器人的路由器节点 - 机器人发往
/relay的消息,转发给所有机械臂的路由器节点 - 禁止机械臂节点之间的任何消息转发
这种方式需在中央路由器中为每个节点设置明确路由策略,确保流量仅在机器人与对应机械臂间流动,机械臂之间完全隔离。
额外优化建议
- 关闭Zenoh的
gossip功能(当前配置gossip.enabled: true),避免节点间自动发现和拓扑信息传播,减少不必要开销 - 为每个机械臂的
/relay主题添加独立子命名空间(如/relay/arm1/、/relay/arm2/),结合访问控制规则进一步细化流量隔离
内容的提问来源于stack exchange,提问作者wouterio
相关产品推荐
相关产品推荐

