ARTICLE DETAIL

资讯详情

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

ROS 2 Humble下Astra Pro深度相机实战:驱动安装到距离检测

ROS 2 Humble下Astra Pro深度相机实战:驱动安装到距离检测 上周调一台巡检机器人我把Astra Pro深度相机接到了ROS 2 Humble上做近距离避障。机器人在楼道里来回跑了半天我坐在电脑前盯着RViz2里的深度图一边看数值一边头疼——距离测量的抖动比我预想的大得多。群里正好有人问“Astra Pro在ROS 2里能不能出图”我就知道这个话题值得系统写一篇。这篇文章里面所有操作都基于我实际跑过的环境Ubuntu 22.04 ROS 2 Humble Astra Pro我手上有S10386这个型号内容包括从装驱动、看到深度图、写距离检测节点再到局域网远程可视化最后把实战中踩过的坑全部摊开来讲。如果你也打算把这台十几年前的经典结构光相机重新用在ROS 2项目里这篇文章能帮你少走至少一个下午的弯路。1. 为什么是Astra Pro ROS 2 Humble这个组合解决了什么问题1.1 从一次现场调试说起那天我调试的是一台底盘巡检机器人轮子上已经带了超声波和激光雷达但激光雷达装的位置偏低遇到桌面高度的小障碍物比如椅子腿、快递盒、电线拖板经常扫不到。需要补一个视觉传感器最直接的方案就是加深度相机。我手上正好有一台Astra Pro。这相机当年是跟着Orbbec第一代开发套件买的一直闲置在柜子里。现在翻出来发现问题是网上大部分教程还在教ROS 1时代的astra_camera、rgbd_launch、OpenNI2而我的开发环境已经全部迁到ROS 2 Humble Ubuntu 22.04了。旧驱动在新系统上编译不过ROS 1的包也没法直接装。所以我只能硬着头皮走ROS 2原生的驱动路线结果发现官方生态其实比我想象中好——只要找对仓库和分支。1.2 Astra Pro的硬件底子决定了它的适用边界Astra Pro采用的是结构光方案通过投射不可见的红外光斑图案再由红外摄像头读取图案变形来解算深度。从硬件指标来看深度分辨率最高1280x1024帧率最高30fps测量范围标称0.6米到8米近距离0.35米附近勉强可用但精度明显下降视场角大约水平58度、垂直45度左右带一颗RGB摄像头分辨率1280x960可以用来做人脸检测、颜色识别供电和数据传输走USB 3.0线材对信号稳定性影响非常大这套参数放到今天当然不算惊艳但做室内机器人的近距离避障、桌面物体检测、人员跟随完全够用。我实际测试下来1米到2.5米范围内的深度数据表现最稳定这个区间恰好是移动机器人最常见的感知范围。你要是拿它去做户外远距离测绘那确实强人所难。1.3 生态现状ROS 2时代为什么值得重新用它很多人以为Astra Pro是“老掉牙的设备”在ROS 2里肯定没人维护。实际上Orbbec官方在GitHub上有维护orbbec_ros和orbbec_camera两个仓库其中orbbec_camera就是专门对接ROS 2的支持Foxy、Galactic、Humble等多个发行版。如果你的项目系统是Ubuntu 22.04直接选Humble分支就行。选Astra Pro还有一个务实原因市面上的二手价格非常便宜而且货源充足。对学生党、个人开发者、搞毕设的人来说用几十块钱的深度相机完成避障、抓取、跟随等视觉功能的前期验证性价比确实高。在和激光雷达配合使用的时候它补盲区的价值很明显。2. 从装驱动到相机出图前半小时做的事2.1 先搞清楚该装哪套驱动别一上来就编译在ROS 2里让Astra Pro工作你大概率会碰到两个名字很像的包。astra_camera这是比较老的驱动最早面向ROS 1后来有人维护了ROS 2版本但接口设计和话题名都比较旧。orbbec_cameraOrbbec官方专门为ROS 2维护的新驱动支持UVC协议的Orbbec相机包括Astra Pro、Astra Plus、Dabai系列等。直接选orbbec_camera不要纠结。astra_camera的文档不完整而且有些分支的API跟新版本不兼容你就算编译过了也容易在运行时出各种莫名其妙的段错误。2.2 编译安装orbbec_camera的完整步骤我用的环境是Ubuntu 22.04 ROS 2 Humble Python 3.10如果你是别的主流发行版流程基本一样只是有几个依赖包的版本号可能略不同。先安装编译工具链和依赖sudo apt install -y ros-humble-camera-info-manager ros-humble-cv-bridge ros-humble-image-transport sudo apt install -y libgflags-dev libgoogle-glog-dev libusb-1.0-0-dev然后创建工作空间并克隆代码mkdir -p ~/ros2_ws/src cd ~/ros2_ws/src git clone -b ros2 https://github.com/orbbec/OrbbecSDK_ROS2.git注意这里的分支名我之前按默认分支克隆下来编译的时候依赖的SDK版本和ROS 2接口不匹配报了一堆错。后来换成ros2分支才顺利通过。编译cd ~/ros2_ws colcon build --symlink-install source install/setup.bash编译过程大概几分钟取决于机器性能。如果报错缺少某个包一般是依赖没装全用rosdep install --from-paths src --ignore-src -r -y可以自动补依赖。2.3 udev规则这一步不做后面全程白忙把相机通过USB 3.0接到电脑上先看系统有没有识别到设备lsusb正常情况下会看到一个2bc5开头的Vendor IDOrbbec的USB Vendor ID比如2bc5:0403或者类似。某些相机型号在旧固件下显示为8087的Intel ID如果你拿到的机器是这种情况需要先升级固件。接下来配置udev规则否则非root用户启动节点时会报权限错误。orbbec_camera仓库自带了脚本直接运行cd ~/ros2_ws/src/OrbbecSDK_ROS2/scripts bash install_udev_rules.sh sudo udevadm control --reload sudo udevadm trigger插拔一次USB线让权限规则生效。2.4 启动节点验证相机出图启动相机节点ros2 launch orbbec_camera orbbec_camera.launch.py启动之后如果一切正常终端里会打印相机型号、固件版本、序列号这些信息。这时候开另一个终端查看话题列表ros2 topic list你会看到类似这样的话题/camera/color/image_raw/camera/depth/image_raw/camera/depth/points/camera/extrinsic/depth_to_color/camera/color/camera_info到这里相机已经跑起来了。整个过程顺利的话确实五六分钟能搞定。但别高兴太早后边的可视化、距离检测、远程传输才是真正的重头戏。3. RViz2里看到深度图图像话题与点云显示3.1 用RViz2添加深度图像相机节点跑通以后并不能立刻在屏幕上看到画面你需要用RViz2来订阅话题。ros2 run rviz2 rviz2打开RViz2后在左侧Displays面板点击Add选择By topic找到/camera/depth/image_raw话题添加Image display默认情况下深度图会显示成灰度图——因为深度值是毫米量级的整数直接映射到图像灰度后近距离物体会显得很亮远距离物体几乎黑成一片看起来就像一张“花屏”图。这不是设备坏了而是显示方式不对。正确的做法是在Image display的Color Scheme下拉菜单里把Overlay改成Black to Red映射或者Turbo如果版本支持。改完之后近距离是红色远距离逐渐变成蓝色色彩层次立刻就出来了画面看起来才真正“像一张深度图”。3.2 点云显示Fixed Frame的坑除了看图像深度相机最大的价值在于能直接输出三维点云。在RViz2里添加PointCloud2 display选择/camera/depth/points话题然后你会遇到一个经典问题——画面里什么都没有或者点云位置飘到不知道哪里去了。原因几乎都是Fixed Frame设置不对。RViz2里所有点云数据的坐标都是相对于某个坐标系来渲染的你需要在左上角Fixed Frame下拉框里选择camera_depth_frame或者camera_link。选错坐标系比如保持默认的map而你的机器人又没有发布从map到相机坐标系的TF变换点云自然显示不出来。我自己喜欢用camera_depth_frame作为Fixed Frame理由是它对调试最直观——你看到的点云就是相机自己视角下的三维信息不会因为机器人的TF树没建全而出现奇怪偏移。3.3 RGB和深度图的对齐问题有一类很常见的需求把RGB图像和深度图像逐像素对齐这样点击画面中某个物体就能同时知道它的颜色和距离。Astra Pro的深度图是红外相机拍摄的它和RGB相机的视野范围不完全重叠两个相机在硬件上也有物理间距所以默认情况下颜色图和深度图是不对齐的。如果你需要做颜色距离的融合可以在orbbec_camera的launch参数里打开对齐开关ros2 launch orbbec_camera orbbec_camera.launch.py depth_registration:true打开之后系统会用内部的标定参数把深度图对齐到RGB坐标系输出一个/camera/depth/image_raw直接对应RGB像素位置的深度流。这个功能开启后会额外消耗CPU如果只是做距离检测可以不开。4. 距离检测把深度值从像素变成厘米4.1 深度图的编码方式16UC1与毫米单位深度图每个像素存储的并不是“距离值”而是一个表示深度的整数值单位是毫米编码格式为16UC116位无符号单通道。所以你在图像里看到的某个像素值为1234意味着该点在相机前方1.234米处。这个编码方式很多人第一次接触时会搞错我见过有人直接用numpy把深度图除以255当灰度图处理导致所有距离都变成几十厘米。正确的是这样depth_image cv2.imread(depth.png, cv2.IMREAD_UNCHANGED) distance_mm depth_image[y, x] distance_m distance_mm / 1000.0在ROS 2里订阅深度话题时拿到的数据是以nav_msgs/msg/OccupancyGrid的变体不对是sensor_msgs/msg/Image里的data字段需要先用cv_bridge转成numpy数组再提取像素值。4.2 写一个简单的距离检测节点下面这个节点订阅深度图实时计算图像中心区域的平均距离并以Float64消息发布出去方便其他节点接收。完整流程是订阅/camera/depth/image_raw用cv_bridge转成numpy数组取中心区域像素均值。import rclpy import message_filters import numpy as np from rclpy.node import Node from std_msgs.msg import Float64 from sensor_msgs.msg import Image from cv_bridge import CvBridge class DistanceDetector(Node): def __init__(self): super().__init__(distance_detector) self.bridge CvBridge() self.publisher self.create_publisher(Float64, distance_to_center, 10) self.subscription self.create_subscription( Image, /camera/depth/image_raw, self.depth_callback, 10 ) def depth_callback(self, msg): depth self.bridge.imgmsg_to_cv2(msg, desired_encodingpassthrough) h, w depth.shape[:2] cx, cy w // 2, h // 2 region depth[cy-20:cy20, cx-20:cx20] # 深度有效值范围0表示无效测量 valid region[region 0].astype(np.float32) if valid.size 0: return distance_m np.median(valid) / 1000.0 self.publisher.publish(Float64(datadistance_m)) self.get_logger().info(fDistance: {distance_m:.3f} m) def main(argsNone): rclpy.init(argsargs) node DistanceDetector() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ __main__: main()这段代码里有几个关键选择用区域中位数而不是平均值。深度图里偶尔会出现孤立的异常点个别像素跳变到几十米外平均数会被拉偏中位数则能很好地抵抗这种噪声。先过滤掉值为0的像素。Astra Pro在检测不到有效反射时深度值为0直接参与计算会把距离拉近很多。取图像中心40x40的小区域。对固定安装的机器人而言中心区域通常对应正前方取区域平均比单点更稳。4.3 多点测距与区域测距换成谁在测如果你要检测的不只是中心点而是整个图片中距离最近的物体比如避障场景可以用numpy一次性处理整幅深度图depth self.bridge.imgmsg_to_cv2(msg, desired_encodingpassthrough) valid_depth depth[depth 0] if valid_depth.size 0: return min_distance np.min(valid_depth) / 1000.0这样得到的就是视野范围内最近的物体距离。注意直接用np.min会比较敏感因为单个坏点可能造成误报所以最好先做个中值滤波或者形态学开运算把孤立噪点清掉。关于距离检测我想补充一个非常容易踩的认知误区深度相机的测距范围不是均匀可靠的。Astra Pro标称0.6到8米实际测试下来0.3到0.6米范围内深度值虽然能出来但噪声明显增大误差可能抓到几十毫米级别超过4米后深度值开始变得稀疏很多像素直接是0。做避障阈值判断时需要针对你的实际安装场景重新标定一下“可用范围”别直接按说明书上的标称值来做逻辑。5. 远程可视化人不用跟着机器人跑5.1 ROS 2分布式通信是怎么让远程可视化成立的很多人第一次接触ROS 2远程可视化时会有一个误解以为必须在机器人本体上装远程桌面然后人远程连上去看画面。其实ROS 2本身就是分布式的DDSData Distribution Service的通信模型决定了节点之间是peer-to-peer的只要两台机器在同一个网络里能互相发现对方A节点发布的话题数据可以直接传到B节点的RViz2里显示。所以思路很简单机器人本体上运行相机节点和距离检测节点你在另一台电脑上运行RViz2订阅话题就能直接看到机器人的“眼睛”看到的一切。5.2 同一个局域网下的配置与踩坑让两台机器互通最简配置只需要三个步骤两台机器装相同的ROS 2版本确保都源码编译过orbbec_camera驱动。设置相同的ROS_DOMAIN_ID环境变量默认是0如果端口冲突可以改成别的比如42。确保两台机器在同一个网段比如都用192.168.1.x并且路由器或者交换机没有开启AP隔离。然后机器人端正常启动相机节点电脑端启动RViz2在Fixed Frame里输入camera_depth_frame添加到话题深度图就能跨越网线出现在你面前。但这里有个出现频率极高的坑两台机器如果都装了多个RMW实现比如同时装了Fast DDS和Cyclone DDS默认选择的DDS实现不一致节点之间就无法互相发现。排查方法很简单echo $RMW_IMPLEMENTATION如果输出不一致在~/.bashrc里统一加上export RMW_IMPLEMENTATIONrmw_fastrtps_cpp两端重启终端即可。5.3 Web可视化用浏览器简化一切如果你不想为了看个距离再装一套完整的ROS 2环境或者你在地铁上用手机也想瞄一眼机器人状态可以加一个web_video_server。它把ROS图像话题转成HTTP视频流任何设备打开浏览器就能看。安装sudo apt install ros-humble-web-video-server运行ros2 run web_video_server web_video_server然后浏览器访问http://机器人IP:8080/stream?topic/camera/depth/image_raw这个方案特别适合不能直接SSH进机器人的场景尤其是你想在手机上快速巡检、调试相机角度是否正确的时候非常实用。5.4 远程传输的带宽优化思路Astra Pro在640x480分辨率下深度图一帧约600KB按30fps计算原始数据每秒接近18MB在局域网勉强没问题但要传到公网就会非常吃力。我用下来最有效的几个办法是把分辨率降到320x240深度信息的精度损失对距离检测影响不大。帧率从30降到10fps。图像压缩格式从raw改成jpeg或者png。orbbec_camera的launch启动参数里支持设置depth_width、depth_height和depth_fps直接改就行。实测320x24010fps的深度流每帧只有约75KB远程传输压力一下子小很多RViz2里的可视化依然流畅。6. 避坑指南这些坑我替你们踩过了6.1 USB线材和接口位置一个隐藏的帧率杀手Astra Pro对USB线很挑剔。我最初用了一根随机附送的USB 3.0线插电脑前置面板经常跑着跑着深度图就卡住不动日志里也没有任何报错重新插拔USB线又恢复。后来换了根短一点、带磁环的USB 3.0线直接插主机背面主板接口再也没出现过这个问题。原因是Astra Pro在1280x102430fps时USB 3.0的实际带宽需求很高劣质线材或者延长线会造成供电不足和信号衰减相机会自动降级或重启USB控制器。如果出现“相机每隔几十秒掉一次线”的情况先查线材大概率不是驱动问题。6.2 近距离盲区靠太近是真的测不到结构光相机和双目相机一样有最小工作距离。Astra Pro在0.35米以内基本没法得到有效深度0.35到0.6米范围内深度图会有大量空洞表现为黑色斑块。我这台S10386尤其明显正前方10厘米处的手掌在深度图里就是一片漆黑。如果你的机器人需要检测非常贴近相机的障碍物单靠Astra Pro是不行的要么加一个超声波传感器做近场补盲要么把相机斜着安装增加近场视野。6.3 阳光和强光结构光的天然克星结构光相机靠投射红外光斑来测量环境红外光强度过高时光斑会被淹没深度值就测不准。实测在室外阳光直射下Astra Pro的深度图基本是废的室内靠近窗边、阳光透过窗户照射到的地方深度图也会有明显噪点。所以这东西适合场景明确室内、稳定光照条件。如果要做室外机器人请直接上激光雷达或者主动双目红外补光的方案别在这个问题上硬耗。6.4 长时间运行的发热和掉帧连续开机两小时以上Astra Pro外壳会明显发热这时候深度图偶尔会出现整帧丢失的情况表现为话题消息间隔从33ms突然跳到200ms以上。我一开始以为是代码问题后来发现是设备过热。解决办法很朴素加一个小散热片贴在后壳上或者用USB风扇对着吹。加上散热后连续跑一整天也没再掉过帧。这个细节在官网资料里完全找不到得靠自己试。6.5 无效深度值的处理不是每个像素都有意义Astra Pro输出的深度图里黑色区域是无效像素值为0。在写距离检测算法时一定要先过滤否则会把真实距离严重拉偏。我刚开始做区域平均测距时就因为没有过滤0值导致图像中有大片无效区域时计算出来的距离偏小好几倍。工程上的处理方法是统计时剔除0值同时统计有效像素占比如果有效像素太少说明这个区域的信息量不足算法应该主动丢弃这一帧而不是输出一个不可靠的数值。7. 实测数据与扩展玩法7.1 不同距离下的测距精度实测我把相机固定在三脚架上正对一面白墙在不同距离下各采集100帧深度数据取中心区域中位数和标准差得到的结果如下表真实距离测量中位数标准差有效像素率0.50 m0.483 m18 mm62%1.00 m0.992 m6 mm98%1.50 m1.506 m5 mm99%2.00 m2.011 m8 mm97%3.00 m2.958 m21 mm89%5.00 m4.763 m55 mm57%从数据看1到2米是黄金区间标准差在10毫米以内做避障阈值判断完全够用。0.5米处不仅标准差变大有效像素率也掉到六成近距离确实不行。5米处有效像素率只剩一半多测距噪声已经大到不适合做精确控制。7.2 扩展玩法micro-ROS ESP32做低成本测距节点如果你想让Astra Pro的数据直接驱动小车上的一块ESP32从而不依赖工控机处理所有逻辑可以用micro-ROS。思路是电脑上跑一个micro-ROS Agent节点ESP32作为micro-ROS Client订阅距离检测节点发布的Float64话题通过串口或WiFi传输数据ESP32拿到距离值后直接控制电机减速或转向。这个方案的工程价值很大深度相机的复杂计算放在高性能平台上底盘控制放在实时性要求更高的单片机上两边通过话题解耦。你要是想把Astra Pro用到竞速小车或者桌面小机器人上这个架构值得研究。7.3 后续还能接什么距离检测只是起点。Astra Pro的深度图接到nav2的costmap里可以做全向避障接到MoveIt里可以做机械臂抓取的物体定位配合RGB图做YOLO检测后还能实现“检测到人→测距→跟随”的完整链路。我自己的下一步计划是把Astra Pro和现在的差分底盘深度绑定做一个跟随配送小车让它跟着人走距离保持在1.5米左右远了就跟上近了就停住。这套功能在ROS 2里也就是把现有节点串起来的事。最后再分享一个小技巧如果你把Astra Pro固定安装在机器上一定要花点时间检查深度图和RGB图的对齐情况。我在调试时发现两个相机在出厂时会有个体差异如果直接拿深度图中心点表示RGB画面中物体的距离偏差最大能到5到10厘米。用棋盘格做一次手眼标定或者干脆在应用中只用深度图坐标系来做距离判断能省掉很多后续乱七八糟的调试问题。
返回列表