#!/usr/bin/env bash # ============================================================================= # scripts/lib/ros_domain.sh —— 真机与仿真的 DDS 域隔离 # # 为什么要单独抽一层 # ---------------- # 仿真侧(scripts/sim_env.sh)**强制** ROS_DOMAIN_ID=77,并且注释里写明了 # "隔离不能靠『环境里恰好没设』"。真机侧当时没有对应保护,于是同一个坑换个 # 方向又踩了一次(2026-09-28 实测): # # 先 source 过 sim_env.sh 的 shell(ROS_DOMAIN_ID=77 还 export 着) # 再起真机栈 → 真机栈落到**仿真的域**上 → 两边节点名撞车 # (/controller_manager、/robot_state_publisher、/arm_status_node…)、 # /joint_states 与 /tf 各有两个来源互相盖。 # # 现象极具误导性:控制器 feedback 与 reference 完全一致(控制器没坏), # 但 TF 显示末端**一动不动** —— 顺着现象查会一路查到 IK / TF / 时钟上, # 全是无辜的。 # # 真机侧有两个入口(scripts/env.sh 给交互 shell 用;scripts/run_real.sh 自己 # 起 conda + install),两处都得有这个纠正,所以放在这里共用一份。 # # 用法(在 `set -uo pipefail` 或 `set -eo pipefail` 之后 source): # source ".../lib/ros_domain.sh" # ros_domain_force_real # ============================================================================= # 仿真的域。改这里要同步 scripts/sim_env.sh(那边是硬编码的 77)。 ROS_SIM_DOMAIN=77 # 把 ROS_DOMAIN_ID 纠正到"真机该用的域"。 # · REAL_ROS_DOMAIN_ID 显式设了 → 用它(要换域就走这个,名字里带 REAL, # 不会被仿真环境的 export 撞上); # · 环境里是 77(仿真的域)→ **喊出来**再改回 0; # · 环境里没设 → 显式写 0,让人一眼能从 `env` 里看出真机跑在哪个域。 ros_domain_force_real() { if [ -n "${REAL_ROS_DOMAIN_ID:-}" ]; then export ROS_DOMAIN_ID="${REAL_ROS_DOMAIN_ID}" elif [ "${ROS_DOMAIN_ID:-0}" = "${ROS_SIM_DOMAIN}" ]; then echo "[domain] ⚠ 环境里的 ROS_DOMAIN_ID=${ROS_SIM_DOMAIN} 是**仿真**用的域" >&2 echo "[domain] (scripts/sim_env.sh 强制那个值)。已改回 0 起真机栈 ——" >&2 echo "[domain] 真机与仿真同域会让节点名/话题互相盖,现象是'臂没动'" >&2 echo "[domain] 而控制器一切正常。要另指定请设 REAL_ROS_DOMAIN_ID。" >&2 export ROS_DOMAIN_ID=0 elif [ -z "${ROS_DOMAIN_ID:-}" ]; then export ROS_DOMAIN_ID=0 fi }