【ROS2+深度相机】奥比中光Gemini 335L的简单使用

官方文档https://www.orbbec.com.cn/index/Gemini330/info.html?cate=119&id=80

B站官方教学: https://www.bilibili.com/video/BV16p421S7p9

ROS2相关源码https://gitee.com/orbbecdeveloper/OrbbecSDK_ROS2

一、安装Orbbec SDK

SDK可视化界面下载娱安装:https://github.com/orbbec/OrbbecSDK_v2/releases

下载对应平台的sdk(windows、linux 、macos)

手动下载解压后运行

bash 复制代码
cd OrbbecViewer_v2.6.3_202512231449_f605fe9_linux_x86_64/
sudo ./OrbbecViewer

可视化结果

二、安装ROS相关环境和包

ROS2相关源码https://gitee.com/orbbecdeveloper/OrbbecSDK_ROS2

2.1 安装ros2和依赖 (已安装可跳过)

安装ros

bash 复制代码
wget http://fishros.com/install -O fishros && bash fishros

source ROS2

bash 复制代码
source /opt/ros/$ROS_DISTRO/setup.bash

2.2 建ROS工作空间 + 拉源码

bash 复制代码
sudo apt install ros-humble-orbbec-camera ros-humble-orbbec-description
bash 复制代码
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src 
git clone https://gitee.com/orbbecdeveloper/OrbbecSDK_ROS2.git
cd OrbbecSDK_ROS2
git checkout v2-main

等待下,月500M, log

Cloning into 'OrbbecSDK_ROS2'...

remote: Enumerating objects: 15383, done.

remote: Counting objects: 100% (1341/1341), done.

remote: Compressing objects: 100% (499/499), done.

remote: Total 15383 (delta 948), reused 1170 (delta 822), pack-reused 14042 (from 1)

Receiving objects: 100% (15383/15383), 508.10 MiB | 4.84 MiB/s, done.

Resolving deltas: 100% (10801/10801), done.

2.3 装依赖(官方给的依赖清单):

bash 复制代码
sudo apt update
sudo apt install -y \
  libgflags-dev nlohmann-json3-dev libdw-dev \
  ros-$ROS_DISTRO-image-transport ros-$ROS_DISTRO-image-transport-plugins \
  ros-$ROS_DISTRO-compressed-image-transport \
  ros-$ROS_DISTRO-image-publisher ros-$ROS_DISTRO-camera-info-manager \
  ros-$ROS_DISTRO-diagnostic-updater ros-$ROS_DISTRO-diagnostic-msgs \
  ros-$ROS_DISTRO-statistics-msgs ros-$ROS_DISTRO-backward-ros
sudo apt install -y libssl-dev

2.4 编译

bash 复制代码
cd ~/ros2_ws
source /opt/ros/$ROS_DISTRO/setup.bash
cd ~/ros2_ws
colcon build --event-handlers console_direct+ --cmake-args -DCMAKE_BUILD_TYPE=Release

2.5 装 udev 规则(非常关键,否则容易没权限/打不开相机)

bash 复制代码
cd ~/ros2_ws/src/OrbbecSDK_ROS2/orbbec_camera/scripts
sudo bash install_udev_rules.sh
sudo udevadm control --reload-rules && sudo udevadm trigger

2.6 读取设备信息

OrbbecSDK_ROS2/orbbec_camera/scripts

bash 复制代码
source ~/ros2_ws/install/setup.bash
ros2 run orbbec_camera list_devices_node

查看信息

USB port_id: 2-6-12

Modified USB port_id: 2-6

INFO\] \[1767083724.975152353\] \[list_device_node\]: - Name: Orbbec Gemini 335L, PID: 0x0804, SN/ID: CP2AB53000xx, Connection: USB3.2 \[INFO\] \[1767083724.975169428\] \[list_device_node\]: serial: CP2AB5300014 \[INFO\] \[1767083724.975172003\] \[list_device_node\]: usb port: 2-6 \[INFO\] \[1767083724.975174137\] \[list_device_node\]: usb connect type: USB3.2

三、运行相机

3.1 启动相机节点

bash 复制代码
ros2 launch orbbec_camera gemini_330_series.launch.py \
enable_accel:=true \
enable_gyro:=true \
enable_left_ir:=true \
enable_right_ir:=true \
enable_sync_output_accel_gyro:=true

其中的参数说明:

enable_accel:是否启用加速度传感器

enable_gyro:是否启用陀螺仪传感器

enable_left_ir:是否启用左侧红外传感器

enable_right_ir:是否启用右侧红外传感器

enable_sync_output_accel_gyro:是否同步输出加速度和陀螺仪数据

发布的相机节点

bash 复制代码
### Orbbec ros2 相机节点
```bash
/camera/accel/imu_info
/camera/color/camera_info
/camera/color/image_raw
/camera/color/image_raw/compressed
/camera/color/image_raw/theora
/camera/color/metadata
/camera/depth/camera_info
/camera/depth/image_raw
/camera/depth/image_raw/compressedDepth
/camera/depth/metadata
/camera/depth/points
/camera/depth_filter_status
/camera/device_status
/camera/gyro/imu_info
/camera/gyro_accel/sample
/camera/left_ir/camera_info
/camera/left_ir/image_raw
/camera/left_ir/image_raw/compressed
/camera/left_ir/image_raw/theora
/camera/left_ir/metadata
/camera/right_ir/camera_info
/camera/right_ir/image_raw
/camera/right_ir/image_raw/compressed
/camera/right_ir/image_raw/theora
/camera/right_ir/metadata

3.2 启动订阅代码

订阅并可视化

python 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse
import time
from collections import deque

import cv2
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image

from cv_bridge import CvBridge


class RgbViewer(Node):
    def __init__(self, image_topic: str, window_name: str = "Orbbec RGB"):
        super().__init__("orbbec_rgb_viewer_min")
        self.bridge = CvBridge()
        self.image_topic = image_topic
        self.window_name = window_name

        # 用最近一段时间的到帧间隔计算 FPS(更稳定)
        self.ts = deque(maxlen=60)

        self.sub = self.create_subscription(
            Image,
            self.image_topic,
            self.cb,
            10,
        )

        self.get_logger().info(f"Subscribing: {self.image_topic}")
        cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL)

    def cb(self, msg: Image):
        # 记录时间戳(ROS stamp 优先;缺失就用 wall time)
        if msg.header.stamp.sec == 0 and msg.header.stamp.nanosec == 0:
            t = time.time()
        else:
            t = msg.header.stamp.sec + msg.header.stamp.nanosec * 1e-9
        self.ts.append(t)

        # FPS
        fps = 0.0
        if len(self.ts) >= 2:
            dt = (self.ts[-1] - self.ts[0])
            if dt > 1e-6:
                fps = (len(self.ts) - 1) / dt

        # 转 OpenCV
        try:
            img = self.bridge.imgmsg_to_cv2(msg, desired_encoding="bgr8")
        except Exception as e:
            self.get_logger().error(f"cv_bridge convert failed: {e}")
            return

        h, w = img.shape[:2]
        enc = msg.encoding if msg.encoding else "unknown"

        overlay = f"{w}x{h}  enc:{enc}  fps:{fps:.1f}"
        cv2.putText(
            img, overlay, (10, 30),
            cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2, cv2.LINE_AA
        )

        cv2.imshow(self.window_name, img)
        # 让窗口可刷新/可关闭
        key = cv2.waitKey(1) & 0xFF
        if key == 27:  # ESC 退出
            rclpy.shutdown()


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--topic", default="/camera/color/image_raw", help="RGB Image topic")
    args = parser.parse_args()

    rclpy.init()
    node = RgbViewer(args.topic)
    try:
        rclpy.spin(node)
    finally:
        node.destroy_node()
        cv2.destroyAllWindows()
        if rclpy.ok():
            rclpy.shutdown()


if __name__ == "__main__":
    main()
相关推荐
不做无法实现的梦~37 分钟前
PX4各个模块的作用(3)
linux·stm32·嵌入式硬件·机器人·自动驾驶
清风66666639 分钟前
基于单片机的喷漆机器人自动控制系统
单片机·嵌入式硬件·机器人·毕业设计·课程设计·期末大作业
9呀1 小时前
【ros2】OccupancyGrid消息里的resolution
人工智能·机器人
熵减纪元2 小时前
人形机器人周末炸场:Atlas后空翻回归、宇树零下47度暴走、中国Bolt跑出10m/s | 2.8日报
人工智能·机器人·人形机器人
硅谷秋水2 小时前
REALM:用于机器人操作泛化能力的真实-仿真验证基准测试
人工智能·机器学习·计算机视觉·语言模型·机器人
云空3 小时前
日常高频英语口语实用表达播客
人工智能·机器人
大江东去浪淘尽千古风流人物3 小时前
【VLN】VLN从理论到实践的完整指南VLN-Tutorial
机器人·大模型·概率论·端侧部署·巨身智能
神筆&『馬良』17 小时前
Foundation_pose在自己的物体上复现指南:实现任意物体6D位姿检测(利用realsense_D435i和iphone_16pro手机)
目标检测·ubuntu·机器人·视觉检测
大江东去浪淘尽千古风流人物18 小时前
【LingBot-Depth】深度补全/单目深度估计算法/立体匹配算法
机器人·大模型·概率论·端侧部署·巨身智能