Files
ros_contorl/scripts/sim_env.sh
T
arm_dev a89250d05d P5c-1:把 Gazebo 仿真环境真正装起来(独立 conda 环境),并固化安装/构建流程
在此之前,仓库里所有 Gazebo 相关的东西都是"声明"而非"事实":
arm.gazebo.xacro 零引用、stack.launch.py 的 isaac 分支只打印日志、
没有 world 文件、devices/sim/gazebo 下的目录全是空占位。
更关键的是:**这台机器上根本没装 Gazebo**,而 ROS 在 conda 里,没有 /opt/ros,
apt 的 ros-humble-gazebo-* 装了也不会被 conda 的 ROS 认到。

环境(与真机环境物理隔离)
- 新建 conda 环境 ros_gz_sim,**不碰能跑真机的 ros_flexiv**。
  仿真要往环境里塞 Gazebo 及 protobuf/ignition/渲染一整条链,
  和真机环境混装随时可能把它弄坏,代价远大于仿真带来的便利。
- 频道组合照抄 ros_flexiv 的安装记录(robostack-staging + conda-forge),
  那是本机已经证明可用的搭配。

两个实测踩到的坑(都写进了脚本注释,避免下次重踩)
1. empy 版本:conda 默认给 empy 4.x,而 Humble 的 rosidl_adapter 用的是 3.x 的
   API。症状是构建自定义消息包时报 `_interpreter.shutdown()` 的 AttributeError,
   报错点在 rosidl_adapter 内部,完全看不出跟 empy 有关。必须钉 empy=3.3.4。
2. conda 激活是**堆叠**的:同一 shell 里从 ros_gz_sim 切到 ros_flexiv 后,
   `which python` 指向 ros_flexiv,但 `python -m pip` 却解析到 ros_gz_sim 的 pip,
   导致 colcon --symlink-install 报 "option --editable not recognized"。
   这个报错和真实原因毫无关系,极易误判成"环境被搞坏了"。
   现在 scripts/lib/conda_switch.sh 会在切换前退到 base,两个 env 脚本共用。

仿真用独立构建产物
- build_sim/ + install_sim/(scripts/build_sim.sh)。工作区只有一份源码,
  若仿真也写 install/,就会覆盖真机的构建产物。
- 排除 11 个真机专属包(flexiv_hardware 需要 Flexiv RDK C++ SDK,根本装不上;
  另有真机驱动/GPIO/MoveIt 配置/真机 bringup),每个都在脚本里写了理由。

已验证(不是只看退出码)
- Gazebo Fortress 6.16 无头启动正常,物理初始化完成
- /clock 桥接到 ROS 成功收到仿真时间;ros_gz_sim create 成功往世界里建物
- 真机构建 18 包通过、233 项测试通过,build/ install/ 时间戳未变(没被覆盖)
- 仿真侧 7 包构建通过;两环境互切后各自都能正常构建

注:Humble 配的是 Gazebo Fortress(ignition-gazebo6,命令行 `ign gazebo`),
不是现代的 gz-sim —— 后者要 libprotobuf>=6.31,与 RoboStack Humble 钉住的
5.29.3 解不开依赖。Fortress 属于新 Gazebo 家族(非已 EOL 的 Classic),
且是 Humble 的官方配对版本。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-23 13:52:04 +08:00

71 lines
2.9 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# =============================================================================
# 激活**仿真**环境(Gazebo Fortress + 本工作区的仿真构建产物)。
#
# 用法: source scripts/sim_env.sh
#
# 与 scripts/env.sh(真机环境)的关系:
# 两者互斥,各自用一套 conda 环境 + 一套构建产物。
# 真机: ros_flexiv → build/ install/
# 仿真: ros_gz_sim → build_sim/ install_sim/
# 切换时**最好开新的 shell**。同一 shell 里来回切会残留 PATH/PYTHONPATH,
# 症状详见 scripts/lib/conda_switch.sh 顶部的说明(实测踩过)。
# 这里会先退到 base 再切以尽量规避,但开新 shell 才是稳妥做法。
#
# 为什么仿真用独立的 build/install 目录:
# 工作区只有一份源码。如果仿真也往 install/ 里写,就会把真机环境的构建
# 产物覆盖掉(两边的依赖路径不同)。分目录后互不干扰。
# =============================================================================
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SIM_ENV_NAME="${SIM_ENV_NAME:-ros_gz_sim}"
REAL_ENV_NAME="${REAL_ENV_NAME:-ros_flexiv}"
CONDA_SH="${HOME}/anaconda3/etc/profile.d/conda.sh"
# shellcheck disable=SC1091
source "${ROOT}/scripts/lib/conda_switch.sh"
if [[ ! -f "${CONDA_SH}" ]]; then
echo "找不到 conda: ${CONDA_SH}" >&2
return 1 2>/dev/null || exit 1
fi
# shellcheck disable=SC1090
source "${CONDA_SH}"
# 关掉 `set -u`:ROS 的 activate.d 脚本会引用未绑定的 CONDA_BUILD,
# 调用方常带 set -u,那样会直接把 source 打断,表现为"脚本毫无输出就退出"。
_sim_had_u=0
case "$-" in *u*) _sim_had_u=1; set +u ;; esac
if ! conda_switch_clean "${SIM_ENV_NAME}" "${REAL_ENV_NAME}"; then
[[ "${_sim_had_u}" -eq 1 ]] && set -u
unset _sim_had_u
echo "无法激活 conda 环境 ${SIM_ENV_NAME}。" >&2
echo "先创建: bash ${ROOT}/scripts/install_sim_env.sh" >&2
return 1 2>/dev/null || exit 1
fi
# 仿真构建产物(由 scripts/build_sim.sh 用 --install-base 生成,与真机隔离)
if [[ -f "${ROOT}/install_sim/setup.bash" ]]; then
# shellcheck disable=SC1091
source "${ROOT}/install_sim/setup.bash"
else
echo "提示: install_sim/ 还不存在,先跑 bash scripts/build_sim.sh" >&2
fi
[[ "${_sim_had_u}" -eq 1 ]] && set -u
unset _sim_had_u
export YOLO_AUTOINSTALL=false
export ROS2_WS="${ROOT}"
# 仿真单独一个 DDS domain:避免与正在跑的真机节点互相抢话题/污染 TF。
# 真机用的是默认 domain,两者天然隔离。
export ROS_DOMAIN_ID="${ROS_DOMAIN_ID:-77}"
# 仿真与真机共用同一份 site.yaml —— 这样"仿真里调好的参数搬到真机也生效"。
# shellcheck disable=SC1091
source "${ROOT}/scripts/lib/load_site_config.sh" 2>/dev/null || true
echo "[sim_env] CONDA=${CONDA_DEFAULT_ENV} ROS_DISTRO=${ROS_DISTRO} ROS_DOMAIN_ID=${ROS_DOMAIN_ID}"