先讲一下经过。
我现是用ubuntu22.04+miniconda玩了一把RAG,所以用conda配的环境。
然后又开始玩ROS2,跟着鱼香肉丝(fishros)的教程安装了ROS2,还玩了海龟模型。
第一天玩得很开心,第二天编写第一个python节点,第一句话
import rclpy
直接给我干废了。
写的py文件命令行能跑起来,pycharm就报错说找不到包。我在网上还找了一堆教程,尝试修复。
比如找到rclpy库所在文件夹,临时修改了环境变量:
export PYTHONPATH='/opt/ros/humble/local/lib/python3.10/dist-packages:$PYTHONPATH'
又报错:modulenotfounderror: No module named '_distutils_hack'
解决方案:
1、找到报错的文件,通过记事本打开

在 import os; 后面(注意是分号后面)敲一个回车,就是改成这样:
接着保存关闭就可以运行了
又报错: ImportError: librmw_fastrtps_cpp.so: cannot open shared object file: No such file or directory
++我不得不说这个时候我就感觉有点不对了。怎么什么库都找不到,怎么个意思需要我一个个export?++
然后我梳理了一下昨天到今天的操作。
昨天装完ros2以后在终端输入命令ros2,结果是这样的:

然后我搜了教程配置了一番,详情记录在https://blog.csdn.net/thinkpad1234567890/article/details/155458847?spm=1011.2124.3001.6209
重点来了朋友们,就是这句
source /opt/ros/humble/setup.bash
它的核心作用就是激活 ROS 2 的运行环境
我们从Linux 操作系统机制 、Shell 脚本原理 以及 ROS 2 的构建系统(Ament) 三个底层层面来细致拆解。
第一层:Linux Shell 机制 ------ 为什么要用 source?
在 Linux 终端中,执行脚本有两种主要方式:
-
直接运行 (例如
./setup.bash):- 系统会启动一个新的子 Shell (Sub-shell) 进程来运行脚本。
- 脚本里修改的变量(环境变量)只在这个子进程里有效。
- 脚本运行结束,子进程销毁,所有变量修改随之消失。你的当前终端(父进程)什么都不会改变。
- 结果 :你依然无法运行
ros2命令。
-
使用
source运行 (例如source setup.bash或. setup.bash):source是 Shell 的内建命令。- 它指示当前 Shell 在当前进程中逐行读取并执行脚本中的命令。
- 脚本里修改的环境变量会直接作用于当前终端。
- 结果 :环境变量被修改并保留下来,你可以运行
ros2命令了。
总结 :source /opt/ros/humble/setup.bash 是为了让脚本能够"通过修改当前终端的内存"来配置环境。
第二层:环境变量 ------ 到底修改了什么?
当脚本执行时,它主要是在你的内存中操作环境变量 (Environment Variables)。这就像是告诉系统去哪里找东西。
最关键的几个变量如下:
-
PATH(寻找可执行程序)- 修改前 :系统只知道去
/usr/bin等默认路径找命令。 - 修改后 :脚本把
/opt/ros/humble/bin加到了PATH的最前面。 - 作用 :当你输入
ros2或rviz2时,系统能在这个目录下找到对应的可执行文件。
- 修改前 :系统只知道去
-
PYTHONPATH(寻找 Python 库)- 作用 :ROS 2 大量使用 Python(比如
rclpy)。脚本会将/opt/ros/humble/lib/python3.10/site-packages加入此变量。 - 后果 :你的 Python 脚本才能成功
import rclpy或导入各种消息类型。
- 作用 :ROS 2 大量使用 Python(比如
-
LD_LIBRARY_PATH(寻找 C++ 动态链接库)- 作用 :ROS 2 底层是 C++。脚本会将
/opt/ros/humble/lib加入此变量。 - 后果 :程序运行时能加载
.so动态库文件(比如 DDS 通讯库)。
- 作用 :ROS 2 底层是 C++。脚本会将
-
AMENT_PREFIX_PATH(ROS 2 专属核心变量)- 作用:这是 ROS 2 构建系统 (Ament) 的核心。它告诉 ROS 2 工具链,ROS 安装在哪里。
- 后果 :
ros2 pkg list能列出包,ros2 launch能找到 launch 文件,全靠这个变量指路。
-
CMAKE_PREFIX_PATH- 作用 :让 CMake 构建工具能找到 ROS 2 的包,以便你在编译自己的代码时能
find_package(rclcpp)。
- 作用 :让 CMake 构建工具能找到 ROS 2 的包,以便你在编译自己的代码时能
第三层:脚本逻辑与 Ament 钩子 (Hooks) ------ 它是怎么工作的?
ROS 2 的 setup.bash 并不是一个简单的硬编码脚本,它设计得非常巧妙,支持模块化。
当你运行 source /opt/ros/humble/setup.bash 时,底层逻辑流如下:
- 入口 :
setup.bash只是一个入口,它会确定当前的 Shell 类型(bash, zsh 等)。 - 调用
local_setup.bash:它会调用同一目录下的local_setup.bash。这个脚本负责处理当前安装目录下的所有包。 - 环境钩子 (Environment Hooks) :
- 这是 ROS 2 (Ament) 最精妙的地方。
- ROS 2 的每个功能包(Package)在安装时,如果需要修改环境变量,会生成一个小的 shell 脚本片段(Hook)。
setup.bash会利用工具(通常是 Python 脚本_local_setup_util_sh)去扫描/opt/ros/humble/share下所有包定义的钩子。- 举例 :
ros_workspace包会提供钩子来设置AMENT_PREFIX_PATH。- 某些特定的包可能需要设置特殊的驱动路径。
- 循环执行 :脚本会遍历所有找到的钩子并
source它们。
这意味着:ROS 2 的环境配置是动态生成的,而不是写死的。如果你在这个目录下新装了一个包,下次 source 时,脚本会自动把新包的环境变量也加上。
第四层:工作空间覆盖 (Overlaying) ------ 为什么要这么设计?
你可能会问:"为什么不直接把这些路径写死在系统的 /etc/profile 里,让它永久生效?"
这就涉及到了 ROS 的工作空间覆盖(Workspace Overlaying) 机制:
- 底层 (Underlay) :
/opt/ros/humble是基础层。 - 上层 (Overlay) :你自己写的代码(比如
~/ros2_ws)。
当你编译自己的代码后,你需要 source ~/ros2_ws/install/setup.bash。 此时,新的 setup.bash 会:
- 检测到已经存在
AMENT_PREFIX_PATH(指向/opt/ros/humble)。 - 把你自己的路径(
~/ros2_ws/install)插到变量的最前面。
这就是"激活环境"的终极奥义 : 通过 source 操作,你在内存中构建了一个优先级列表。
- 系统找包时,先去你的工作空间找。
- 找不到,再去
/opt/ros/humble找。
这让你可以在不修改系统源码的情况下,修改或替换系统自带的节点(例如,你可以自己写一个同名的包来覆盖官方包)。
那么很显然,我这命令行能跑起来(说明库已经存在),pycharm就报错说找不到包,pycharm中反复出现各种动态连接库找不到的问题就是和环境配置有很大关系。
明明文件就在那里,系统却是个瞎子。哭了。
然后,罪魁祸首是谁呢?是miniconda !
如果你安装了 Anaconda 或 Miniconda,Conda 环境会劫持系统的路径。Conda 有自己的一套库文件(比如 libstdc++ 等),可能会屏蔽掉 ROS 需要的系统库,或者重置了 LD_LIBRARY_PATH
妈妈咪呀,我的老天乃!
接下来是我的自救过程。
首先在上次ROS2配置过程中,我在bashrc中加了一句:
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
这句是个全局配置,我们现把这句删掉:
sudo gedit ~/.bashrc
找到source /opt/ros/humble/setup.bash这句(通常在文件末尾),然后注释掉或者删掉
# source /opt/ros/humble/setup.bash
保存文件,然后重新开一个终端,等于说回退到

然后在 Conda 内部装 ROS
操作步骤:
-
创建一个新的 Conda 环境(不要污染你的 base 环境)
conda create -n ros_env python=3.10 conda activate ros_env -
添加 RoboStack 源并安装 ROS 2 Humble
conda config --env --add channels conda-forge conda config --env --add channels robostack-staging conda config --env --remove channels defaults # 安装 ROS 2 Humble 基础包 conda install ros-humble-desktop -
在这个环境里,你不需要 source
/opt/ros/...,直接就能用。而且你可以随意安装 pytorch 等库,它们会自动处理依赖兼容 -
验证Conda ROS 是否正常: 在新终端里激活你的 Conda 环境
conda activate ros2检查
ros2命令到底用的是谁的which ros2正确结果 :应该显示类似
/home/你的用户名/anaconda3/envs/ros2/bin/ros2测试运行
ros2 run demo_nodes_cpp talker如果能跑起来,恭喜你,环境完美了!
写到这里基本能解决我的问题了,还有一个问题是:
如果你偶尔还想用系统自带的 ROS 怎么办?
既然去掉了自动 source,如果你某天突然想用 /opt/ros/humble 下的系统版,该怎么办?
方法:使用别名 (Alias)
你可以再次编辑 ~/.bashrc,加上这一行:
alias load_sys_ros='source /opt/ros/humble/setup.bash'
使用逻辑:
- 日常使用 Conda 版 :打开终端 ->
conda activate ros2-> 直接用。 - 偶尔使用系统版 :打开终端 -> 确保没有 激活 Conda -> 输入
load_sys_ros-> 激活系统版环境。
核心原则: 永远不要在同一个终端里同时激活 Conda 环境和系统 ROS 环境,除非你是能够手写 CMakeList 的高级玩家。
如果你一打开终端conda就是激活的,那就不停地退出
conda deactivate
多退几次,直到前面没有括号了。
或者修改conda的全局配置,禁止自动激活 base:
conda config --set auto_activate_base false
你需要用环境时,再手动输入 conda activate xxx