ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Astra Pro深度相机接入ROS 2 Humble:远程可视化与距离检测实战

Astra Pro深度相机接入ROS 2 Humble:远程可视化与距离检测实战 做这个项目之前先说说我为什么盯上这块组合。Astra Pro 这款深度相机在国产设备里算是非常能打的价格比进口的 RealSense 低一大截深度数据在室内场景下的表现也很稳。而 ROS 2尤其是 Humble 版本已经成了机器人领域事实上的标准框架微服务和分布式通信的设计让它在多机协同场景里特别吃香。我最初的需求很简单手里的机器人平台需要视觉感知能力但工控机不在身边得在另一台电脑上实时看到深度画面同时还要能直接读取前方障碍物的距离数值。这就把两个核心问题摆上了台面——远程可视化怎么做才不卡顿、距离检测怎么算才够准。这篇文章就把我完整跑通这套流程的经验写下来从驱动安装到最后跑通距离检测全程带代码和避坑记录适合手里正好有 Astra Pro、想在 ROS 2 里快速做出视觉方案的工程师参考。1. 项目概述与整体思路拆解1.1 项目目标与核心需求这个项目的目标拆开了看其实就两件事。第一件事是把 Astra Pro 深度相机接入 ROS 2 系统让相机的深度数据和彩色图像能像普通传感器消息一样被发布出来方便后续所有节点订阅使用。第二件事是在这个基础上实现两个应用层功能一个是远程可视化也就是不插显示器、不坐在工控机面前通过网络在另一台电脑上看到相机画面另一个是距离检测直接从深度图像里读出目标的距离信息输出一个实时数值。如果把整个项目当作一个传感器数据链路来看就是 相机采集 → 驱动节点发布话题 → 可视化与距离检测节点消费话题 这三个环节。看起来不复杂但实际跑起来就会发现每一个环节都有隐藏的坑比如驱动编译不过、图像全黑、远程连接不上、深度值跳变等。1.2 技术选型与硬件选择选 Astra Pro 的核心原因就是性价比。它采用的是主动双目三角测距方案直接通过投射不可见的红外结构光生成深度信息室内无阳光干扰的环境中深度图的质量相当能打。当时对比过 Orbbec 另外几款包括 Femto Mega、Dabai DCAM 系列最终还是选了 Astra Pro 作为主力测试设备。不只是因为它出货量大、社区资料丰富更重要的是它在 ROS 2 下的驱动支持已经相当成熟踩坑的几率可控。至于 ROS 2 版本我选了 Humble。Humble 是长期支持版本到 2027 年都有官方维护比 Foxy 多了不少稳定性修复而且生态下的工具链和第三方驱动大多优先适配 Humble。如果你同时玩 Micro-ROS在 Humble 上通过 micro_ros_agent 连接 ESP32 之类的微控制器也非常方便整个技术栈可以打通。1.3 系统架构与数据流设计Astra Pro Depth Camera | | USB 2.0 / USB 3.0 v Driver Node (astra_camera_ros2) | | /camera/depth/image_raw (深度图) | /camera/rgb/image_raw (彩色图) | /camera/depth/points (点云) v ----------- | 可视化端 | Foxglove / rviz2 ----------- | v ----------- | 距离检测 | 订阅深度图读取中心深度值 ------------整个链路的关键是理清消息之间的依赖关系。驱动节点负责把相机的原始数据包装成标准 ROS 2 消息可视化端和距离检测节点分别从不同话题拉取数据。1.4 为什么选 ROS 2 而不是 ROS 1这里必须多说一句。ROS 1 确实积累了大量资料但它的通信中枢 Master 节点间点对点连接的模式在多机协同、动态拓扑场景下天然有瓶颈。ROS 2 用 DDS 作为底层通信协议节点之间直接收发数据不需要中央调度网络中断后能自动恢复。体现在这个项目里就是远程可视化时ROS 2 的分布式发现机制让它天然适合跨机器通信。你不需要像 ROS 1 那样担心 Master 挂了所有节点就失联。这也是我选择直接一步到位玩 ROS 2 的原因。2. 环境准备与硬件连接2.1 硬件清单与连接方式先列一下我用的硬件环境清单硬件型号备注深度相机Astra Pro (Orbbec)支持深度彩色点云主机A采集端工控机 / PCUbuntu 22.04连接相机跑驱动主机B可视化端PC / 笔记本Ubuntu 22.04远程查看跑 FoxgloveUSB线USB 2.0/3.0 数据线长度不宜超过1.5米相机连接看似简单插上去就能被识别但这里有个小坑强烈建议把相机插到主机的 USB 3.0 接口上而不是 USB 2.0。虽然 Astra Pro 官标 USB 2.0 也能跑但深度图彩色图同时高帧率传输时USB 2.0 的带宽容易成为瓶颈表现为图像卡顿、帧率上不去甚至偶尔掉线。实测 USB 2.0 下深度图 640x48030fps 就会偶尔丢帧换到 USB 3.0 之后就很稳定。2.2 Ubuntu 与 ROS 2 Humble 环境安装整个项目的基础系统我用的是 Ubuntu 22.04 ROS 2 Humble。如果还没装 ROS 2先按官方文档走一遍这里只提几个容易忽略的点# 设置软件源 sudo apt update sudo apt install curl gnupg lsb-release sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release echo $UBUNTU_CODENAME) main | sudo tee /etc/apt/sources.list.d/ros2.list /dev/null sudo apt update sudo apt install ros-humble-desktop python3-argcomplete装完 ros-humble-desktop 基本就把工具链带全了。记得source /opt/ros/humble/setup.bash加入~/.bashrc后面开终端不用每次手动 source。注意ROS 2 Humble 默认要求的 Ubuntu 版本是 22.04如果你还在用 20.04建议直接升级系统或者用 Docker 跑 Humble避免依赖版本冲突带来一堆不必要的问题。2.3 Astra Pro 驱动安装Astra Pro 在 ROS 2 下有两种主流驱动方案。第一种是社区维护的astra_camera_ros2支持大多数 Orbbec 的 Astra 系列相机第二种是官方更通用的OrbbecSDK_ROS2底层基于 OrbbecSDK 封装。我建议直接上官方 SDK 方案社区版驱动在 Humble 上偶尔会有编译问题官方出门证件更全。以OrbbecSDK_ROS2为例安装步骤是# 克隆官方SDK和ROS2 wrapper git clone https://github.com/orbbec/OrbbecSDK_ROS2.git cd OrbbecSDK_ROS2 # 如果有依赖的第三方子模块拉取一下 git submodule update --init --recursive # 编译 rosdep install --from-paths src --ignore-src -r -y colcon build --symlink-install source install/setup.bash如果编译过程中遇到找不到依赖的问题大概率是缺ros-humble-libg2o之类的不常用包直接sudo apt install对应名称即可。编译完成后插上相机运行ros2 launch orbbec_camera OrbbecAstraPro.launch.py如果一切正常你会看到相机节点启动的日志并在话题列表里看到/camera/depth/image_raw和/camera/rgb/image_raw。3. 远程可视化——从本机到跨机器3.1 本机可视化验证驱动跑通之后先在本机验证图像数据是否正常。最简单的方式是用 rqt_image_viewros2 run rqt_image_view rqt_image_view在界面左上角下拉选择/camera/rgb/image_raw或/camera/depth/image_raw如果能看到画面说明数据链路已经打通。这里要提醒一句深度图在 rqt_image_view 里默认显示的是 16 位灰度图看起来偏暗是正常现象不代表数据有问题。3.2 Foxglove Studio —— 远程可视化的最佳选择本机验证通过后下一步就是远程。远程可视化的方案我试过几个跑 rviz2 加 SSH X11 转发、用 Web 端 Foxglove Studio、直接用 VNC 连工控机桌面。实测下来最靠谱、最优雅的还是 Foxglove Studio。Foxglove 是个专业的机器人可视化工具支持直接连接 ROS 2 的 DDS 网络也可以在服务端用 Foxglove Bridge 中转。核心优势是浏览器端渲染本机只要装个 Chrome 或者 Edge 就能看不需要在采集端安任何 GUI 软件。远程连接的配置分两种场景场景一可视化端和采集端在同一个局域网这种情况下最简单只要保证两端的 ROS 2 使用相同的ROS_DOMAIN_ID并且网络互通Foxglove 就可以直接发现话题。# 采集端 export ROS_DOMAIN_ID42 ros2 launch orbbec_camera OrbbecAstraPro.launch.py # 可视化端 export ROS_DOMAIN_ID42 # 打开 Foxglove Studio添加 ROS 2 连接Foxglove 打开后点击左侧Data Source→Open connection→Rosbridge或直接选择ROS 2连接方式它会自动发现当前域里的话题。场景二跨网段 / 不在同一局域网如果主机不在同一局域网就需要借助代理转发。常见做法是用 Foxglove Bridge 或者ros2 daemon加ROS_DISCOVERY_SERVER配置。我在实际项目中用了 Foxglove Bridge因为部署简单只需要在采集端跑一个 bridge 服务可视化端通过浏览器连接这个服务的端口。# 采集端跑 foxglove bridge pip install foxglove-bridge foxglove-bridge --port 8765然后可视化端 Foxglove 里选择Rosbridge地址填采集端的 IP:8765 即可。这种方式不要求两端 ROS 域一致甚至可视化端的电脑不需要装 ROS 2浏览器直接看。注意远程看深度图时一定要保证网络带宽。深度图 640x48030fps 的原始消息量很大Wi-Fi 环境容易卡。建议在采集端做一次分辨率缩放和帧率限制把深度图降到 320x24015fps 再发布远程体验会流畅很多。3.3 rviz2 远程查看的备选方案如果你还是想在 rviz2 里看也不复杂前提是两端 ROS 2 能正常通信。启动 rviz2 后添加一个Image显示话题选/camera/rgb/image_raw深度图同理。结合项目里遇到的实际情况我最终长期是弃用 rviz2 远程看图的原因是它每次启动都要手动添加显示主题而且插件加载慢、内存占用高。Foxglove 的布局可以保存成配置文件下次打开直接恢复画面效率高出一大截。4. 距离检测——从深度图到实际距离4.1 深度图像素与物理距离的关系Astra Pro 发布的深度图每个像素值代表该点到相机平面的距离单位默认是毫米。所以拿到深度图之后第一时间要确认编码格式。在 ROS 2 里sensor_msgs/Image的encoding字段通常是16UC1意思是每个像素占 16 位、单通道、无符号整形值域 0~65535对应的物理单位就是毫米。你可能要问为什么不直接用点云算距离点云的计算开销比直接读深度图大而且对带宽要求高。距离检测只需要关心某个像素位置的深度值直接从深度图读取最快最省资源。4.2 距离检测节点的 Python 实现我写了一个轻量级的距离检测节点核心逻辑是订阅深度图话题提取图像中心像素的深度值再经过滤波后发布。代码不长贴上完整的可运行版本#!/usr/bin/env python3 import rclpy from rclpy.node import Node from sensor_msgs.msg import Image import numpy as np from std_msgs.msg import Float32 class DistanceDetector(Node): def __init__(self): super().__init__(distance_detector) self.sub self.create_subscription( Image, /camera/depth/image_raw, self.depth_callback, 10 ) self.pub self.create_publisher(Float32, /distance/center, 10) # 保存最近20帧深度值用于中值滤波 self.depth_history [] def depth_callback(self, msg): # 根据编码格式转换 if msg.encoding 16UC1: depth np.frombuffer(msg.data, dtypenp.uint16).reshape(msg.height, msg.width) else: self.get_logger().warn(fUnsupported encoding: {msg.encoding}) return # 读取图像中心像素 h, w depth.shape center_depth depth[h // 2, w // 2] # 无效值过滤 if center_depth 0: self.get_logger().warn(Invalid depth at center (0 or NaN)) return # 中值滤波消除随机跳变 self.depth_history.append(center_depth) if len(self.depth_history) 20: self.depth_history.pop(0) filtered int(np.median(self.depth_history)) # 发布单位从毫米转米便于应用层使用 msg_out Float32() msg_out.data filtered / 1000.0 self.pub.publish(msg_out) # 同时打印到日志 self.get_logger().info(fCenter distance: {msg_out.data:.3f} m) def main(argsNone): rclpy.init(argsargs) node DistanceDetector() try: rclpy.spin(node) except KeyboardInterrupt: pass finally: node.destroy_node() rclpy.shutdown() if __name__ __main__: main()把这几个点拆开讲清楚第一深度单位换算。驱动发布的消息单位是毫米直接给应用层用不直观我在发布前统一换成米这样 Node-RED、日志平台、上位机都不需要再做二次换算。第二无效值处理。深度相机在目标太近、太远或者反光材质上会返回 0 或 65535 之类的异常值。代码要主动过滤不然一个脏数据就能让下游逻辑傻掉。第三中值滤波为什么用 20 帧。单帧深度值在边缘场景下可能会上下抖几十毫米中值滤波取的是历史数据的中位数能把毛刺削掉同时又不会引入延迟感。窗口大小按实际帧率调节30fps 下 20 帧对应约 0.67 秒的响应延迟在静止或缓慢移动场景下已经足够丝滑。4.3 扩展到指定区域的最近距离检测中心点检测只是一个起点很多项目实际需要的是“前方某个范围里最近的障碍物到底有多远”。这个扩展也很直接取中心区域的一小块矩形比如宽 100 像素、高 80 像素的 roi在这个区域内取有效深度值的最小值。# 在depth_callback中扩展 roi depth[h//2-40:h//240, w//2-50:w//250] roi_valid roi[roi 0] # 过滤0值 if roi_valid.size 0: self.get_logger().warn(No valid depth in ROI) return nearest int(np.min(roi_valid))为什么取最小值而不是平均值因为对避障来说最近的物体才是真正有威胁的障碍物平均值会被背景拉远造成“明明快撞上了但读数还能接受”的错觉。这也是我实际测试时踩过的坑一开始求区域均值后来发现墙边的椅子腿根本检测不出来改成取最小值后就正常了。4.4 深度图对齐彩色图如果还需要把深度信息叠加到彩色图上显示就要考虑对齐问题。Astra Pro 的深度传感器和彩色摄像头存在物理位置偏差直接用原始深度图和彩色图逐像素叠加是对不上的。好在 OrbbecSDK 提供了硬件层面的对齐功能。在 launch 文件里可以开启对齐参数把深度图重投影到彩色图坐标系下这样深度图和彩色图的像素坐标一一对应。开启对齐后深度图的分辨率会以彩色图为准处理时注意别把坐标系搞混。5. 常见问题与排查技巧实录5.1 驱动编译失败这个我在不同电脑上遇到不下三次。典型报错是找不到orbbec::Sdk头文件或者链接时找不到OrbbecSDK库。排查思路固定三步第一步确认子模块有没有拉全很多报错都是git clone时没加--recursive第二步确认 rosdep install 执行过第三方依赖缺失是最常见的编译失败原因第三步如果还不行手动把OrbbecSDK_ROS2/lib下的.so库路径加到环境变量export LD_LIBRARY_PATH$LD_LIBRARY_PATH:/path/to/OrbbecSDK_ROS2/lib5.2 图像全黑或者全是噪点装好驱动后如果看到深度图全黑先不要怀疑相机坏大概率是两个原因一是距离太近Astra Pro 有效工作距离约 0.3~6 米太近的地方深度值全是无效值二是相机驱动版本和硬件版本不匹配。如果你用的是社区版的astra_camera_ros2跑新的 Astra Pro 硬件就会出现深度图异常。解决办法是换官方OrbbecSDK_ROS2。另外把相机对着灰白色的均匀背景测试比如白墙深度值会稳定平滑这一步能快速判断相机本身有没有问题。5.3 远程可视化连不上连不上多半是 ROS_DOMAIN_ID 不一致或者局域网防火墙拦截了 DDS 的组播包。ROS 2 的 DDS 默认使用多播进行节点发现如果主机不在同一个广播域或者路由器禁止了多播就发现不了对方的话题。排查时先看采集端的话题列表可视化端用ros2 topic list是否能同步看到。如果看不到检查防火墙# 可视化端临时关闭防火墙测试 sudo ufw disable如果能看到了再把防火墙加白名单规则放行 DDS 相关的 UDP 端口段。ROS 2 默认的 DDS 端口在 7400~7500 附近具体端口可以参考 Fast DDS 文档。5.4 帧率上不去、延迟大远程看图像卡顿这件事除了网络带宽还有一个容易被忽略的参数就是 QoS。ROS 2 的话题在发布者和订阅者之间默认 QoS 是RELIABLE也就是每个数据包都要确认送达这对强实时性图像流来说反而是负担一个重传就把管道堵住了。图像类话题建议改成BEST_EFFORT策略降低可靠性的要求但换来低延迟from rclpy.qos import qos_profile_sensor_data self.sub self.create_subscription( Image, /camera/depth/image_raw, self.depth_callback, qos_profile_sensor_data )5.5 深度值跳变如果中心距离读数一直抖先试代码里的中值滤波还不行就在 ROS 2 参数层面调深度的最小和最大可用范围把髒数据范围缩小。OrbbecSDK 的 launch 文件里有depth_max_distance_m和depth_min_distance_m参数把有效范围限制到实际需要的区间无效值比例会大幅下降。6. 最后补充几个心得体会做这个项目前后花了大概两天时间踩坑主要集中在驱动安装和远程连接阶段真正写距离检测代码反而很快。这里有个经验任何深度相机的项目第一步永远是先跑通 Topic 数据流不管是 rqt 还是命令行ros2 topic echo看一眼消息结构再开始写上层逻辑能省一半调试时间。另外Astra Pro 虽然便宜但它的深度数据在强光直射和黑色吸光物体上确实会有短板这是主动双目方案的天生限制。如果你的场景是户外或者高反光环境老老实实考虑 LiDAR 或者更换其他技术路线的深度相机。我在实际使用中还有一个习惯就是把距离检测节点输出的数值额外接到一个轻量级的日志平台或者 WebSocket 服务上这样不仅机器人上能看到距离手机浏览器也能实时看到后面接语音播报、远程报警都很方便。这次的方案整个链路就是这样照着跑通后你可以继续扩展的目标还有很多比如把深度数据接入 Nav2 的避障插件或者用 Micro-ROS 把检测结果同步到 ESP32 做硬件响应那都是后续的事了。
返回列表