ROS2 节点使用 Conda 环境运行 Python 依赖的解决方案
适用场景 :ROS2 节点需要 PyTorch、NumPy 等仅在 Conda 中安装的 Python 包,但 ros2 launch / ros2 run 启动时出现 ModuleNotFoundError,或 rclpy 与 Python 版本不匹配。
一、问题现象
在 Conda 环境(如 metarobotics)中已安装 PyTorch,且终端中 python3 -c "import torch" 正常,但通过 ROS2 launch 启动节点时报错:
ModuleNotFoundError: No module named 'torch'
或改用 conda run 后出现:
ModuleNotFoundError: No module named 'rclpy._rclpy_pybind11'
The C extension '...cpython-38-x86_64-linux-gnu.so' isn't present on the system.
二、原因分析
2.1 为什么 ModuleNotFoundError: No module named 'torch'?
ros2 run / ros2 launch 启动的节点,实际执行的是 colcon 安装时生成的入口脚本(如 install/lib/xxx_pkg/executable_name)。该脚本的 shebang 通常指向构建时的 Python 解释器 ,多为系统自带的 /usr/bin/python3,而非 Conda 环境中的 Python。
因此:
- 终端中
python3来自 Conda → 能找到 torch - 节点进程使用的 Python 来自系统 → 找不到 torch
2.2 为什么 rclpy._rclpy_pybind11 报错?
ROS2 Humble 的 rclpy C 扩展是为 Python 3.10 编译的。若 Conda 环境使用 Python 3.8:
- Conda 的 Python 3.8 能 import torch ✓
- 但 rclpy 的
.so文件是为 cpython-310 编译的,Python 3.8 无法加载 ✓ - 报错提示缺少
rclpy._rclpy_pybind11或 C 扩展不匹配
本质是 Python 版本不一致:ROS2 用 Python 3.10,Conda 用 Python 3.8。
三、解决方案
方案一:创建 Python 3.10 的 Conda 环境(推荐)
使 Conda 环境与 ROS2 Humble 使用同一 Python 版本,同时安装所需依赖:
bash
# 1. 创建 Python 3.10 环境
conda create -n ros2_torch python=3.10 -y
conda activate ros2_torch
# 2. 安装 PyTorch 等依赖
pip install torch numpy
# 3. 使用该环境启动 ROS2 节点(见下文 launch 配置)
在 launch 文件中通过 conda run 在指定环境中运行节点,例如:
python
from launch.actions import ExecuteProcess
eeg_simulator_node = ExecuteProcess(
cmd=[
'conda', 'run', '-n', 'ros2_torch', '--no-capture-output',
'python3', '-m', 'your_pkg.your_node_module', # 用 python -m 避免走系统 Python
'--ros-args', '--params-file', params_file,
],
output='screen',
shell=False,
)
注意 :必须用
python3 -m your_pkg.your_node_module,而不要用ros2 run。否则ros2 run调用的仍是 colcon 安装的脚本,可能继续使用系统 Python。
四、launch 中通过 conda run 指定环境的示例
以 eeg_bci_go2 包为例,支持通过 launch 参数指定 Conda 环境:
python
# launch 参数
conda_env_arg = DeclareLaunchArgument(
'conda_env',
default_value='ros2_torch', # 或 metarobotics(需 Python 3.10)
description='Conda environment for nodes that need PyTorch',
)
# 需要 PyTorch 的节点:用 python3 -m 在 Conda 中运行
eeg_simulator_node = ExecuteProcess(
cmd=[
'conda', 'run', '-n', LaunchConfiguration('conda_env'), '--no-capture-output',
'python3', '-m', 'eeg_bci_go2.eeg_simulator_node',
'--ros-args', '--params-file', params_file,
],
output='screen',
shell=False,
)
# 不需要 PyTorch 的节点:可用 ros2 run 或同样用 conda run
eeg_cmd_bridge_node = ExecuteProcess(
cmd=[
'conda', 'run', '-n', LaunchConfiguration('conda_env'), '--no-capture-output',
'ros2', 'run', 'eeg_bci_go2', 'eeg_cmd_bridge_node',
'--ros-args', '--params-file', params_file,
],
output='screen',
shell=False,
)
启动方式:
bash
# 默认使用 ros2_torch
ros2 launch my_package my_nodes_launch.py
# 指定 Conda 环境
ros2 launch my_package my_nodes_launch.py conda_env:=metarobotics
这样即使当前终端未激活 Conda,launch 也会在指定 Conda 环境中启动相关节点。