> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 使用 qrb_ros_camera 运行零拷贝摄像头

> qrb_ros_camera 是一个 ROS 包，用于发布来自 Qualcomm CSI 和 GMSL 摄像头的图像。

[qrb\_ros\_camera](https://github.com/qualcomm-qrb-ros/qrb_ros_camera) 是一个 ROS 包，用于发布来自 Qualcomm **CSI** 和 **GMSL** 摄像头的图像。它提供以下功能：

* 支持并发多路流输出。

* 支持可组合 ROS 节点。

* 由 [QRB ROS Transport](https://github.com/qualcomm-qrb-ros/qrb_ros_transport) 提供支持的零拷贝传输。

* 仅支持 NV12 作为输出格式，受 Camera Service 限制。

## `qrb_ros_camera` 的管道流程

下图展示了 `qrb_ros_camera` 的管道流程。

<Frame caption="qrb_ros_camera 管道。">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/SDKs/QIR-SDK-Ubuntu/images/image17.svg" alt="Camera hardware and a camera info YAML file feeding the qrb_ros_camera ROS node through the camera server, which publishes two output topics." />
</Frame>

[qrb\_ros\_camera](https://github.com/qualcomm-qrb-ros/qrb_ros_camera/tree/main/qrb_ros_camera) 是一个 ROS 2 包。它使用 `qrb_ros_transport` 创建了一个用于零拷贝传输的图像发布者。它支持节点组合，能够使用 ROS 进程内通信提升性能。

[qrb\_camera](https://github.com/qualcomm-qrb-ros/qrb_ros_camera/tree/main/qrb_camera) 是一个 C++ 库。它为 `qrb_ros_camera` 提供 API 以从下层的 **Camera Service** 和 CamX 库查询图像。

它包括 2 个模块：

* `camera_manager` 模块管理摄像头流，实现多流支持。

* `camera_client` 模块调用 Camera Service API 来管理摄像头流。

[qrb\_ros\_transport](https://github.com/qualcomm-qrb-ros/qrb_ros_transport) 是一个 ROS 2 包，使用 Linux DMA 缓冲区支持零拷贝图像传输，并实现 ROS 类型适配。它与进程内和进程间通信都兼容。

Camera Service 是 Qualcomm 的多媒体框架。它导出用于访问 Qualcomm 多媒体硬件的 API。

CamX 为 Qualcomm 驱动的设备上的图像捕获、处理和管理提供基础。

## `qrb_ros_camera` ROS 接口和参数

`qrb_ros_camera` 节点公开了 ROS 接口和 ROS 参数。使用它们订阅所发布的图像话题并配置摄像头流。

### ROS 接口

下表描述了 `qrb_ros_camera` 提供的 ROS 接口。

| 接口          | 名称                                | 类型                           | 说明       |
| ----------- | --------------------------------- | ---------------------------- | -------- |
| `Publisher` | `/cam${camera_id}_${stream_name}` | `sensor_msgs/msg/Image`      | 输出图像。    |
| `Publisher` | `/cam${camera_id}_camera_info`    | `sensor_msgs/msg/CameraInfo` | 提供摄像头信息。 |

### ROS 参数

下表描述了 `qrb_ros_camera` 的 ROS 参数。

| 名称                      | 类型         | 说明         | 默认值                              |
| ----------------------- | ---------- | ---------- | -------------------------------- |
| `camera_id`             | `int64`    | 摄像头设备 ID   | `0`                              |
| `stream_size`           | `uint64`   | 摄像头流的数量    | `1`                              |
| `stream_name`           | `string[]` | 摄像头流的名称    | `["stream1"]`                    |
| `${stream_name}.width`  | `uint32`   | 图像宽度       | `1920`                           |
| `${stream_name}.height` | `uint32`   | 图像高度       | `1080`                           |
| `${stream_name}.fps`    | `uint32`   | 输出图像频率（Hz） | `30`                             |
| `camera_info_path`      | `string`   | 摄像头元数据文件路径 | `config/camera_info_imx577.yaml` |

## `qrb_ros_camera` 库 API

下表描述了 `qrb_ros_camera` 调用的 `qrb_camera` C++ 库函数。

| 函数                                                                                             | 参数                                                                    | 说明                    |
| ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------- |
| `int create_camera(CameraType type, uint32_t camera_id)`                                       | • `type`：摄像头类型<br />• `camera_id`：摄像头 id                              | 创建摄像头，成功时返回摄像头索引。     |
| `bool set_camera_parameter(int index, CameraConfigure & param)`                                | • `index`：摄像头索引<br />• `param`：摄像头参数                                  | 摄像头参数设置成功时返回 `true`。  |
| `bool start_camera(int index)`                                                                 | `index`：摄像头索引                                                         | 启动摄像头。成功启动时返回 `true`。 |
| `void stop_camera(int index)`                                                                  | `index`：摄像头索引                                                         | 停止摄像头。                |
| `bool register_callback(int index, ImageCallback image_cb, PointCloudCallback point_cloud_cb)` | • `index`：摄像头索引<br />• `Image_cb`：图像回调<br />• `Point_cloud_cb`：点云消息回调 | 注册图像和点云消息的回调。         |

## 前提条件

你已根据[安装 QIR SDK](./install-the-qir-sdk)完成设备设置，并在设备上安装了 ROS2 Jazzy 和 Qualcomm Intelligent Robotics (QIR) SDK。

## 开箱即用运行 `qrb_ros_camera`

<Steps>
  <Step title="安装 qrb_ros_camera 包">
    ```bash Install the packages theme={null}
    sudo apt install ros-jazzy-qrb-ros-camera
    ```
  </Step>

  <Step title="使用摄像头节点">
    ```bash Launch the camera node theme={null}
    source /opt/ros/jazzy/setup.bash
    ros2 launch qrb_ros_camera qrb_ros_camera_launch.py
    ```
  </Step>

  <Step title="在 RVIZ 或 RQT 中通过话题 /cam${camera_id}_${stream_name} 检查 ROS 话题或查看图像">
    ```bash theme={null}
    source /opt/ros/jazzy/setup.bash
    ros2 topic echo /cam0_stream1
    ros2 topic echo /cam0_camera_info
    ```
  </Step>

  <Step title="启用多路流">
    通过使用 `stream_size` 和 `stream_name` 参数，你可以在启动文件中为一个摄像头配置多路流，例如 `/opt/ros/jazzy/share/qrb_ros_camera/launch/qrb_ros_camera_launch.py`。

    ```python qrb_ros_camera_launch.py theme={null}
    parameters=[{
        'camera_id': 0,
        'stream_size': 2,
        'stream_name': ["stream1", "stream2"],
        'stream1':{
            'width':1920,
            'height':1080,
            'fps':30,
        },
        'stream2':{
            'width':1080,
            'height':720,
            'fps':60,
        },
        'camera_info_path': os.path.join(
            get_package_share_directory('qrb_ros_camera'),
            'config', 'camera_info_imx577.yaml'),
    }]
    ```
  </Step>

  <Step title="启用零拷贝传输">
    `qrb_ros_camera` 支持在节点之间直接共享图像 `dmabuf_fd`，从而可避免通过 DDS 的图像数据内存拷贝。

    <Note>
      有关此特性的详细信息，请参阅 [ROS documentation](https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Composition.html)。
    </Note>
  </Step>
</Steps>

以下是一个使用 launch（推荐）组合多个节点的示例。

```python theme={null}
def generate_launch_description():
    container = ComposableNodeContainer(
        name='my_container',
        namespace='',
        package='rclcpp_components',
        executable='component_container',
        composable_node_descriptions=[
            ComposableNode(
                package='qrb_ros_camera',
                plugin='qrb_ros::camera::CameraNode',
                name='camera_node',
                parameters=[{
                    # ...
                }]
            ),
            ComposableNode(
                package='qrb_ros_camera',
                plugin='qrb_ros::camera::TestNode',
                name='sub_node',
            )
        ],
        output='screen',
    )
    return launch.LaunchDescription([container])
```

## 构建并运行 `qrb_ros_camera`

<Steps>
  <Step title="安装依赖">
    ```bash Install the dependencies theme={null}
    sudo apt install ros-jazzy-qrb-ros-transport-image-type \
    ros-dev-tools \
      qcom-camera-server \
      qcom-syslog-plumber-dev \
      libqmmf-dev \
      qcom-camxapi-dev
    ```
  </Step>

  <Step title="将仓库克隆到设备上">
    ```bash Download the source code theme={null}
    mkdir -p ~/ros2_ws/src
    cd ~/ros2_ws/src
    git clone https://github.com/qualcomm-qrb-ros/qrb_ros_camera.git
    ```
  </Step>

  <Step title="构建并运行 qrb_ros_camera">
    ```bash Build and launch theme={null}
    cd ~/ros2_ws
    colcon build
    source install/setup.bash
    ros2 launch qrb_ros_camera qrb_ros_camera_launch.py
    ```
  </Step>
</Steps>
