命名空间与 Remap:可复制的图,而不是全局话题平原
节点内相对名,launch 推前缀;绝对名白名单;remap 是适配器不是架构。

1. 第二台机器人到来时,平原崩溃
第一台车代码里全是 /cmd_vel、/scan——单实例能跑。加第二台实例后,两台订阅同一个 /cmd_vel,遥控信号随机喂给某一台;或 launch 里临时 remap 狂欢,文档没有「裸名→全名」表,现场每人一套口头约定。Namespace 与 remapping 是构图工具:决定图能否复制、能否多实例、能否与第三方包对接。设计时把实例前缀(/robot1)当一等公民,不是上线前夕补丁。
2. 规则
节点内用相对名 cmd_vel,由 launch 推命名空间:
GroupAction([
PushRosNamespace('robot1'),
Node(package='teleop', executable='joy_node',
remappings=[('cmd_vel', 'cmd_vel')]), # → /robot1/cmd_vel
])绝对名以 / 开头,刺穿当前 namespace,落到图根——只留给真全局资源。TF 策略里 /tf、/tf_static 是否全局必须团队书面约定;其余绝对名默认禁止。私有 topic 用相对名即可表达「仅本节点关心」,不必为了「显得正式」加绝对路径。
调试必用:
ros2 node info /robot1/joy_node
ros2 topic list | grep cmd_vel看解析后的 fully qualified name,而不是猜 launch 字符串。
3. Remap 是适配器,不是架构
第三方驱动硬编码 publish scan(相对)还好;若硬编码 /scan(绝对),只能用 remapping 或 fork 适配:
Node(package='vendor_lidar', executable='driver',
remappings=[('/scan', 'scan')]) # 绝对→相对,再被 namespace 推前缀超过三处 remap 指向同一逻辑话题,说明接口未对齐——应回到驱动包装节点统一出口,而不是 launch 里再加第四行。Remap 适合桥接 legacy,不适合表达系统架构。__node:= 与 __ns:= 替换规则在 Humble 后更严格——旧教程里的匿名 remap 在新版可能 silently 失效,要以 ros2 node info 为准。
4. 多实例与 composition
多机启动两份相同 launch,各自 PushRosNamespace;CI 门禁跑「双实例串话测试」:robot1 发 cmd,robot2 的 odom 不应动。容器内 component 的 namespace 在 LoadNode 时确定:
ros2 component load /Container \
my_pkg LaserDriver -n robot1/lidar热加载缺省 namespace 的组件会污染根图——代码 review 必查 create_publisher 是否用相对名。参数也受 namespace 影响:ros2 param set /robot1/lidar frame_id 与根下 /lidar 不是同一节点——ros2 param list 按全名操作,调试时别漏前缀。
5. 全局名白名单与静态扫描
允许全局的话题/service 列白名单(通常仅 TF 相关 + 少数 fleet 广播)。CI 用脚本扫源码与 launch 里的 '/' 字符串,新增绝对名 MR 必须解释。第三方不得不用时,集中在一个 adapter.launch.py 并注释原因——比散落十个 launch 可审计。
6. 与 DDS 域、发现策略
Namespace 是 ROS 图逻辑;DDS ROS_DOMAIN_ID 是传输隔离。多机器人同域不同 namespace 仍可能带宽互扰;仿真与真机同域误连是另一类灾难。文档写清:domain 隔离机群,namespace 隔离实例。
ROS_LOCALHOST_ONLY=1 适合单机多实例调试,但不能替代 namespace——它只限本机 loopback,不解决同名 topic 冲突。fleet 里每台车固定 (domain_id, namespace) 二元组写进资产台账,现场扫码贴号与 launch 参数一致,减少手工改域。
7. 文档与测试验收
- README 有「裸名 → 全名」表(teleop、nav、perception 各一行示例)。
- 双实例测试自动化,合并前必绿。
- 故意去掉
PushRosNamespace:测试应捕获 cross-talk 或断言失败。 ros2 doctor无 unexpected duplicate node name。
8. 案例:绝对 /scan 刺穿 namespace
fleet 调度给 robot2 起导航,RViz 却显示 robot1 的激光——vendor 驱动 publish /scan 绝对名,robot2 的 remap 只改了相对订阅。修复:包装节点 re-publish 到相对名,或 fork 驱动。事后 CI 禁止新增绝对话题 publish。
9. 参数与节点的 namespace 联动
ros2 param load 的目标节点名含 namespace:/robot1/lidar。launch 里 PushRosNamespace 后,Node 的 name 是相对节点名,param 文件键无需重复前缀——但 CLI 操作必须带全名。文档示例命令与 launch 片段并列,减少现场手滑改错节点。
相对名 + launch 前缀;remap 当适配器;双实例测试当门禁。图可复制,运维才能复制。命名策略写进接口设计文档的第一页,而不是运维手册附录——第二台机器人到来时再补,成本最高。
相关
也可以看看
- ·3 分钟阅读
多机发现与命名:先定协作模型,再谈话题
隔离 domain 或同域 namespace 二选一;ROS_DOMAIN_ID、发现与带宽在算法之前。
- ·15 分钟阅读
ContentFilteredTopic:把过滤下推到中间件还是应用层
对比订阅端丢弃、应用层条件判断与 DDS 内容过滤的 CPU/带宽边界,说明表达式能力与发现时序限制;用高频率噪声话题与延迟尖峰验收过滤位置选择。
- ·16 分钟阅读
ROS 2 Action 取消语义:收到 cancel 不等于执行器已经停下
梳理 goal handle 状态机、取消回调与硬件停止之间的异步边界;用可中断执行循环、截止时间和终态发布构建契约并以注入验收。
johan's blog