文章目录
概要
一份无人机初学者学习日志
Windows + WSL2 + Docker + ROS 摄像头穿透全流程指南。
适用场景
适用场景: Windows 10/11 宿主机 -> WSL2 (Ubuntu) -> Docker 容器 -> ROS Noetic 核心原理: 利用 usbipd-win 将 Windows 的 USB 信号通过 TCP/IP 桥接到 WSL,再通过 Docker 的 --device 参数映射给容器。
整体流程
第一阶段:环境准备 (只需执行一次)
第二阶段:连接摄像头 (每次重启电脑后需执行)
第三阶段:启动 Docker 容器
第四阶段:ROS 节点运行与调试
技术细节
一、环境准备 (只需执行一次)
1、Windows 端:安装桥接工具
在 Windows 上我们需要一个“搬运工”来把 USB 信号发出去。 打开 PowerShell (管理员):
winget install --interactive --exact dorssel.usbipd-win
安装完成后,建议重启一次电脑。
2、WSL (Ubuntu) 端:安装接收驱动
这是最关键的一步! 很多时候出现乱码或连接失败都是因为这一步没做。 打开你的 Ubuntu 终端(需要先下载ubuntu):
sudo apt update
sudo apt install linux-tools-virtual hwdata -y
sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/*/usbip 20
二、连接摄像头 (每次重启电脑后需执行)
电脑重启后,USB 设备默认会回到 Windows 手里,你需要手动把它“插”给 WSL。
1、物理连接与重置
为了防止设备处于“错误状态 (Error State)”,建议:是外接摄像头的情况下,拔掉摄像头 USB后等待三秒然后重新插入;
是笔记本电脑自带摄像头的情况下,打开设备管理器,关闭摄像头设备后等待三秒再打开。
2、系统内部挂载
在 PowerShell 管理员模式下,将摄像头绑定与挂载在WSL2下,也即ubuntu系统下。
# 1. 查看设备列表,找到你的摄像头 BUSID (例如 6-4)
usbipd list
# 2. 绑定设备 (如果之前绑过可以跳过,报warning ‘force’ 则加上 --force)
usbipd bind --busid <你的BUSID> --force
# 3. 连接到 Ubuntu (此时必须保持 Ubuntu 终端是开着的!)
usbipd attach --wsl Ubuntu --busid <你的BUSID>
3. 验证
在Ubuntu 终端下执行下列指令:
lsusb
ls -l /dev/video0
如果看到输出为: /dev/video0 说明物理链路已打通!
三、启动 Docker 容器
此时 Ubuntu 已经拥有了摄像头,我们需要把它传递给 Docker。
我的模板是:
docker run -it \
--name <容器名称> \
--net=host \
--device=/dev/video0:/dev/video0 \
-v D:\UAV_Planning_Project:/home <镜像名>
/bin/bash
--device: 核心参数,直通硬件;
--net=host: 让容器共享宿主机网络,方便 ROS 通信。关于这里笔者在容器内部.bashrc文件中对于ip地址同时做了适应性改动,暂时没深究是哪边改动优先级更高;
--privileged: 给予容器更高权限,防止驱动读写报错。
四、ROS 节点运行与调试
到这里链路打通就没什么问题了,理论上直接执行调用apriltag的测试launch文件即可测试ros下对tag的目标检测,但是笔者出现了其他问题,具体是:进入容器后,由于虚拟化带宽限制,直接运行报错 select timeout。可以使用 MJPEG 格式。
1. rosrun命令行快速验证
# 强制指定 mjpeg 格式和分辨率,防止带宽堵塞
rosrun usb_cam usb_cam_node \
_video_device:="/dev/video0" \
_pixel_format:="mjpeg" \
_image_width:=640 \
_image_height:=480 \
_framerate:=30
2. Launch 文件编写
<launch>
<node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
<param name="video_device" value="/dev/video0" />
<param name="image_width" value="640" />
<param name="image_height" value="480" />
<param name="pixel_format" value="mjpeg" />
<param name="framerate" value="30" />
<param name="camera_frame_id" value="usb_cam" />
<param name="io_method" value="mmap"/>
</node>
<arg name="node_namespace" default="apriltag_ros_continuous_node" />
<arg name="camera_name" default="/usb_cam" />
<arg name="image_topic" default="image_raw" />
<node pkg="apriltag_ros" type="apriltag_ros_continuous_node" name="$(arg node_namespace)" clear_params="true" output="screen" >
<rosparam command="load" file="$(find classicalplanning)/config/settings.yaml" />
<rosparam command="load" file="$(find classicalplanning)/config/tags.yaml" />
<remap from="image_rect" to="$(arg camera_name)/$(arg image_topic)" />
<remap from="camera_info" to="$(arg camera_name)/camera_info" />
<param name="publish_tag_detections_image" type="bool" value="true" />
</node>
<node name="tag_view" pkg="image_view" type="image_view" respawn="false" output="screen">
<remap from="image" to="/tag_detections_image" />
<param name="autosize" value="true" />
</node>
</launch>
这里注意两点:
1、settings.yaml和tags.yaml需要自行制定,主要是说明你要检测的tag的类型和tag的基本属性。
2、笔者在工作空间的src下gitclone了apriltag的源码及其依赖包也编译通过了,同时也安装了系统版:
# 1. AprilTag 核心算法库 (C库)
sudo apt-get install ros-noetic-apriltag
# 2. AprilTag 的 ROS 封装 (节点和Launch文件)
sudo apt-get install ros-noetic-apriltag-ros
此时,可以通过roscd apriltag_ros命令来探究到底使用了哪个版本。一般情况下因为Workspace Overlaying,在source之后是使用源码版。
做完上面所有的流程后,即可实现apriltag识别!

常见问题小结
1、Device in error state
原因:摄像头驱动卡死,或 NoMachine 等软件干扰
解决方案:
- 物理拔插摄像头。
- 运行
usbipd unbind -b <ID>。 - 卸载 NoMachine (不推荐)或删注册表 UpperFilters(推荐)。
2、select timeout
原因:YUYV 格式数据量太大,虚拟USB传不过来
解决方案:改用 mjpeg 格式,或降低分辨率到 320x240
后续会加入嵌套标识识别以及海面场景下红外短波相机识别学习过程。

2103

被折叠的 条评论
为什么被折叠?



