仿真环境串味根治:清残留路径 + 补 conda lib + 修入口脚本 shebang

症状一(最隐蔽):同一 shell 里先 source 过真机环境(scripts/env.sh)再
source 仿真环境,install/ 与 ros_flexiv 的路径不会被 conda deactivate 撤掉,
长在 install_sim/ 前面:
  - PYTHONPATH 里真机那份 arm_msgs 压住仿真那份 → 消息类型混用
  - LD_LIBRARY_PATH 里没有 $CONDA_PREFIX/lib → sim_tactile_adapter 订阅
    ros_gz_interfaces/Contacts 时抛
      Type support not from this implementation ...
      cannot open shared object file
    而库其实就在 conda 里、ldd 全齐。整条触觉链静默死掉(话题不发)。

症状二:setuptools 写 console_scripts 用的是**构建那一刻**的 python。
若在真机环境里跑过 build_sim.sh,install_sim/ 里 7 个入口脚本的 shebang
会指向 ros_flexiv —— 而 ros2 run 是照 shebang 执行的,于是**仿真节点一直
跑在真机 conda 环境里**。两个环境都是 Humble+py3.11,所以"居然能跑",
只有偶发 dlopen / 反序列化怪错。

修法:
  - conda_switch.sh 新增 path_drop_patterns:按 glob 从冒号列表里删条目
  - sim_env.sh 清掉真机残留 + 末尾补 $CONDA_PREFIX/lib(优先级最低)
  - 新增 lib/fix_shebangs.sh,build.sh / build_sim.sh 收尾各扫一遍(幂等)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
arm_dev
2026-09-24 14:42:50 +08:00
parent bda2fa7129
commit aed5d326a0
5 changed files with 171 additions and 0 deletions
+26
View File
@@ -54,6 +54,32 @@ else
echo "提示: install_sim/ 还不存在,先跑 bash scripts/build_sim.sh" >&2
fi
# --- 清掉真机环境留下的路径残留 ---------------------------------------------
# 同一个 shell 里先 source 过 scripts/env.sh(真机)再 source 本文件时,install/
# 与 ros_flexiv 的路径不会被 conda deactivate 撤掉,会长在 install_sim/ 前面,
# 导致 import 到真机那份包、dlopen 到真机那份库。详见 conda_switch.sh 里
# path_drop_patterns 的注释(那里记了 sim_tactile_adapter 崩溃的实测症状)。
path_drop_patterns PYTHONPATH "${ROOT}/install/*" "${ROOT}/build/*" "*/envs/${REAL_ENV_NAME}/*"
path_drop_patterns LD_LIBRARY_PATH "${ROOT}/install/*" "*/envs/${REAL_ENV_NAME}/*"
path_drop_patterns PATH "${ROOT}/install/*" "*/envs/${REAL_ENV_NAME}/*"
path_drop_patterns AMENT_PREFIX_PATH "${ROOT}/install" "*/envs/${REAL_ENV_NAME}"
path_drop_patterns CMAKE_PREFIX_PATH "${ROOT}/install" "*/envs/${REAL_ENV_NAME}"
# --- 补上 conda 环境自己的 lib ----------------------------------------------
# conda 激活**不会**把 $CONDA_PREFIX/lib 放进 LD_LIBRARY_PATH(见下面 GZ 插件
# 路径那段长注释)。对 gz 我们靠 GZ_SIM_SYSTEM_PLUGIN_PATH 兜住了,但
# rosidl 的 typesupport 是靠 dlopen("lib<包名>__rosidl_typesupport_*.so") 找的,
# 只认 ld.so 的搜索路径。于是 conda 里带的(不在本工作区的)消息包会在
# create_publisher/create_subscription 时抛
# Type support not from this implementation ... cannot open shared object file
# 追加在**末尾**(优先级最低),避免压过系统/工作区里已有的同名库。
if [[ -n "${CONDA_PREFIX:-}" && -d "${CONDA_PREFIX}/lib" ]]; then
case ":${LD_LIBRARY_PATH:-}:" in
*":${CONDA_PREFIX}/lib:"*) ;;
*) export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${CONDA_PREFIX}/lib" ;;
esac
fi
[[ "${_sim_had_u}" -eq 1 ]] && set -u
unset _sim_had_u