引言:
🔥 在同时安装了 ROS1 Noetic 和 ROS2 Foxy 的 Ubuntu 20.04 系统上,开发基于 ROS1 的视觉节点时,常面临两大痛点:
① 每次手动激活 Conda 虚拟环境 + 加载 ROS1 环境
② 节点需要开机自启动,且必须保证 ROS1 环境不被 ROS2 干扰本文提供一套经过验证的自动化方案,通过 systemd 服务 + 智能环境切换脚本 ,实现视觉节点的 开机自启动、环境隔离、自动重启,让你的机器人项目真正实现"一键部署、无人值守"。

📌 目录
-
整体思路
-
第一步:编写视觉节点启动脚本
-
第二步:创建 roscore 系统服务(可选但推荐)
-
第三步:创建视觉节点 systemd 服务
-
第四步:处理图形界面显示问题(若需要显示窗口)
-
第五步:启用并测试服务
-
常见问题与调试技巧
-
总结
1. 整体思路
| 模块 | 作用 |
|---|---|
| 启动脚本 | 清理 ROS2 环境变量 → 加载 ROS1 环境 → 激活 Conda 环境 → 运行视觉节点 |
| roscore 服务 | 确保 ROS 核心在视觉节点前启动,并支持自动重启 |
| systemd 服务 | 实现开机自启、进程守护、失败重启 |
| 环境依赖 | 正确配置 DISPLAY 和 XAUTHORITY(如果节点需要 GUI) |
2. 第一步:编写视觉节点启动脚本
假设你的 Conda 环境名为 vision_env,视觉节点脚本位于:
/home/your_user/catkin_ws/src/vision_node/scripts/vision_node.py
创建文件 /home/your_user/start_vision_node.sh,内容如下:
bash
#!/bin/bash
### 1. 清理可能冲突的 ROS 环境变量(防止 ROS2 干扰)
unset ROS_DISTRO ROS_PACKAGE_PATH ROS_MASTER_URI ROS_ROOT ROS_ETC_DIR
unset CMAKE_PREFIX_PATH AMENT_PREFIX_PATH PYTHONPATH
### 2. 加载 ROS1 Noetic 环境
source /opt/ros/noetic/setup.bash
# 如果有自定义工作空间,也加载它
source /home/your_user/catkin_ws/devel/setup.bash
### 3. 初始化 conda 并激活虚拟环境
# 注意:将下面的路径替换为你实际的 conda 安装路径
source /home/your_user/anaconda3/etc/profile.d/conda.sh
conda activate vision_env
### 4. 等待 roscore 就绪(最多等待 30 秒)
timeout=30
while ! rostopic list > /dev/null 2>&1; do
sleep 1
timeout=$((timeout-1))
if [ $timeout -le 0 ]; then
echo "[ERROR] roscore 未启动,退出"
exit 1
fi
done
### 5. 运行视觉节点
export ROS_MASTER_URI=http://localhost:11311
cd /home/your_user/catkin_ws
exec rosrun vision_node vision_node.py
# 如果是独立 Python 脚本,也可以用:
# exec python /home/your_user/catkin_ws/src/vision_node/scripts/vision_node.py
⚠️ 务必修改:
将
/home/your_user/替换为你的实际用户目录将
anaconda3替换为你的 conda 安装名(如miniconda3)将
vision_env替换为你的 Conda 环境名确保
vision_node.py具有可执行权限:chmod +x /path/to/vision_node.py
赋予脚本执行权限:
bash
sudo chmod +x /home/your_user/start_vision_node.sh
3. 第二步:创建 roscore 系统服务(可选但推荐)
将 roscore 做成独立服务,便于管理和依赖控制。
创建文件 /etc/systemd/system/roscore.service:
bash
ini
[Unit]
Description=ROS1 roscore
After=network.target
[Service]
Type=simple
User=your_user
Environment="ROS_MASTER_URI=http://localhost:11311"
ExecStart=/opt/ros/noetic/bin/roscore
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
4. 第三步:创建视觉节点 systemd 服务
创建文件 /etc/systemd/system/vision_node.service:
bash
ini
[Unit]
Description=Vision Node with ROS1 and Conda
After=roscore.service network.target
Requires=roscore.service # 确保 roscore 先启动
[Service]
Type=simple
User=your_user
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/home/your_user/.Xauthority"
Environment="QT_X11_NO_MITSHM=1"
ExecStart=/home/your_user/start_vision_node.sh
Restart=on-failure
RestartSec=5
WorkingDirectory=/home/your_user
# 日志输出到 journald
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
📌 说明
若节点不需要 GUI ,可删除
DISPLAY和XAUTHORITY行若需要访问摄像头等硬件,可能需要添加
User=your_user并加入video组:
sudo usermod -aG video your_user
5. 第四步:处理图形界面显示问题(若需要显示窗口)
如果你的视觉节点会弹出图像窗口(例如 cv2.imshow、rviz 等),需要解决 systemd 服务无法访问 X11 显示 的问题。
🔹 方法一:使用用户级 systemd 服务(推荐,依赖图形会话)
将服务文件放到用户目录下,并改为**--user** 模式。
-
复制服务文件到用户配置目录:
bashmkdir -p ~/.config/systemd/user cp /etc/systemd/system/vision_node.service ~/.config/systemd/user/ -
修改用户级服务文件中的
After和WantedBy:bashini [Unit] Description=Vision Node with ROS1 and Conda After=graphical-session.target # 等待图形会话启动 [Service] Type=simple Environment="DISPLAY=:0" Environment="XAUTHORITY=%h/.Xauthority" ExecStart=/home/your_user/start_vision_node.sh Restart=on-failure [Install] WantedBy=default.target -
启用并启动:
bashsystemctl --user enable vision_node.service systemctl --user start vision_node.service
✅ 优点:自动继承当前登录用户的 X11 权限,无需额外配置。
🔹 方法二:使用 Xvfb 虚拟显示器(无界面场景)
如果不需要实际显示图像,但节点必须运行 GUI 代码,可使用虚拟显示器:
bash
sudo apt install xvfb
修改启动脚本,在运行节点前加上 xvfb-run:
bash
exec xvfb-run -a rosrun vision_node vision_node.py
6. 第五步:启用并测试服务
bash
# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 启动 roscore 服务(若创建了)
sudo systemctl enable roscore.service
sudo systemctl start roscore.service
# 启动视觉节点服务
sudo systemctl enable vision_node.service
sudo systemctl start vision_node.service
# 查看服务状态
sudo systemctl status vision_node.service
# 实时查看日志
journalctl -u vision_node.service -f
如果一切正常,重启系统后视觉节点会自动运行。
7. 常见问题与调试技巧
❌ 问题1:conda: command not found
原因 :非交互式 shell 未加载 conda 初始化脚本。
解决 :在启动脚本中显式 source conda 的 profile.d/conda.sh,如上述代码所示。
❌ 问题2:roscore 未启动,视觉节点卡在等待
原因 :roscore 服务启动较慢。
解决 :在启动脚本中增加等待逻辑(已包含);或修改服务依赖为 After=roscore.service 并去掉脚本中的等待循环。
❌ 问题3:图形窗口无法显示
原因 :systemd 服务默认无法访问 X11。
解决 :改用用户级 systemd 服务(见第四节),或在服务文件中正确设置 DISPLAY 和 XAUTHORITY 并允许 X11 连接:
bash
xhost +SI:localuser:your_user # 一次性命令,重启失效
更稳妥的办法是使用用户级服务。
❌ 问题4:ROS2 环境变量污染,导致 rosrun 找不到包
原因 :系统 .bashrc 中同时 source 了 ROS1 和 ROS2。
解决 :在启动脚本开头强制清理 所有 ROS2 相关环境变量(已包含)。同时确保 .bashrc 中不要自动 source 任何 ROS 环境,或通过条件判断隔离。
8. 总结
通过本方案,你可以在 ROS1/ROS2 共存的 Ubuntu 20.04 上实现:
| 需求 | 实现方式 |
|---|---|
| 自动激活 Conda 环境 | 启动脚本中 conda activate |
| 加载 ROS1 环境 | 清理冲突变量后 source /opt/ros/noetic/setup.bash |
| 开机自启动 | systemd 服务 enable |
| 进程守护与自动重启 | systemd 的 Restart=on-failure |
| 图形界面支持 | 用户级 systemd 服务 + X11 权限 |
| 依赖 roscore | After 和 Requires 控制启动顺序 |
最后提醒:
-
所有路径、用户名、conda 安装目录请根据实际情况修改
-
先手动执行启动脚本验证无误,再部署为系统服务
-
若视觉节点需要频繁修改,建议在调试阶段使用用户级服务,方便查看终端输出
将这套方案融入你的机器人项目中,即可享受"开机即用、零人工干预"的 ROS 视觉节点运行体验!