ARTICLE DETAIL

资讯详情

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

ROS2与Astra Pro深度相机实战:远程可视化与距离检测

ROS2与Astra Pro深度相机实战:远程可视化与距离检测 1. 项目整体思路与方案拆解1.1 为什么选择 ROS 2 Astra Pro 这组组合搞机器人和视觉的朋友应该都体会过这种场景驱动装好了、话题也出来了可真到了要调试 3D 检测或者远程看画面的时候要么各种依赖对不上要么图像卡到怀疑人生。ROS 2 Humble Astra Pro 这个组合我前后踩坑踩了两天主要是驱动来源不统一、DDS 配置不熟悉这两大块。真正理顺之后从插上相机到屏幕上看到距离数据其实五分钟就够。先说为什么要选这套方案。Astra Pro社区里经常叫大白深度相机是 Orbbec 的结构光深度相机价格亲民分辨率最高支持 640×48030fps室内测距精度在近距离场景下表现相当稳非常适合做人形机器人避障、桌面抓取、体感交互这类项目。ROS 2 这边选 Humble是因为它是目前 LTS 版本里教程资料最全、第三方驱动兼容性最好的一个Ubuntu 22.04 直接 apt 装就行后续换 jazzy 的成本也不高。再说一个很关键的选择点ROS 2 天生支持分布式通信节点跑在机器人上、可视化端跑在笔记本上中间走的是 DDS 的局域网发现协议。这意味着你完全不用在机器人面前插显示器只要网络能通远程看深度图、远程发指令都是原生能力。我在实际项目里就是这么干的——机器人本体放在试验台人坐在工位前RViz2 界面上看到的画面和现场唯一的差别就是延迟。所以这篇文章的“远程可视化”不是靠改代码而是靠把 ROS 2 的分布式特性用起来把 DDS 的网络配置调通。1.2 整体架构与三个核心模块整套系统的架构可以拆成三层理解了这个分层后面所有操作都会变得顺理成章。最底层是驱动层。Astra Pro 通过 USB 3.0 接到主控驱动负责把相机的深度流、彩色流、红外流解析成 ROS 2 的 topic。目前最推荐的是 Orbbec 官方维护的orbbec_camera包底层调用 OrbbecSDK支持 Astra Pro / Astra Pro Plus / Femto 等一系列设备。老一点的astra_camera包只适配 ROS 1除非你还在用 Melodic否则没必要碰。中间是传输层。ROS 2 的动态发现机制会自动找到同一局域网里的节点但有个前提——所有设备的ROS_DOMAIN_ID必须一致网络里要允许 UDP 组播。这一步很多人没注意结果就是机器人端的 ros2 topic list 有数据笔记本端怎么等都等不到。最上面是应用层。可视化用 RViz2 或者 Foxglove Studio距离检测用一个小节点订阅深度图取出图像中心的深度值换算成毫米距离再发布成标准消息。这个节点看起来简单但它是后面做避障、跟随、测距所有功能的原型非常值得亲手写一遍。2. 环境准备与驱动安装2.1 ROS 2 Humble 环境准备如果你手里是一台装好 Ubuntu 22.04 的工控机或者台式机ROS 2 Humble 的安装其实很直接。先把 locale 和软件源配好然后添加 ROS 2 的 apt 源最后安装机器人常用的桌面版sudo apt update sudo apt install locales sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALLen_US.UTF-8 LANGen_US.UTF-8 sudo apt install software-properties-common sudo add-apt-repository universe sudo apt update sudo apt install curl -y 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 $(. /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-colcon-common-extensions装完之后记得做两件事第一把 source 命令写进 bashrc省得每个终端都手动来一遍第二装一个方便后面调试的命令行补全工具ros-dev-tools。echo source /opt/ros/humble/setup.bash ~/.bashrc source ~/.bashrc sudo apt install ros-dev-tools这里有个小经验ROS 2 的ros-humble-desktop已经包含了 RViz2、demo 节点、常用库做可视化实验完全够用。真正容易漏的是ros-humble-depth-image-proc和ros-humble-rqt-*这类跟图像相关的辅助包后面深度图转点云、调试图像话题都会用到。2.2 Astra Pro 驱动安装的两种路径驱动这块网上常见的教程混着 ROS 1 和 ROS 2 的内容很容易把人带偏。我实测下来最省心的路径是直接克隆orbbec_ros2官方仓库用 colcon 编译安装。mkdir -p ~/orbbec_ws/src cd ~/orbbec_ws/src git clone https://github.com/orbbec/OrbbecSDK_ROS2.git cd ~/orbbec_ws colcon build --symlink-install echo source ~/orbbec_ws/install/setup.bash ~/.bashrc source ~/.bashrc如果你不想自己编译也可以直接装发行版二进制包但这里有个坑发行版仓库里可能只有orbbec_camera的旧版本对 Humble 的 DDS 配置支持不如源码版好。我建议第一次调试直接源码编译毕竟这个包依赖很少编译也就几分钟而且--symlink-install参数能让以后改 launch 文件即时生效不用反复编译。编译完先别急着启动检查一下设备权限。Astra Pro 默认的 USB 设备节点可能需要 root 权限很多同学一插上相机就报permission denied根源就是 udev 规则没配置。官方仓库里带了一个scripts/目录下的 udev 规则文件把它复制到系统目录再重载cd ~/orbbec_ws/src/OrbbecSDK_ROS2 sudo cp scripts/99-orbbec-usb.rules /etc/udev/rules.d/ sudo udevadm control --reload-rules sudo udevadm trigger然后重新插拔一次相机用lsusb确认设备是不是已经被识别为 Orbbec 相关的 Vendor ID。到了这一步驱动环境基本就绪。3. 核心实现五步跑通整个流程3.1 第一步验证驱动和话题驱动装好之后先启动相机节点看看话题是否正常。orbbec_camera包自带一个 launch 文件直接指定设备型号启动就行ros2 launch orbbec_camera orbbec_camera.launch.py device_type:AstraPro启动日志里如果能看到类似device connected、stream started的信息说明驱动层已经通了。这一步先不要急着可视化先把话题结构看清楚ros2 topic list正常情况下你应该能看到一串话题其中重点看这几个/camera/color/image_raw彩色图像/camera/depth/image_raw深度图像/camera/depth/points深度点云/camera/depth/camera_info深度相机内参/camera/color/camera_info彩色相机内参如果/camera/depth/points没有不用慌这通常是因为depth_image_proc没有随 launch 一起启动。你可以手动跑一下点云转换节点ros2 launch depth_image_proc pointcloud_launch.py input_depth:/camera/depth/image_raw input_rgb:/camera/color/image_raw这里我想多说一句关于“验证话题”的习惯很多同学上来就打开 RViz2发现没画面就开始怀疑驱动有问题这其实是把排查链路搞反了。正确顺序应该是先确认 ROS 2 话题上有数据在流动再谈可视化。用ros2 topic hz /camera/depth/image_raw看一眼发布频率如果稳定在 30Hz 左右说明驱动和数据链路完全没问题后面可视化出问题基本就是网络配置或者工具设置的锅。3.2 第二步远程可视化方案实操远程可视化这里我推荐两套方案一套是经典稳重的 RViz2一套是现代好用的 Foxglove Studio两套我都实际跑过各有特点。先讲 RViz2 这套原理上它就是一个普通 ROS 2 节点只要你的笔记本和机器人端在同一个 ROS 2 网络里直接运行就能订阅到对方的 topic。但前提是两端都配置好同一个ROS_DOMAIN_ID并且确保机器人上的防火墙没有挡住 UDP 组播端口。机器人端不需要额外操作笔记本端执行export ROS_DOMAIN_ID0 ros2 run rviz2 rviz2打开 RViz2 之后把左下角的 Fixed Frame 改成camera_link或者camera_depth_frame取决于 launch 里的配置然后点击 Add选择 By topic找到/camera/depth/image_raw添加 DepthCloud 或者 Image 显示就能看到深度图像了。这里有个我从 ROS 1 时代就养成的好习惯如果你在 RViz2 里看不到画面先退到命令行用ros2 topic echo /camera/depth/image_raw --once看一眼数据是不是真的在流。如果 topic echo 有数据但 RViz2 没画面90% 的情况是在 RViz2 里没有正确设置坐标系或者添加的显示类型不对。DepthCloud 类型需要同时有深度图和 camera_info光有图没有内参是显示不出来的。再讲 Foxglove Studio。它的优势是界面现代化很多插件丰富还支持网页版和桌面版不需要像 RViz2 那样手动加一堆 Display。Foxglove 在 ROS 2 下有两种接入方式我实际最常用的是“无侵入式”——只让 Foxglove 作为一个 ROS 2 节点跑在笔记本上然后它内部自动发现并订阅机器人端的 topic。前提同样是同一个 DDS 网络。sudo snap install foxglove-studio foxglove-studio在 Foxglove 里打开左侧的 “Open connection”选 “ROS 2”它会自动发现当前域里的所有话题。然后拖一个 3D 面板进来添加/camera/depth/points话题点云会实时显示在三维视图里比 RViz2 的 DepthCloud 渲染舒服多了。Foxglove 还内置了 Topic 监控、数据录制、回放这些功能调试阶段效率提升非常明显。如果你是非局域网环境比如机器人端和笔记本端不在同一个物理网段还可以用 Foxglove 的 WebSocket 桥接模式把机器人端的 ROS 2 话题通过一个 bridge 服务转发出来可视化端只要连上 bridge 的 WebSocket 端口就行。这个模式在现场调试时很实用因为很多时候现场没有预铺网线用无线桥接经常掉包但 WebSocket 桥接的稳定性好很多。具体做法是在机器人端启动foxglove_bridge节点默认监听 8765 端口笔记本端 Foxglove 连接地址填ws://机器人IP:8765即可。这个方案避开了 DDS 的多播发现问题只要 TCP 能通就能看画面。3.3 第三步中心点距离检测节点可视化通了之后核心功能还没完我们要写一个小节点订阅深度图实时算出图像中心点的距离。这个节点我建议你用 C 写因为 ROS 2 里 C 的性能开销更可控后面如果要做实时避障这个节点可以直接作为基础。完整代码放这里#include rclcpp/rclcpp.hpp #include sensor_msgs/msg/image.hpp #include std_msgs/msg/float64.hpp class CenterDistanceNode : public rclcpp::Node { public: CenterDistanceNode() : Node(center_distance_node) { sub_ this-create_subscriptionsensor_msgs::msg::Image( /camera/depth/image_raw, 10, std::bind(CenterDistanceNode::image_callback, this, std::placeholders::_1)); pub_ this-create_publisherstd_msgs::msg::Float64(center_distance, 10); } private: void image_callback(const sensor_msgs::msg::Image::SharedPtr msg) { // 只处理 16UC1 格式的深度图Astra Pro 默认 depth 就是 16UC1 if (msg-encoding ! 16UC1) { RCLCPP_WARN_ONCE(this-get_logger(), Unsupported encoding: %s, msg-encoding.c_str()); return; } uint32_t width msg-width; uint32_t height msg-height; uint32_t cx width / 2; uint32_t cy height / 2; // image.data 是单通道 16 位数据每个像素占 2 字节 uint32_t offset (cy * width cx) * 2; uint16_t depth_mm *(reinterpret_castconst uint16_t*(msg-data[offset])); std_msgs::msg::Float64 out; if (depth_mm 0) { out.data depth_mm / 1000.0; // 毫米转米 } else { out.data std::numeric_limitsdouble::quiet_NaN(); } RCLCPP_INFO_THROTTLE(this-get_logger(), *this-get_clock(), 1000, Center distance: %.3f m, out.data); pub_-publish(out); } rclcpp::Subscriptionsensor_msgs::msg::Image::SharedPtr sub_; rclcpp::Publisherstd_msgs::msg::Float64::SharedPtr pub_; }; int main(int argc, char** argv) { rclcpp::init(argc, argv); rclcpp::spin(std::make_sharedCenterDistanceNode()); rclcpp::shutdown(); return 0; }代码逻辑很直白订阅深度图像取图像中心点的像素值这个像素值本身就是毫米单位的距离。如果值是 0说明该点没有有效深度数据可能因为反光、太近或者结构光被遮挡这时候发布 NaN让上层应用去处理无效值而不是硬塞一个假距离进去。编译配置 CMakeLists.txt 里要加这些依赖find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(sensor_msgs REQUIRED) find_package(std_msgs REQUIRED) add_executable(center_distance_node src/center_distance_node.cpp) ament_target_dependencies(center_distance_node rclcpp sensor_msgs std_msgs) install(TARGETS center_distance_node DESTINATION lib/${PROJECT_NAME})写完colcon build之后运行ros2 run center_distance_pkg center_distance_node终端每秒会打印一次中心点距离。你可以把手放在相机正前方不同位置看数值是否跟随变化——这个直观反馈比什么测试都有效。我测下来 Astra Pro 在 0.3 到 3 米范围内中心点的距离跳动基本在 ±5mm 以内墙面这种平整场景更稳人物边缘会稍微毛糙一点这是结构光相机的正常表现。如果你关注的是“测距测的是图像中心”这一点——没错这个节点设计就是最简单粗暴的中心点测距。但它的价值在于框架你完全可以把cx、cy改成任意像素坐标甚至改成对一整片 ROI 区域做均值滤波。后面接避障逻辑时往往不是一个点而是把深度图下采样成网格每个格子取最小距离这样判断哪个方向有障碍物才靠谱。这个节点是那个大框架的起点。4. 常见问题与避坑指南4.1 设备识别不到、驱动冲突这类问题我把这几个月群里和评论区反复出现的问题整理成了一张速查表每条都是我自己或者身边朋友真真切切踩过的现象可能原因解决方案lsusb里看不到设备USB 线质量问题或用了 USB 2.0 口换一根 USB 3.0 屏蔽线插蓝色接口避免通过扩展坞转接启动 launch 报permission deniedudev 规则没生效复制 99-orbbec-usb.rules 后必须udevadm control --reload-rules再重新插拔启动后 topic 只有 color 没有 depthAstra Pro 的深度流启动失败常见于 USB 带宽不足排查 USB 是否独占 3.0 带宽试试只保留 depth 流关掉 color 流或者降分辨率到 320×240频繁出现设备 disconnect供电不足或 USB 控制器过热使用带独立供电的 USB Hub或者直插主机背板 USB 口笔记本用户尽量别用前面板口和 Realsense 等其他相机同时工作时异常多个相机抢 USB 带宽不同相机分插不同 USB 控制器理想情况是一个相机占一个控制器这里最坑的是第一个问题——USB 线。Astra Pro 官方附带的那根线比较短有些人为了方便就随手换了一根普通安卓数据线结果稳定性和带宽瞬间崩塌。深度相机对 USB 3.0 的误码率非常敏感USB 2.0 线或者劣质线插入后会回退到 2.0 模式此时虽然能识别到设备但深度流要么出不来要么全是噪点。我自己的教训就是为了一根线多花了三个小时排查。还有一个容易被忽略的点如果你之前安装过openni2或者 ROS 1 的astra_camera它可能往系统里装过旧的libuvc库这些库会和 OrbbecSDK 冲突。症状是启动时报一堆libusb错误但设备明明就在那儿。解决办法是彻底卸载旧驱动相关包然后在干净环境下重装。4.2 远程可视化连不上、画面卡住远程可视化是这套流程里翻车率最高的环节但绝大多数问题都不是代码问题而是网络配置问题。最常见的现象机器人端ros2 topic list能看到话题笔记本端运行ros2 topic list却只有/rosout几个默认话题。这基本就是ROS_DOMAIN_ID不一致或者网络组播受限。先检查两端的 domain idecho $ROS_DOMAIN_ID如果输出为空两端默认都是 0理论上能互通。如果两边不一样手动统一然后每个终端里重新 source。改了 domain id 之后如果节点是之前在旧 domain 下启动的记得ros2 daemon stop再重试让 daemon 重新发现拓扑。这个 daemon 坑非常隐蔽我见过太多人改了配置明明生效了却因为 daemon 缓存还保留旧发现结果导致所有话题都搜不到。如果 domain id 没问题还是连不上大概率是组播被防火墙或路由器挡了。ROS 2 底层 DDS 默认使用端口 7400 左右的 UDP 组播只要网内有一层防火墙策略就可能挡掉。排查思路很简单在两端分别ping一下对方的 IP确认三层通再用ros2 multicast receive和ros2 multicast send验证组播通不通。组播不通时临时做法是关闭机器人端防火墙仅限测试环境或者改用 Foxglove WebSocket 桥接方式绕过 DDS 组播。还有一个非常实操的细节如果你用无线网络连接 ROS 2 节点画面卡顿几乎是必然的。深度相机 640×48030fps 的图像话题发布数据量大约在 60 Mbps 左右普通 2.4G 无线很容易跑不满。我在实验室里为了远程调试特意布置了一根超五类以上网线直连工控机和笔记本网络延迟从 20ms 降到了 1ms 以内画面流畅度完全不一样的。如果实在没法插网线那就考虑在机器人端先把话题压缩或者降分辨率只发布可视化需要的低分辨率流把高分辨率数据留在本机用。4.3 深度数据异常空洞、跳动、近距离失效深度数据本身的问题我会单列一节讲因为这部分原因复杂新手最容易误判成驱动坏了。先说空洞。Astra Pro 是结构光相机本质上靠红外散斑图案来计算深度遇到黑色物体、镜面、玻璃、高反光表面红外散斑会被吸收或者反射异常深度图对应区域就会出现黑斑值为 0。这是物理限制不是设备故障。处理手段是在应用层做中值滤波、时间滤波或者融合多个相机的视角。我做桌面抓取项目时对黑色哑光的物体还好遇到黑色亮面物体基本只能放弃深度改走结构光之外的方案。再说近距离失效。Astra Pro 的最小工作距离在 0.3 米左右小于这个距离深度值会快速劣化甚至直接变 0。如果你想把相机装到小机器人上做近距离避障一定要先确认使用距离在标称范围内否则数据从源头就是坏的。反过来超过 5 米之后深度误差也会随时间平方增长5 米以上不要使用 Astra Pro。最后是跳动问题。如果你发现静止场景下深度值在 2cm 甚至 5cm 范围来回跳先看看是不是拍摄场景里有强红外干扰比如阳光直射或者其他红外灯。结构光相机对红外干扰特别敏感室内补光灯如果是白炽灯也得注意因为白炽灯也会辐射红外。排除干扰源后还跳再查驱动参数比如depth_scan_avergae这类滤波参数有没有开。Orbbec 的 launch 文件里默认参数比较保守你可以打开配置文件对着改把均值滤波次数调高一点跳动就能明显缓解。5. 扩展思路从桌面节点到嵌入式与多机协作5.1 micro-ROS 与 ESP32 的接入思路标题里带了一个很值得展开的热搜词ROS 2 humble micro-ros esp32。很多人会奇怪ESP32 这种 MCU 和 Astra Pro 这种 USB 相机摆在一起能产生什么化学反应我举个实际场景你就明白了——你做了一个带机械臂的小车Astra Pro 负责感知避障决策在工控机上跑但电机控制、急停、指示灯逻辑放在 ESP32 上这时候 ESP32 最好不只是一个串口从机而是直接作为 ROS 2 网络里的一个节点跟工控机平级通信。micro-ROS 就是干这个的。它把 ROS 2 的通信栈裁剪到能在 MCU 上运行的规模ESP32 连上 WiFi 之后可以直接发布订阅 topic。这样避障节点的最终控制指令可以发到/cmd_velESP32 订阅后驱动电机ESP32 还能把 IMU、编码器数据发布成标准传感器消息工控机上用 RViz2 直接可视化和监控。接入的基本流程是这样的先装 micro-ROS 的 ESP32 组件库然后在 PlatformIO 里引入micro_ros_espidf_component配置 WiFi SSID 和密码再指定 Agent 的 IP 地址。Agent 是在工控机上跑的一个桥接进程负责把 ESP32 的串口/WiFi 数据转成标准 ROS 2 话题。配置完成之后ESP32 就真正成为 ROS 2 图里的一个节点了用ros2 node list可以看到它的名字用ros2 topic echo可以直接看到它发的数据。需要注意ESP32 的 RAM 有限micro-ROS 发布的消息如果是一整帧深度图是绝对不可能塞进去的但发布一个小结构体比如std_msgs/msg/Int16的距离值、sensor_msgs/msg/LaserScan的稀疏点云完全没有问题。所以一个很自然的架构是Astra Pro 的深度数据在工控机侧处理成稀疏的距离值或者障碍物标志然后 ESP32 只订阅这些轻量级消息把“看得懂”的信息“用起来”。这个扩展思路的价值在于它把一个单一相机项目升级成了“感知-决策-执行”的完整机器人架构。Astra Pro 负责感知工控机负责重计算ESP32 负责执行三级分工清清楚楚。5.2 应用场景扩展避障、跟随、抓取聊完嵌入式我再以距离检测为起点发散几个实际能落地的应用方向方便你根据自己项目定位选路。第一个是移动底盘避障。中心点距离检测只是起点真正做避障的时候一般把深度图划分成左中右三个区域每个区域取最小距离然后阈值判断左右前三个方向哪个有障碍物。我做过一个基于 ESP32 的小车工控机订阅深度图做区域裁剪计算之后把三个区域的最小距离发布出去ESP32 订阅后依据设定的安全距离执行减速或者原地转向。整套逻辑跑在 Humble 上非常稳定没有用任何重型的深度学习检测。第二个是目标跟随。这个场景稍微复杂一些需要用颜色或者 YOLO 检测到目标中心在图像里的坐标然后把这个坐标映射到深度图区域取目标框内的平均距离作为与目标的实际距离再用一个简单的 PID 控制底盘跟随。Astra Pro 的彩色图和深度图虽然来自两个传感器但 Orbbec 驱动一般会输出彩色到深度的外参你可以直接用图像配准之后的 topic比如/camera/depth/image_rect_raw配合 rectified color把 RGB 像素坐标直接对应到深度值上。实测在光线稳定的室内场景跟随精度大概在 10cm 以内做桌面级应用足够了。第三个是机械臂抓取。这个方向门槛会高一些因为需要把深度图转成点云然后用点云库做平面分割、目标位姿估计。ROS 2 里可以用depth_image_proc把深度图转成点云配合 PCL 库在 C 节点里处理最后通过 MoveIt 2 规划机械臂轨迹。Astra Pro 在这个场景里的定位就是提供高质量近距离点云它在 0.5 到 1 米范围内的点云平整度比同价位双目相机好不少结构光在这个距离段是有天然优势的。我个人在实际项目里最推荐的组合是Astra Pro 负责桌面级近距离感知ESP32 负责底层执行工控机做中间决策。这套组合的成本可控开发效率高而且每个环节都有独立的调试手段——相机看话题决策看日志执行看串口出问题时定位链路特别清晰。最后分享一个我自己反复强调的小习惯不管做哪个方向先录一段 ROS 2 bag 再开发。ros2 bag record -a -o debug_0321把原始话题数据录下来之后你可以离线反复回放数据不用一直占着相机和现场。我在调跟随算法的过程中全靠回放录好的 bag 来反复调参这个效率比每次都在现场对着真实目标测试高太多了。真的是谁用谁知道。
返回列表