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>

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐