Files
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

137 lines
5.1 KiB
Bash
Raw Permalink 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 仿真用的独立 conda 环境。
#
# 为什么单独一个环境,而不是往 ros_flexiv 里装:
# ros_flexiv 是**能跑真机**的那一套。仿真需要往环境里加 Gazebo 及其一大堆
# 依赖(protobuf / ignition / 渲染栈),和真机环境混装随时可能把它弄坏。
# 真机环境坏了,代价远大于仿真带来的便利。所以两者物理隔离。
#
# 用法:
# bash scripts/install_sim_env.sh # 创建或补齐(幂等,可重复跑)
# bash scripts/install_sim_env.sh --verify # 只验证现有环境,不安装
#
# 装完用 scripts/sim_env.sh 激活,用 scripts/run_sim_gz.sh 启动。
# =============================================================================
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ENV_NAME="${SIM_ENV_NAME:-ros_gz_sim}"
CONDA_SH="${HOME}/anaconda3/etc/profile.d/conda.sh"
# 频道组合照抄现有 ros_flexiv 环境的安装记录,那是已经证明可用的搭配。
CHANNELS=(-c robostack-staging -c conda-forge)
ok() { printf ' \033[32m✓\033[0m %s\n' "$1"; }
info() { printf ' \033[36m·\033[0m %s\n' "$1"; }
die() { printf ' \033[31m✗ %s\033[0m\n' "$1" >&2; exit 1; }
if [[ ! -f "${CONDA_SH}" ]]; then
die "找不到 conda: ${CONDA_SH}(本脚本假定 anaconda 装在 ~/anaconda3)"
fi
# shellcheck disable=SC1090
source "${CONDA_SH}"
# --- 验证 -------------------------------------------------------------------
verify() {
info "激活 ${ENV_NAME} 并自检…"
conda activate "${ENV_NAME}" 2>/dev/null || die "激活失败,环境可能没建好"
echo
echo "1) 仿真器本体"
# 注意:Humble 配的是 Gazebo Fortress,命令行是 `ign gazebo`,不是 `gz sim`。
# 现代包名 gz-sim 在 conda-forge 上要 libprotobuf>=6.31,而 RoboStack 的
# Humble 把 protobuf 钉在 5.29.3,混装会解不开依赖。Fortress 是官方配对版本。
ign gazebo --version 2>&1 | head -1 | sed 's/^/ /'
echo
echo "2) ROS 侧桥接与力控"
local missing=0 p
for p in ros_gz_sim ros_gz_bridge gz_ros2_control controller_manager ros2_control xacro; do
if ros2 pkg prefix "$p" >/dev/null 2>&1; then
ok "$p"
else
printf ' \033[31m✗ %s 缺失\033[0m\n' "$p"; missing=1
fi
done
echo
echo "3) 构建工具链(Humble 的 rosidl 需要 empy 3.x)"
local empy_ver
empy_ver="$(python -c 'import em; print(em.__version__)' 2>/dev/null || echo '?')"
if [[ "${empy_ver}" == 3.* ]]; then
ok "empy ${empy_ver}"
else
printf ' \033[31m✗ empy %s —— 必须是 3.x,否则 rosidl 生成接口时会报\n' "${empy_ver}"
printf ' "AttributeError: NoneType object has no attribute shutdown"\033[0m\n'
missing=1
fi
echo
echo "4) 仿真能真跑起来吗(无头空跑 30 步)"
local world
world="$(find "${CONDA_PREFIX}/share" -name empty.sdf -path '*gazebo*' 2>/dev/null | head -1)"
if [[ -n "${world}" ]] && timeout 60 ign gazebo -s -r --iterations 30 "${world}" >/dev/null 2>&1; then
ok "仿真引擎正常启动"
else
printf ' \033[31m✗ 仿真引擎启动失败\033[0m\n'; missing=1
fi
echo
if [[ "${missing}" -eq 0 ]]; then
echo "环境就绪。下一步:"
echo " source scripts/sim_env.sh"
echo " bash scripts/build_sim.sh"
echo " bash scripts/run_sim_gz.sh"
else
echo "环境不完整,重跑 bash scripts/install_sim_env.sh 补齐。"
return 1
fi
}
if [[ "${1:-}" == "--verify" ]]; then
verify
exit $?
fi
# --- 安装 -------------------------------------------------------------------
echo "=== 1/4 创建环境 ${ENV_NAME} ==="
if conda env list | awk '{print $1}' | grep -qx "${ENV_NAME}"; then
ok "已存在,跳过创建"
else
conda create -y -n "${ENV_NAME}" python=3.11 pip || die "创建环境失败"
ok "已创建"
fi
echo
echo "=== 2/4 安装 ROS 2 Humble 仿真栈 ==="
info "ros-humble-ros-gz 会一并带入 Gazebo Fortress(ignition-gazebo6)"
conda install -y -n "${ENV_NAME}" "${CHANNELS[@]}" \
ros-humble-ros-base \
ros-humble-ros-gz \
ros-humble-gz-ros2-control \
ros-humble-ros2-control \
ros-humble-ros2-controllers \
ros-humble-controller-manager \
ros-humble-robot-state-publisher \
ros-humble-joint-state-publisher \
ros-humble-joint-state-publisher-gui \
ros-humble-xacro \
ros-humble-tf2-ros \
ros-humble-camera-info-manager \
ros-humble-image-transport-plugins \
compilers cmake make pkg-config catkin_pkg lark-parser numpy \
colcon-common-extensions || die "ROS 仿真栈安装失败"
echo
echo "=== 3/4 钉住 empy 3.x(Humble 的硬性要求)==="
# 坑:conda 默认会给 empy 4.x,而 Humble 的 rosidl_adapter 用 empy 3.x 的 API。
# 症状是构建自定义消息包时报 '_interpreter.shutdown()' 的 AttributeError,
# 报错点在 rosidl_adapter 内部,看起来完全不像 empy 的问题。
conda install -y -n "${ENV_NAME}" "${CHANNELS[@]}" "empy=3.3.4" || die "empy 降级失败"
ok "empy 3.3.4"
echo
echo "=== 4/4 自检 ==="
verify