Linux/ROS 下固定 USB 串口设备名称(解决 video0/video1 乱跳问题)
·
1. 问题背景
在 Linux 环境下(如 Ubuntu + ROS)开发机器人时,经常会挂载多个 USB 设备(双目相机、激光雷达、IMU、单片机等)。系统默认按照插入顺序或响应速度分配设备名(如 /dev/video0, /dev/video1, /dev/ttyUSB0)。
痛点:
-
设备冲突:重启电脑或重新插拔后,设备可能从
video0变成了video2,导致代码报错(OpenCV Error: device not found)。
解决方案:
利用 Linux 的 udev (Userspace Device) 机制,根据设备的唯一硬件 ID(Vendor ID 和 Product ID),为其绑定一个固定的软链接别名(Symlink),并自动赋予读写权限。
2. 操作步骤
第一步:获取设备硬件 ID
首先插上设备,确认其当前的临时名称(例如 /dev/video2)。
在终端执行以下命令查看详细信息:
Bash
udevadm info --attribute-walk --name=/dev/video2 | grep -E "idVendor|idProduct"
输出示例(取最上方的一组):
ATTRS{idVendor}=="1bcf" <-- 厂商ID
ATTRS{idProduct}=="2d4f" <-- 产品ID
注意:请务必记录最顶层(输出结果的第一组)的 ID,后续的 ID 通常属于 USB Hub 或主板控制器。
第二步:编写 udev 规则文件
进入规则目录,新建一个 .rules 文件(文件名建议以 99- 开头,表示高优先级):
Bash
sudo gedit /etc/udev/rules.d/99-hbv-camera.rules
在文件中写入以下内容(替换为您查到的 ID):
# 格式说明:
# SUBSYSTEM: 设备子系统 (摄像头是 video4linux, 串口是 tty)
# ATTRS{idVendor/Product}: 刚才查到的硬件身份证
# MODE: 0666 表示赋予所有用户读写权限 (解决 sudo 问题)
# SYMLINK: 我们自定义的固定名字
SUBSYSTEM=="video4linux", ATTRS{idVendor}=="1bcf", ATTRS{idProduct}=="2d4f", ATTR{index}=="0", MODE="0666", SYMLINK+="video_cam"
第三步:重载规则并生效
保存文件后,在终端执行以下命令使规则立即生效(无需重启电脑):
sudo udevadm control --reload-rules && sudo udevadm trigger
此时拔掉设备重新插入,检查是否生成了别名:
ls -l /dev/hbv_cam
# 输出应类似: lrwxrwxrwx 1 root root ... /dev/hbv_cam -> video2
3. 代码适配指南
配置好别名后,代码中不再使用 0, 1, 2 这种数字索引,而是使用字符串路径。
C++ (OpenCV)
C++
#include <opencv2/opencv.hpp>
// 旧写法 (不推荐)
// cv::VideoCapture cap(0);
// 新写法 (推荐)
std::string device_path = "/dev/hbv_cam";
cv::VideoCapture cap;
// 强制指定 V4L2 后端,兼容性更好
cap.open(device_path, cv::::CAP_V4L2);
if (!cap.isOpened()) {
std::cerr << "无法打开设备: " << device_path << std::endl;
}
Python (OpenCV)
Python
import cv2
# 直接传入路径字符串
cap = cv2.VideoCapture("/dev/hbv_cam")
ROS Launch 文件
<launch>
<node pkg="my_driver" type="camera_node" name="cam_node">
<param name="video_device" value="/dev/hbv_cam" />
</node>
</launch>
更多推荐



所有评论(0)