我自己在 Ubuntu 20.04 上折腾 Intel RealSense D435i 驱动踩了整整两天坑,从 USB2.0 带宽不足导致深度流频繁掉线,到 udev 规则没配导致权限报错,再到内核 UVC 模块补丁缺失引发的 metadata 流不工作,几乎把新手能遇到的大坑全部踩了一遍。把解决过程整理出来,希望对正在折腾 D435i 的人有帮助。
1. 前置:为什么D435i在Ubuntu 20.04上容易翻车
D435i 是 Intel RealSense 系列里比较特殊的一款,它除了深度相机本身,还带了一个 IMU(惯性测量单元),可以同时输出加速度计和陀螺仪数据。在 Ubuntu 20.04 下,它不像普通 UVC 摄像头那样插上就能用,官方 SDK(librealsense)需要自己编译或者配置仓库,而且驱动层对 USB 控制器、内核模块、权限规则都有要求,任何一个环节出问题,最终表现都是同样的“设备插入无反应”或者“深度流启动报错”。
另一个容易忽略的点是,D435i 的定位是机器人、机械臂、SLAM 这类场景。它的深度图像和 IMU 数据需要同步输出,对 USB 传输带宽和稳定性要求很高。如果你看到有人用 USB2.0 HUB 去接 D435i,或者主板 USB 口供电不足,大概率会碰到深度流花屏、卡顿、甚至直接断连。所以围绕 D435i 的驱动安装,本质上不是“装个软件”这么简单,而是把内核、USB 链路、设备权限、SDK 版本这几个层次全部对齐的过程。
这篇指南面向的读者是:在 Ubuntu 20.04 上第一次使用 D435i 的开发者、学生、机器人方向的研究人员。我会从最容易被忽视的 USB3.0 检测讲起,再讲内核补丁和 udev 规则的配置,最后给出 librealense 的源码编译细节和 Python 接口安装方法,顺带把我在实际过程中遇到的十几个坑列成排查速查表。如果你已经装好了但深度流异常,也可以直接跳到第 7 部分。
2. 硬件体检:USB3.0识别与检测技巧(安装前必做)
2.1 USB3.0为什么是硬性前提
D435i 在 USB3.0 下可以同时输出深度流、RGB 流、双目 IR 流,并且保持帧率同步;在 USB2.0 下最多只能跑低分辨率的深度流,而且带宽瓶颈会直接影响 IMU 数据和深度图像的时间对齐。很多人把相机插到电脑前面的 USB 口,结果那是 USB2.0 的扩展口,然后就出现了“时好时坏”的诡异问题。所以装驱动之前,第一件事不是apt install,而是确认链路确实是 3.0。
关于带宽这块,我做了一个简单的计算:D435i 输出 1280x720 深度图(16bit,30fps)大约需要 55MB/s,IMU 数据单个流约 1-2MB/s,如果同时开 RGB 1080p 30fps(YUYV/压缩),整体瞬时带宽可以冲到 200MB/s 以上。USB2.0 实际有效带宽只有 35MB/s 左右,完全撑不住。这个数字不需要背,只需要记住结论:USB3.0 是 D435i 正常工作的门槛,不是可选项。
2.2 用 lsusb -t 快速判断总线速率
最简单的检测工具是系统自带的lsusb。插上相机后,在终端执行:
lsusb正常情况下能看到一行:
Bus 002 Device 004: ID 8086:0b3a Intel Corp.8086是 Intel 的厂商 ID,0b3a是 D435i 的设备 ID。这一步能确认系统认出了设备。但如果要判断速率,必须加-t参数:
lsusb -t输出里会列出总线的拓扑和设备速率。关键看下面这一行的结尾。如果是:
|__ Port 3: Dev 4, If 1, Class=Application Specific Interface, Driver=uvcvideo, 5000M最后面的5000M代表设备是以 5Gbps 的 SuperSpeed(USB3.0)速率连接的。如果看到的是480M,那就说明 D435i 当前运行在 USB2.0 模式,深度流后面的问题会接踵而来。
注意:
lsusb -t显示的5000M是理论链路速率,实际有效负载大概打六到七折。这个只要不是480M就可以接受。
2.3 用 dmesg 确定连接状态
lsusb -t只能告诉你当前速率,但无法看出设备枚举过程中是否出现过降级或供电报警。这时候要看内核日志:
dmesg | grep -i usb | tail -20如果链路是 USB3.0,会看到类似:
usb 2-1: new high-speed USB device number 4 using xhci_hcd usb 2-1: New USB device found, idVendor=8086, idProduct=0b3a usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3这里注意第一行:如果显示new high-speed USB device,指的是 USB2.0 的 HighSpeed;如果是 USB3.0,内核通常还会在后续打印new super-speed USB device。但有些主板会把 D435i 枚举为high-speed,然后在后续几行通过SuperSpeed关键字体现。所以稳妥的做法是同时观察lsusb -t和dmesg。
如果 dmesg 里出现cannot enable. Maybe the USB cable is bad?或device not accepting address,这就是典型的供电不足或线材质量差导致的枚举失败。优先换线、换口再试。
2.4 带宽算一算:D435i到底吃多少USB带宽
我实测下来的经验:D435i 在 1280x720 深度 + 640x480 彩色 + IMU 同时开启时,瞬时带宽大约在 180~220MB/s 之间浮动,这个范围内 USB3.0 有充足的余量。但如果在同一 USB 控制器上同时挂了好几台相机或者移动硬盘,总带宽压力会快速上升。
建议在安装驱动之前就规划好总线拓扑:D435i 单独占用一个 USB3.0 控制器,不要和其他大吞吐设备抢带宽。可以用lspci | grep -i usb查看主板上 USB3.0 控制器的分布,再把相机插到独立控制器对应的接口上。这条经验是从机械臂项目里摔过跟头才总结出来的——当时 D435i 和一块高速数据采集卡挂在同一控制器下,深度流时不时断连,最后拆开排查才发现是带宽争抢。
3. 装驱动前的两件小事:内核补丁与udev规则
3.1 检查内核与UVC补丁
D435i 的深度流、IR 流和 metadata 流依赖 Linux 内核的uvcvideo模块。Intel 官方在修改 UVC 驱动后,向内核上游提交过补丁,但各发行版内核合入补丁的时机不同。Ubuntu 20.04 默认内核版本是 5.4 左右,较新版的 5.8、5.11、5.15 已经把 D435i 的 metadata 端点支持合入了主线,早期 5.4 内核则可能缺失。
先看自己的内核版本:
uname -r再检查当前uvcvideo模块是否包含 metadata 相关支持。最直接的办法是运行 realsense-viewer 里的硬件信息页面,如果能正常显示深度流且没有 metadata 报错,就说明补丁没问题。但更保险的做法是,在编译 librealsense 之前直接跑一下官方脚本加载补丁:
cd ~/librealsense ./scripts/patch-uvcvideo.sh这个脚本会自动检测内核源码树,运行完后可能需要重新编译并加载uvcvideo模块。需要注意的是,如果内核版本较新,脚本会提示“补丁已包含”而跳过。我在 5.15 内核上跑这个脚本时就直接跳过了,属于正常现象,不用慌。
如果脚本报错找不到内核构建目录,还需要先安装:
sudo apt install linux-headers-$(uname -r) build-essential补丁打完以后重启系统,再执行一遍 2.2 的lsusb -t,确认设备仍然以 5000M 挂在总线上,然后再继续往下走。
3.2 配置udev规则,避免权限地狱
驱动装好了,设备也能在lsusb里看到,但在运行 realsense-viewer 的关键时刻报Permission denied,这种事我见过太多次了。原因是普通用户对 USB 设备的访问权限不够,需要在 udev 规则里给 D435i 单独授权。
官方仓库里自带了一个参考规则文件,路径是:
/lib/udev/rules.d/80-realsense.rules如果源码编译完成后没有自动安装,可以手动创建一份。这里直接给出我使用的规则内容:
sudo vim /etc/udev/rules.d/99-realsense.rules写入以下内容:
SUBSYSTEM=="usb", ATTR{idVendor}=="8086", ATTR{idProduct}=="0b3a", MODE="0666" SUBSYSTEM=="usb", ATTR{idVendor}=="8086", ATTR{idProduct}=="0b07", MODE="0666"然后重新加载 udev 规则:
sudo udevadm control --reload-rules sudo udevadm trigger这里用了MODE="0666"而不是0444,目的是让普通用户直接读写设备节点。有些教程会写成MODE="0666", GROUP="plugdev",理论上更规范,但实际上很多 Ubuntu 桌面版的plugdev组和用户组不一致,反而会出问题。对于单机开发环境,0666最省心。
重要提示:改完 udev 规则后,建议把相机拔掉重新插一次,而不是仅仅 reload 规则。某些设备需要重新枚举才会应用新的权限设置。
4. 驱动安装实操:三种方式选型与源码编译细节
4.1 三种安装方式对比与选型
librealsense 官方提供三种安装方式:注册官方 apt 仓库直接安装、下载 release 包安装、从源码编译安装。三者的区别如下:
| 方式 | 版本灵活度 | 编译时长 | 坑位数量 | 适合场景 |
|---|---|---|---|---|
| apt 官方仓库 | 低(固定版本) | 无 | 少 | 只是跑 demo、快速验证 |
| Release binary | 中 | 无 | 中(依赖匹配) | 不想编译、需要较新版本 |
| 源码编译 | 高(可控版本) | 约10~20分钟 | 多 | ROS扩展、二次开发、定制功能 |
我的建议是:如果你后面要配合 ROS 使用(比如跑 ORB-SLAM3 或者 realsense-ros),一定选源码编译。因为 apt 仓库里的版本和 realsense-ros 的版本经常对不上,编译 realsense-ros 时会因为 API 差异报错。而源码编译可以精准控制版本匹配。
4.2 源码编译librealsense:推荐路线
先安装编译基础工具和依赖:
sudo apt-get update sudo apt-get install git cmake build-essential libusb-1.0-0-dev pkg-config sudo apt-get install libgtk-3-dev libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev注意,后面这几个图形库非常关键。libglfw3-dev缺失会导致编译出的 realsense-viewer 无法显示 3D 点云,而libgtk-3-dev缺失则会导致 GUI 窗口无法正常创建。我在第一次编译时偷懒跳过了这两个包,结果 realsense-viewer 启动后黑屏,排查了半小时才发现是少了依赖。
然后克隆源码:
git clone https://github.com/IntelRealSense/librealsense.git cd librealsense切换到稳定版本(这里强烈建议不要直接用 master 分支,而是打 tag):
git checkout v2.50.0选择 v2.50.0 的主要原因是这一版对 D435i 的 IMU 支持和固件兼容性做的比较好,而且 realsense-ros 2.x 版本可以对应得上。如果你手里是更新的相机固件,再考虑 v2.54.2 或更高版本。
接着创建构建目录并开始配置:
mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release \ -DFORCE_RSUSB_BACKEND=OFF \ -DBUILD_PYTHON_BINDINGS=ON \ -DPYTHON_EXECUTABLE=/usr/bin/python3然后:
make -j$(nproc) sudo make install sudo ldconfig编译完成后,运行一下环境自带的工具检查:
realsense-viewer如果 GUI 能弹出并且出现深度画面,说明核心 SDK 已经装好了。
4.3 关键cmake参数解读
这里单独说一下-DFORCE_RSUSB_BACKEND这个参数。它有两个选择,默认是 OFF(使用 V4L2 后端,走系统 UVC 驱动),改成 ON 后,librealsense 会绕过系统内核驱动,直接通过 libusb 跟硬件通信。
对 D435i 来说,我的建议是保持 OFF。原因是:使用 V4L2 后端时,深度流和 RGB 流可以同时打开,而且 CPU 占用率更低;使用 RSUSB 后端虽然可以免于处理 UVC 补丁,但在多路流切换和 IMU 同步上会有一些兼容问题,尤其与 ROS 配合时更容易出现“同一时间只能开一个流”的怪毛病。
另一个需要留意的参数是:
-DBUILD_GRAPHICAL_EXAMPLES=ON默认就是 ON,但如果你的系统是纯服务器环境(没有显示器),建议显式设为 OFF,否则编译时会因为找不到 OpenGL 相关库而卡住。我们实验室那台无头机器人就是这样,设 OFF 之后编译效率高了很多。
5. Python接口安装:pyrealsense2怎么配最省心
如果你主要用 Python 开发,编译时已经加了-DBUILD_PYTHON_BINDINGS=ON,那么make install完成之后,Python 包会被安装到系统 Python 路径下。可以直接验证:
python3 -c "import pyrealsense2 as rs; print(rs.__version__)"如果顺利输出版本号,就说明 Python 接口 OK。但这里有一个容易踩到的坑:如果系统里有多个 Python 环境(conda、venv 等),make install默认只装到/usr/local/lib/python3.8/dist-packages,而你的 conda 环境不一定能加载到。解决办法是手动指定安装路径:
cmake .. -DPYTHON_EXECUTABLE=$(which python3) \ -DPYTHON_INCLUDE_DIR=$(python3 -c "from sysconfig import get_path; print(get_path('include'))")然后在 Python 里用一个简单的读取脚本验证深度流:
import pyrealsense2 as rs pipeline = rs.pipeline() config = rs.config() config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30) config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30) pipeline.start(config) for i in range(10): frames = pipeline.wait_for_frames() depth = frames.get_depth_frame() color = frames.get_color_frame() if depth and color: print(f"Frame {i}: depth {depth.get_width()}x{depth.get_height()}, color {color.get_width()}x{color.get_height()}") pipeline.stop()能跑通这个脚本,说明 D435i 的核心功能已经可用了。如果跑不通,多半是 USB 链路或者权限问题,回到第 2、3 章排查。
另外,Python 接口的版本必须与librealsense核心库保持一致。如果之前通过 pip 装过旧版pyrealsense2,建议先卸载:
pip3 uninstall pyrealsense2然后再用刚才编译安装的版本。我在一次项目中因为 pip 版本和源码版本不一致,出现了TypeError: __init__() got an unexpected keyword argument 'depth'这种特别误导人的报错,花了好一阵才反应过来。
6. 安装验证与深度/IMU流测试
安装完成后,建议做一次完整的实机验证。第一步是用官方枚举工具看看设备属性:
rs-enumerate-devices正常输出里能看到设备型号Intel RealSense D435I,Firmware Version一栏是当前固件版本。如果你发现固件版本过老,可以在 realsense-viewer 的 Advanced 页面里升级固件,也可以手动用:
rs-fw-update -f intel-realsense-d435i-<版本号>.bin这个升级过程最好在 USB3.0 链路上进行,不然刷写到一半断连会直接把设备变砖。我在实验室给一批 D435i 刷固件时,有台机器因为插在 USB2.0 HUB 上升级失败,设备直接进入 recovery 模式,最后靠按住设备侧面按钮重新枚举才恢复。
验证深度流时,建议用 realsense-viewer 打开三个画面:Depth、RGB、Accel/Gyro。深度画面里应该有平滑的灰度渐变,RGB 画面正常显示彩色,Accel/Gyro 数值会随着相机摆动而变化。这三个同时正常,基本可以确认 SDK 和硬件链路都没有问题。
IMU 数据是 D435i 和 D415 最大的区别。如果没有看到 IMU 数据流,可以先检查是不是固件版本太旧。我碰到过一台 D435i,深度 RGB 都正常,唯独 accel/gyro 没有任何输出,后来在 realsense-viewer 里把固件从 5.8 升级到 5.12,IMU 数据才正常出现。这属于比较隐蔽的问题,如果不用官方工具排查很难定位。
7. 常见问题与排查速查表
下面把我在多个项目里遇到的典型问题整理为速查表,按场景分类,方便快速定位。
7.1 编译/依赖类
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
cmake 报找不到libudev.h | 缺少 libudev 开发包 | sudo apt install libudev-dev |
编译时报glfw3.h: No such file | 缺少 OpenGL 窗口开发库 | sudo apt install libglfw3-dev |
make卡在 60% 左右 CPU 满载 | 正常现象,3D 图形示例编译耗时 | 耐心等待或使用-j4降低并发 |
| realsense-viewer 运行时黑屏 | 缺少 OpenGL 驱动或远程桌面会话 | 检查glxinfo,确保有硬件 GLX 支持 |
| pip 安装的 pyrealsense2 与源码版本冲突 | 混用不同安装源 | 卸载 pip 版本,使用源码编译安装 |
7.2 设备识别/权限类
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
rs-enumerate-devices输出空列表 | USB 枚举异常或线材故障 | 换线换口,查看dmesg | tail |
程序报Permission denied | udev 规则未配置 | 按 3.2 节创建99-realsense.rules |
lsusb -t显示480M | USB3.0 链路未建立 | 换 USB3.0 口、检测线材、避免经过 HUB |
| 插入后系统无任何反应 | 设备供电不足 | 使用带供电的 USB3.0 HUB 或直接插主板背板口 |
7.3 运行/性能类
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
| 深度画面卡顿、横纹 | USB 带宽不足 | 降低分辨率/帧率,关闭 RGB 流 |
| 深度流间歇性断连 | 供电波动或 USB 控制器争抢 | 独立 USB 控制器、检查电源管理 |
| 只有深度流没有 IMU | 固件过旧 | 升级到官方最新固件 |
| 双相机同时打开崩溃 | 带宽叠加超过链路余量 | 分接不同 USB 控制器 |
| 点云输出不完整 | 深度图和 RGB 对齐失败 | 开rs.align对齐,确认外参标定正常 |
以上大部分问题,我在不同电脑上至少遇到过一遍。最典型的是实验室一台 Dell 台式机,前置 USB 口全部是 2.0,插上去lsusb -t稳定显示480M,深度流在 640x480 还能勉强跑,一开 1280x720 就断连。后来换到机箱背板 USB3.0 口,问题直接消失。这种硬件链路问题,花费大量时间去 debug 软件完全是南辕北辙。
8. 最后再说几点肺腑之言
D435i 的驱动安装流程,本身并不复杂。但它牵扯到 USB 链路检测、内核模块、设备权限、SDK 编译、Python 绑定五个层面,每个环节出问题都有不同的表现方式。而大多数所谓“装不上驱动”的报错,最后排查下来都是 USB2.0 速率导致的。
我个人实际使用的经验是:把这台相机作为机器人视觉的主力传感器之后,已经养成了习惯,拿到任何新设备(包括笔记本、NUC、嵌入式板卡)的第一时间不是装 librealsense,而是先lsusb -t看 USB 拓扑。这个习惯帮我省了无数个排查时间。
最后再分享一个小技巧:在 Ubuntu 20.04 下如果长期不使用 D435i,建议把 USB 自动暂停功能关掉,防止系统进入省电状态后 USB 设备断连。可以通过添加内核参数usbcore.autosuspend=-1或者用udev规则来关闭该接口的自动挂起。这一步虽然不影响安装,但在跑长时间采集任务时能避免数据丢失。