【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()
相关推荐
多吃蔬菜!!!6 小时前
筛选机器人可动关节、校准零位姿态并获取末端执行器位置
python·机器人
liukuang1107 小时前
IPO视角| 卧安机器人赴港IPO曲线救国:先卖窗帘、再造人
microsoft·机器人
C++ 老炮儿的技术栈7 小时前
时序数据库 相对于关系型数据库,有什么区别
c语言·开发语言·c++·机器人·时序数据库·visual studio
棱镜研途8 小时前
科研快报 |从特斯拉到科沃斯:具身智能让机器人成真!
人工智能·深度学习·目标检测·机器学习·计算机视觉·机器人·智能控制
boss-dog1 天前
curobo——CUDA加速的机器人库
机器人·轨迹规划·避障·curobo
思通数科多模态大模型1 天前
门店 AI 清洁系统:AI 语义分割 + 机器人清洁
大数据·人工智能·算法·目标检测·计算机视觉·自然语言处理·机器人
GAOJ_K1 天前
滚柱导轨精度等级如何匹配应用场景?
人工智能·科技·机器人·自动化·制造
RPA机器人就选八爪鱼1 天前
RPA在银行IT运维领域的应用场景与价值分析
大数据·运维·数据库·人工智能·机器人·rpa
具身智能之心1 天前
美团 “全能突破”:RoboTron-Mani +RoboData实现通用机器人操作
机器人·具身智能