Holoscan Sensor Bridge 入门指南(Getting Started)

0. 简介(Introduction)

概述

Holoscan Sensor Bridge 提供了一个基于 FPGA 的接口,用于利用 GPU 进行低延迟的传感器数据处理。外设数据由 Holoscan Sensor Bridge 设备的 FPGA 采集,并通过以太网以 UDP 方式发送至主机系统。在 IGX Devkit 或 DGX Spark 等系统中,ConnectX SmartNIC 接口可以将 UDP 数据直接写入 GPU 显存,从而大幅降低延迟。Holoscan Sensor Bridge 的主机端软件支持将接收到的传感器数据集成到 Holoscan 流水线中;官方提供了基于 Sony IMX274 相机的视频处理与推理示例。该配置可以连接 IGX、Jetson AGX Orin、Jetson AGX Thor 或 DGX Spark 计算系统。此外:

  • Holoscan Sensor Bridge 支持带有或不带 RDMA 加速网卡的主机。对于非加速配置(如 Jetson AGX Orin Devkit),则通过基于 Linux socket 的以太网连接提供支持。
  • 适当配置的主机系统可以支持高精度 PTP 时间戳;这些时间戳可用于记录数据接收的时间、测量数据与流水线的延迟,以及同步传感器行为。IGX 和 AGX Orin 系统的板载网络接口均具备硬件 PTP 支持。

软件(Software)

Holoscan 应用通过组合一系列算子(operator)来编写。将一个算子的输出连接到另一个算子的输入(通过 add_flow API),即可配置 Holoscan 的流水线,并规定各个算子何时可以运行。

Holoscan Sensor Bridge 的主机端软件借助 Holoscan 框架,提供了用于接收 Holoscan Sensor Bridge 设备所生成网络数据的算子。例如,RoceReceiverOp 提供了从 Holoscan Sensor Bridge 数据源接收 UDP 报文并将数据存入 GPU 显存的能力。当与视频相机源配合使用时,接收到的数据呈现为一块包含 CSI-2 Bayer 图像数据的内存。Holoscan 内置了开箱即用的算子,用于:

  • 从 Bayer 视频构建 RGBA 图像
  • 图像信号处理(ISP)
  • 推理
  • 可视化,以及
  • 数据完整性测试

这些工具都旨在简化视频数据的实时处理。更多细节请参见 IMX274 demo。

不同应用对接收数据有不同的用途。例如,高速模拟信号(如 5G 蜂窝天线)的需求与视频相机不同。一般而言,应用代码通过传感器对象上的 API 为该设备提供合适的配置与控制;传感器对象知道如何按需配置网络接收算子。如果某个应用或设备的需求超出了当前实现的能力,Holoscan 算子是以源代码形式提供的:用户可以修改这些代码以满足自身需求,并且如果愿意,还可以将这些修改发回给 NVIDIA,以便纳入传感器桥接主机软件的未来版本。

应用(Applications)

Holoscan 应用的工作方式是:创建一个 HoloscanApplication 子类,重写其 configure 方法,并用它来构建适合该应用的流水线。Holoscan Sensor Bridge 的应用流水线通常专注于:从传感器设备采集数据、对数据进行处理、生成合适的输出,并将输出数据发送到合适的目标。

传感器对象(Sensor objects)

用于配置和监控特定传感器的 API 呈现在传感器对象 上。例如,Imx274Cam 就是一个传感器对象,提供初始化时配置、运行时参数更新(如曝光)以及设备健康监控等方法。Holoscan 应用使用这些 API 来影响设备行为:例如,一个"自动曝光算子"可以接收视频帧作为输入,并据此确定发送给相机 set_exposure 方法的数值。传感器对象是针对特定设备的用户态驱动:它们提供对设备功能的访问,但不包含任何特定于应用的行为。

主机要求(Host requirements)

Holoscan Sensor Bridge 软件可以运行在任何受 NVIDIA Holoscan 支持的系统上。为获得最佳性能,推荐使用配备 ConnectX SmartNIC 的 IGX 系统。在没有 ConnectX 网卡的系统中(如 Jetson AGX Orin),性能会受限于主机操作系统的网络协议栈。


本页是 Getting Started 的引言部分,核心要点是:Sensor Bridge 的数据通路为「传感器 → FPGA → UDP/以太网 → (可选 ConnectX RDMA 直写 GPU 显存)→ Holoscan 算子流水线」,并且软硬件都支持在有/无 RDMA 网卡两种主机形态下工作。

1. 硬件设置(Hardware Setup)

本页介绍 Holoscan Sensor Bridge 官方内置支持的开发套件的设备设置方法。完整的合作伙伴产品列表,请访问 Holoscan Sensor Bridge 主页。许多厂商维护自己的 FPGA、MCU 与传感器模组的 Holoscan Sensor Bridge 移植版本,使用其产品时请直接联系相应厂商获取说明。

目前覆盖以下四种设备:

  • Lattice CPNX100-ETH-SENSOR-BRIDGE
  • Microchip MPF200-ETH-SENSOR-BRIDGE
  • Leopard imaging VB1940 Eagle 相机
  • TauroTech DA326

1.1 Lattice CPNX100-ETH-SENSOR-BRIDGE

Holoscan Sensor Bridge 板卡

【图:Holoscan sensor bridge 板卡(Lattice Bajoran Board 正面)】

Lattice CPNX100-ETH-SENSOR-BRIDGE 具有如下连接器:

  1. SFP+ 端口 ------ 两个 10Gbps 以太网端口,用于连接主机系统。
  2. 相机连接器 ------ 用于连接相机(例如 IMX274)。
  3. 电源端口 ------ 传感器桥设备通过 USB-C 电源供电,输入电压范围为 5V 至 20V。由于传感器经由传感器桥板供电,建议使用专用电源同时为板卡和传感器供电。
  4. GPIO 引脚 ------ 传感器桥设备支持 16 个 GPIO 引脚(0...15)和 4 个接地引脚(上图中标记为 "G")。

注意:传感器桥设备不提供 USB 主机接口------USB-C 接口仅用于供电。与主机的所有交互均通过以太网端口进行。

Holoscan sensor bridge 的参考应用目前使用 IMX274 双摄像头模组:

【图:IMX274 双摄像头模组】

摄像头模组按下图所示方式安装到传感器桥设备上:

【图:传感器桥设备与相机的安装方式】

将 Holoscan sensor bridge 连接到主机

  1. 确保 Holoscan sensor bridge 板卡处于断电状态。
  2. 按上图所示,将摄像头模组装入相机连接器。
  3. 将下图中标记为 "SFP+ 0" 的 SFP+ 端口连接到主机系统。这是访问立体相机对中第一路相机的正确连接方式,该端口提供对图中 "Camera 0" 所示相机数据的访问。

【图:传感器桥相机配置(SFP+ 0 位置)】

  1. 对于 IGX Devkit,连接到下图中红色箭头标注的 QSFP 端口。

【图:IGX 背板】

对于使用立体相机对中第二路相机的配置,将标记为 "SFP+ 1" 的 SFP 端口连接到 IGX 背面尚未使用的另一个 QSFP 端口。

  1. 对于 DGX Spark,将 HSB 上的 "SFP+ 0" 端口连接到下图所示的 "CX7 QSFP port 0"。使用立体相机对中第二路相机的配置,则将 HSB 上的 "SFP+ 1" 端口连接到 "CX7 QSFP port 1"。

【图:DGX Spark CX7 QSFP 端口】

  1. 对于 AGX Orin Devkit,连接到 10G 以太网端口(下图中标记为 "H")。

【图:Jetson AGX Orin 端口】

  1. 将最低规格为 12V/2A 的 USB-C 电源接到传感器桥设备的 USB-C 电源连接器上,等待传感器桥板上的绿色 LED 亮起。
  2. 更多细节请参阅 Lattice CPNX100-ETH-SENSOR-BRIDGE 官方页面。

随后请按照「主机设置」一章的说明配置你的主机系统。

1.2 Microchip MPF200-ETH-SENSOR-BRIDGE

以下说明介绍如何设置 Microchip MPF200-ETH-SENSOR-BRIDGE 设备,并将其连接到 IGX 与 Jetson AGX Orin 开发套件。

Holoscan Sensor Bridge 板卡

【图:Microchip 传感器桥板卡】

Microchip MPF200-ETH-SENSOR-BRIDGE 具有如下连接器:

  1. SFP+ 端口 ------ 两个 10Gbps 以太网端口,用于连接主机系统。
  2. 相机连接器 ------ 用于连接相机(例如 IMX477)。
  3. 电源开关 ------ 传感器桥设备通过连接到该端口的 12V 电源供电,电源最低规格为 12V/2A。

Microchip MPF200-ETH-SENSOR-BRIDGE 的参考应用目前使用 IMX477 相机模组:

【图:IMX477 相机模组】

摄像头模组按下图所示方式安装到传感器桥设备上:

【图:传感器桥设备与 IMX477 的连接方式】

将 Holoscan sensor bridge 连接到主机

  1. 如上图所示,将 SFP+ 端口连接到主机系统。
  2. 对于 AGX Orin Devkit,连接到 10G 以太网端口(下图中标记为 "H")。

【图:Jetson AGX Orin 端口】

  1. 使用电源开关给板卡上电。
  2. 更多细节请参阅 Microchip MPF200-ETH-SENSOR-BRIDGE 官方页面。

随后请按照「主机设置」一章的说明配置你的主机系统。

1.3 Leopard imaging VB1940 Eagle 相机

以下说明介绍如何设置 VB1940 Eagle 相机,并将其直接连接到 IGX 与 Jetson AGX Orin 开发套件。

Leopard imaging VB1940 Eagle 相机

Leopard imaging VB1940 Eagle 相机是一款以太网供电(POE)相机,无需传感器桥设备即可直接连接开发套件。其特点包括:

  • 直连以太网 ------ 使用 CAT-6 网线直接连接主机系统
  • 工业级设计 ------ 面向工业、机器人与医疗应用
  • 紧凑设计 ------ 不需要额外的桥接硬件

【图:LI VB1940 Eagle 相机】

将 VB1940 Eagle 相机连接到主机

请确保你的 VB1940 已刷写最新固件,详见「Holoscan Sensor Bridge FPGA 固件更新」页面。

  1. 用以太网线将 VB1940 Eagle 相机连接到开发套件上一个可用的以太网端口。
  2. 对于 IGX Devkit,使用 QSFP 转接器连接到背板上红色箭头标注的 QSFP 以太网端口。

【图:IGX 背板】

  1. 对于 AGX Orin Devkit,连接到 10G 以太网端口(下图中标记为 "H")。

【图:Jetson AGX Orin 端口】

  1. 确保 VB1940 Eagle 相机已上电。
  2. 运行 ping 192.168.0.2 验证连通性。
  3. 更多细节请参阅 Leopard imaging Eagle 相机文档。

随后请按照「主机设置」一章的说明配置你的主机系统。

1.4 TauroTech DA326

【图:TauroTech DA326 传感器桥板卡】

与 Lattice、Microchip 的传感器桥板卡(相机传感器直接接在 MIPI CSI-2 连接器上)不同,TauroTech DA326 桥接的是 GMSL 相机模组:传感器模组通过 GMSL 链路连接到板卡,板载的 MAX96716A 解串器(deserializer)将 GMSL 流转换为 MIPI CSI-2 信号送给 FPGA。

TauroTech DA326 具有如下连接器:

  1. SFP+ 端口 ------ 一个 10Gbps 以太网端口,用于连接主机系统。
  2. GMSL 相机连接器 ------ 用于相机输入的 GMSL 接口。
  3. 电源端口 ------ 传感器桥设备由专用电源供电;板卡还通过同轴连接器为所连接的相机模组供电。

DA326 上的 Holoscan sensor bridge 参考应用使用 Hawk 相机模组:

【图:Hawk 相机模组】

一个 Hawk 模组由两个传感器(AR0234)和一个串行器(MAX9295D)组成。

将 TauroTech DA326 连接到主机

  1. 确保 DA326 板卡处于断电状态。

  2. 使用同轴线缆将 Hawk 相机模组接到 DA326 的 GMSL 连接器上。

  3. 将 DA326 的 SFP+ 端口连接到主机系统。

  4. 对于 IGX Devkit,使用 QSFP 转接器连接到背板上红色箭头标注的 QSFP 以太网端口。

    【图:IGX 背板】

  5. 对于 AGX Orin Devkit,在 Tauro Tech DA326 的 SFP 笼中安装一个 10GBASE-T SFP PHY,以连接到 10G 以太网端口(下图中标记为 "H")。

    【图:Jetson AGX Orin 端口】

  6. 对于 AGX Thor Devkit,使用 QSFP 转接器连接到 QSFP 端口(下图中标记为 "6")。

    【图:Jetson AGX Thor 端口】

  7. 给 DA326 板卡上电,等待板卡状态 LED 指示就绪。

  8. 运行 ping 192.168.0.2 验证连通性。

关于参考传感器模组的更多细节,请参阅 Leopard imaging Hawk 相机文档;关于上述串行器与解串器的更多细节,请参阅 Analog Devices 文档;关于 TauroTech DA326 板卡的更多细节,请参阅 Tauro Technologies 文档。

随后请按照「主机设置」一章的说明配置你的主机系统。


2. 主机设置(Host Setup)

Holoscan sensor bridge 支持以下配置:

  • 配置有 IGX OS 1.1.2+ 并配备 CX7 SmartNIC 设备的 IGX 系统。
  • 运行 JP6.2.1+ 的 AGX Orin 系统。该配置下,板载以太网控制器配合 Linux 内核网络协议栈进行数据 I/O;所有网络 I/O 均由 CPU 完成,没有网络加速。
  • 运行 JP7.2、配备 MGBE SmartNIC 设备并使用 CoE 传输的 AGX Thor 系统。
  • 运行 DGX OS 7.2.3+ 并配备 CX7 SmartNIC 设备的 DGX Spark 系统。
  • 配备 NVIDIA 独立显卡的 x86 Linux 工作站。支持两条主机接收路径:非加速的基于 Linux socket 的接收器(主要用于开发或测试),以及加速的 RoCE 路径(要求通往传感器桥的链路上有 ConnectX 网卡)。注意:该配置不属于主要参考平台;即使 GPU 与驱动显示 GPUDirect RDMA 可用,主机的 PCIe 路径也可能并不真正支持它------此时必须在构建时禁用 GPU VRAM 帧缓冲(见下文 x86 Linux 一节)。

Holoscan sensor bridge 板卡设置完成之后,需要在主机系统中配置若干前提条件。虽然 holoscan sensor bridge 的演示应用通常在容器中运行,但以下命令全部要在容器之外、直接在主机系统上执行。这些配置在重启后依然保留,因此只需设置一次。

  • 安装 git-lfs

    Holoscan sensor bridge 源码仓库中的部分数据文件使用 GIT LFS。

    bash 复制代码
    sudo apt-get update
    sudo apt-get install -y git-lfs
  • 授予你的用户访问 docker 子系统的权限:

    bash 复制代码
    sudo usermod -aG docker $USER

    重启计算机以使该设置生效。

接下来,根据你的主机类型,按照下面相应小节的指引进行配置。

2.1 IGX

  • 运行以下命令,将 GPU 驱动更新到 535.309.01 并安装 IGX 1.1.3:

    bash 复制代码
    sudo tee /etc/apt/preferences.d/nvidia-driver-pin >/dev/null <<'EOF'
    Package: nvidia-* libnvidia-*
    Pin: version 535.309.01*
    Pin-Priority: 1001
    EOF
    
    sudo apt-get purge "nvidia-kernel-*"
    sudo apt-get update && sudo apt-get install -y nvidia-driver-535-open=535.309.01-0ubuntu0.22.04.1
    sudo apt dist-upgrade

    重启机器以加载新驱动:

    bash 复制代码
    sudo reboot

    重启后,确认新驱动已生效:

    none 复制代码
    ➜ nvidia-smi
    +---------------------------------------------------------------------------------------+
    | NVIDIA-SMI 535.309.01             Driver Version: 535.309.01   CUDA Version: 12.2     |
    |-----------------------------------------+----------------------+----------------------+
    | GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
    |                                         |                      |               MIG M. |
    |=========================================+======================+======================|
    |   0  NVIDIA RTX 6000 Ada Gene...    Off | 00000005:09:00.0 Off |                  Off |
    | 30%   34C    P8              20W / 300W |    189MiB / 49140MiB |      0%      Default |
    |                                         |                      |                  N/A |
    +---------------------------------------------------------------------------------------+
  • 确定与第一个 CX7 端口关联的网络设备名称。从 IGX 机箱背面看,这是最右侧的 QSFP 端口。

    【图:IGX QSFP0】

    bash 复制代码
    ls /sys/class/infiniband
    none 复制代码
    roceP5p3s0f0 roceP5p3s0f1

    该命令会列出所有 CX7 端口;你的设备名称可能不同。编号最小的一个(本例中为 roceP5p3s0f0)就是第一个 CX7 端口。

    使用上面命令输出的、你机器上实际出现的设备名之一,检查 CX7 固件版本:

    bash 复制代码
    cat /sys/class/infiniband/roceP5p3s0f0/fw_ver
    none 复制代码
    28.39.3004

    如果版本低于或等于 28.38.1026,请从 IGX 下载页面下载相应的 "ConnectX-7 Firmware" ISO 并升级 CX7 固件。升级后务必重启机器,并重新检查确认固件已加载为新版本。

    将第一个 CX7 端口的名称赋给变量 $IN0

    bash 复制代码
    LC_COLLATE=C IN=(/sys/class/infiniband/*)
    IN0=`basename ${IN[0]}`
    echo $IN0
    none 复制代码
    roceP5p3s0f0

    接下来,确定与该设备关联的主机以太网端口,并将其赋给变量 $EN0,稍后的网络配置会用到它:

    bash 复制代码
    EN0=`basename /sys/class/infiniband/$IN0/device/net/*`
    echo $EN0
    none 复制代码
    enP5p3s0f0np0

    小结:与 $IN0roceP5p3s0f0)关联的主机网络接口是 $EN0enP5p3s0f0np0);你的具体设备名称可能不同。

  • IGX OS 使用 NetworkManager 配置网络接口。默认情况下,传感器桥设备的第一个端口使用地址 192.168.0.2。将第一个以太网设备($EN0)配置为使用地址 192.168.0.101,并添加到 192.168.0.2 的永久路由,MTU 使用 RoCE 推荐值(如果你的系统无法以这种方式使用 192.168.0.0/24 网段,请参阅文档 support/notes 中的 IP 地址配置说明):

    bash 复制代码
    sudo nmcli con add con-name hololink-$EN0 ifname $EN0 type ethernet ip4 192.168.0.101/24
    sudo nmcli connection modify hololink-$EN0 +ipv4.routes 192.168.0.2/32
    sudo nmcli connection modify hololink-$EN0 ethtool.ring-rx 4096
    sudo nmcli connection modify hololink-$EN0 802-3-ethernet.mtu 4200
    sudo nmcli connection up hololink-$EN0

    给传感器桥设备上电,确认其连接正确,然后执行 ping 192.168.0.2 检查连通性:

    none 复制代码
    ping 192.168.0.2
    PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
    64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.225 ms
    64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.081 ms
    64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=0.088 ms
    64 bytes from 192.168.0.2: icmp_seq=4 ttl=64 time=0.132 ms
    ^C
    --- 192.168.0.2 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3057ms
    rtt min/avg/max/mdev = 0.081/0.131/0.225/0.057 ms
  • 传感器桥设备上的第二个 SFP+ 连接器用于传输立体相机模组(如 IMX274)第二路相机采集的数据。默认情况下,传感器桥设备的第二个端口使用地址 192.168.0.3。将第二个 IGX QSFP 端口(下图中红色箭头所示)连接到传感器桥设备的第二个 SFP+ 端口。

    【图:IGX QSFP1】

    我们将它们记作 $IN1$EN1。沿用前面赋值 $IN0$EN0 的命令:

    bash 复制代码
    IN1=`basename ${IN[1]}`
    echo $IN1
    EN1=`basename /sys/class/infiniband/$IN1/device/net/*`
    echo $EN1
    none 复制代码
    roceP5p3s0f1
    enP5p3s0f1np1

    同上,你的设备名称可能不同。为第二个 QSFP 网络端口配置合适的地址和永久路由:

    bash 复制代码
    sudo nmcli con add con-name hololink-$EN1 ifname $EN1 type ethernet ip4 192.168.0.102/24
    sudo nmcli connection modify hololink-$EN1 +ipv4.routes 192.168.0.3/32
    sudo nmcli connection modify hololink-$EN1 ethtool.ring-rx 4096
    sudo nmcli connection modify hololink-$EN1 802-3-ethernet.mtu 4200
    sudo nmcli connection up hololink-$EN1

    现在用 ping 192.168.0.3 测试第二条连接:

    none 复制代码
    ping 192.168.0.3
    PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
    64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.210 ms
    64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.271 ms
    64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.181 ms
    64 bytes from 192.168.0.3: icmp_seq=4 ttl=64 time=0.310 ms
    64 bytes from 192.168.0.3: icmp_seq=5 ttl=64 time=0.258 ms
    ^C
    --- 192.168.0.3 ping statistics ---
    5 packets transmitted, 5 received, 0% packet loss, time 4102ms
    rtt min/avg/max/mdev = 0.181/0.246/0.310/0.045 ms

    第二个端口配置完成后,第一个端口应仍能正常响应 ping。

2.2 AGX Orin

本软件包中的演示与示例假定传感器桥设备连接到 eno1,即 AGX Orin 上的 RJ45 连接器。

  • 在板载网络端口上配置静态 IP 地址 192.168.0.101。

    L4T 使用 NetworkManager 配置接口;默认情况下接口被配置为 DHCP 客户端。使用以下命令将 IP 地址更新为 192.168.0.101。(如果你的系统无法以这种方式使用 192.168.0.0/24 网段,请参阅文档 support/notes 中的 IP 地址配置说明。)

    注意:运行 JP6.2.1 的 AGX 上,板载以太网设备为 eno1;JP7.2 上则为 end0。如果你运行的是其他配置,请为变量 EN0 使用相应的名称:

    bash 复制代码
    EN0=end0
    sudo nmcli con add con-name hololink-$EN0 ifname $EN0 type ethernet ip4 192.168.0.101/24
    sudo nmcli connection up hololink-$EN0

    给传感器桥设备上电,确认其连接正确,然后执行 ping 192.168.0.2 检查连通性。

  • 对于基于 Linux socket 的示例,建议将一个处理器核心从 Linux 内核调度中隔离出来。对于高带宽应用(例如 4K 视频采集),隔离网络接收核心是必需的。当示例程序以处理器亲和性绑定到该隔离核心运行时,性能会提升、延迟会降低。默认情况下,sensor bridge 软件将时间关键的后台网络接收进程运行在第三个处理器核心上。如果该核心被从 Linux 调度中隔离,那么除非用户显式请求,否则不会有任何进程被调度到该核心上,可靠性与性能都会大幅提升。

    隔离该核心的方法是编辑 /boot/extlinux/extlinux.conf:在以 APPEND 开头的那一行末尾添加 isolcpus=2。修改后文件大致如下:

    none 复制代码
    TIMEOUT 30
    DEFAULT primary
    
    MENU TITLE L4T boot options
    
    LABEL primary
          MENU LABEL primary kernel
          LINUX /boot/Image
          ...
          APPEND ${cbootargs} ...<other-settings>... isolcpus=2

    Sensor bridge 应用也可以通过将环境变量 HOLOLINK_AFFINITY 设置为某个核心号,让网络接收进程运行在其他核心上。例如,运行在第一个处理器核心上:

    bash 复制代码
    HOLOLINK_AFFINITY=0 python3 examples/linux_imx274_player.py

    HOLOLINK_AFFINITY 设置为空则会跳过 sensor bridge 代码中的所有核心亲和性设置。

  • 在开机时运行 "jetson_clocks" 工具,将各核心时钟设为最大值:

    bash 复制代码
    JETSON_CLOCKS_SERVICE=/etc/systemd/system/jetson_clocks.service
    cat <<EOF | sudo tee $JETSON_CLOCKS_SERVICE >/dev/null
    [Unit]
    Description=Jetson Clocks Startup
    After=nvpmodel.service
    
    [Service]
    Type=oneshot
    ExecStart=/usr/bin/jetson_clocks
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    sudo chmod u+x $JETSON_CLOCKS_SERVICE
    sudo systemctl enable jetson_clocks.service
  • 将 AGX Orin 的电源模式设置为 "MAXN" 以获得最佳性能。该设置可通过屏幕左上角的 L4T 电源下拉菜单更改:

    【图:AGX Orin MAXN】

  • 重启 AGX Orin,使核心隔离与性能设置生效。如果配置 "MAXN" 性能模式时没有提示你重启设备,请手动执行重启命令:

    bash 复制代码
    reboot

2.3 DGX Spark

  • 首先检查是否存在 OTA 的 ConnectX-7 热插拔(hotplug)特性,如果存在则将其禁用并重启。该特性会在未检测到链路时关闭网卡,可能干扰本指南的操作与 HSB 的正常工作。注意:如果你的网卡在未接任何设备时断电,但下列文件并不存在,说明你可能没有禁用它的能力,应当更新 OTA。

    bash 复制代码
    if [ -f /etc/nvidia/cx7-hotplug-enabled ] ; then
        sudo mv /etc/nvidia/cx7-hotplug-enabled /etc/nvidia/cx7-hotplug-disabled
        sudo reboot
    fi
  • 确定与第一个 CX7 端口关联的网络设备名称。从 DGX Spark 机箱背面看,这是最左侧的 QSFP 端口(下图中的 "port 0")。注意:下面 echo 输出的具体设备名称可能因不同系统的驱动配置而不同或发生变化。

    【图:DGX Spark CX7 QSFP 端口】

    bash 复制代码
    ls /sys/class/infiniband
    none 复制代码
    roceP2p1s0f0  roceP2p1s0f1  rocep1s0f0  rocep1s0f1

    该命令会列出连接到 CX7 端口的 InfiniBand 设备;你的设备名称可能不同。编号最小的一个(本例中为 roceP2p1s0f0)就是第一个 CX7 端口。将该名称赋给变量 $IN0

    bash 复制代码
    LC_COLLATE=C IN=(/sys/class/infiniband/*)
    IN0=`basename ${IN[0]}`
    echo $IN0
    none 复制代码
    roceP2p1s0f0

    接下来,确定与该设备关联的主机以太网端口,并将其赋给变量 $EN0,稍后的网络配置会用到它:

    bash 复制代码
    EN0=`basename /sys/class/infiniband/$IN0/device/net/*`
    echo $EN0
    none 复制代码
    enP2p1s0f0np0

    小结:与 $IN0roceP2p1s0f0)关联的主机网络接口是 $EN0enP2p1s0f0np0);你的具体设备名称可能不同。

  • DGX OS 使用 NetworkManager 配置网络接口。默认情况下,传感器桥设备的第一个端口使用地址 192.168.0.2。将第一个以太网设备($EN0)配置为使用地址 192.168.0.101,并添加到 192.168.0.2 的永久路由,MTU 使用 RoCE 推荐值:

    bash 复制代码
    sudo nmcli con add con-name hololink-$EN0 ifname $EN0 type ethernet ip4 192.168.0.101/24
    sudo nmcli connection modify hololink-$EN0 +ipv4.routes 192.168.0.2/32
    sudo nmcli connection modify hololink-$EN0 ethtool.ring-rx 4096
    sudo nmcli connection modify hololink-$EN0 802-3-ethernet.mtu 4200
    sudo nmcli connection up hololink-$EN0

    给传感器桥设备上电,确认其连接正确,然后执行 ping 192.168.0.2 检查连通性:

    none 复制代码
    ping 192.168.0.2
    PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
    64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.225 ms
    64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.081 ms
    64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=0.088 ms
    64 bytes from 192.168.0.2: icmp_seq=4 ttl=64 time=0.132 ms
    ^C
    --- 192.168.0.2 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3057ms
    rtt min/avg/max/mdev = 0.081/0.131/0.225/0.057 ms
  • 传感器桥设备上的第二个 SFP+ 连接器用于传输立体相机模组(如 IMX274)第二路相机采集的数据。默认情况下,传感器桥设备的第二个端口使用地址 192.168.0.3。将第二个 DGX Spark QSFP 端口(上图中的 "port 1")连接到传感器桥设备的第二个 SFP+ 端口。

    我们将它们记作 $IN1$EN1。沿用前面赋值 $IN0$EN0 的命令:

    bash 复制代码
    IN1=`basename ${IN[1]}`
    echo $IN1
    EN1=`basename /sys/class/infiniband/$IN1/device/net/*`
    echo $EN1
    none 复制代码
    roceP2p1s0f1
    enP2p1s0f1np1

    同上,你的设备名称可能不同。为第二个 QSFP 网络端口配置合适的地址和永久路由:

    bash 复制代码
    sudo nmcli con add con-name hololink-$EN1 ifname $EN1 type ethernet ip4 192.168.0.102/24
    sudo nmcli connection modify hololink-$EN1 +ipv4.routes 192.168.0.3/32
    sudo nmcli connection modify hololink-$EN1 ethtool.ring-rx 4096
    sudo nmcli connection modify hololink-$EN1 802-3-ethernet.mtu 4200
    sudo nmcli connection up hololink-$EN1

    现在用 ping 192.168.0.3 测试第二条连接:

    none 复制代码
    ping 192.168.0.3
    PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
    64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.210 ms
    64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.271 ms
    64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.181 ms
    64 bytes from 192.168.0.3: icmp_seq=4 ttl=64 time=0.310 ms
    64 bytes from 192.168.0.3: icmp_seq=5 ttl=64 time=0.258 ms
    ^C
    --- 192.168.0.3 ping statistics ---
    5 packets transmitted, 5 received, 0% packet loss, time 4102ms
    rtt min/avg/max/mdev = 0.181/0.246/0.310/0.045 ms

    第二个端口配置完成后,第一个端口应仍能正常响应 ping。

2.4 AGX Thor

  • 在 Thor Devkit 上安装 JP 7.2 之后,完成以下步骤。

    如果是使用 ISO 方式安装的,请安装 CUDA Toolkit 13.2 并执行:

    bash 复制代码
    export PATH=/usr/local/cuda/bin:$PATH
    export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
    wget https://developer.nvidia.com/downloads/embedded/L4T/r39_Release_v2.0/release/Jetson_SIPL_API_R39.2.0_aarch64.tbz2
    wget https://developer.nvidia.com/downloads/embedded/L4T/r39_Release_v2.0/release/Jetson_Multimedia_API_R39.2.0_aarch64.tbz2
    sudo tar xjf Jetson_SIPL_API_R39.2.0_aarch64.tbz2 -C /
    sudo tar xjf Jetson_Multimedia_API_R39.2.0_aarch64.tbz2 -C /
  • 对于基于 Linux socket 的示例,建议将一个处理器核心从 Linux 内核调度中隔离出来。对于高带宽应用(例如 4K 视频采集),隔离网络接收核心是必需的。当示例程序以处理器亲和性绑定到该隔离核心运行时,性能会提升、延迟会降低。默认情况下,sensor bridge 软件将时间关键的后台网络接收进程运行在第三个处理器核心上。如果该核心被从 Linux 调度中隔离,那么除非用户显式请求,否则不会有任何进程被调度到该核心上,可靠性与性能都会大幅提升。

    隔离该核心的方法是编辑 /boot/extlinux/extlinux.conf:在以 APPEND 开头的那一行末尾添加 isolcpus=2。修改后文件大致如下:

    none 复制代码
    TIMEOUT 30
    DEFAULT primary
    
    MENU TITLE L4T boot options
    
    LABEL primary
          MENU LABEL primary kernel
          LINUX /boot/Image
          ...
          APPEND ${cbootargs} ...<other-settings>... isolcpus=2

    Sensor bridge 应用也可以通过将环境变量 HOLOLINK_AFFINITY 设置为某个核心号,让网络接收进程运行在其他核心上。例如,运行在第一个处理器核心上:

    bash 复制代码
    HOLOLINK_AFFINITY=0 python3 examples/linux_imx274_player.py

    HOLOLINK_AFFINITY 设置为空则会跳过 sensor bridge 代码中的所有核心亲和性设置。

    此步骤需要重启系统才能生效。

  • 安装 Holoscan SDK v4.4.0:

    bash 复制代码
    sudo apt update
    sudo apt install holoscan-cuda-13=4.4*
  • 安装其他 Holoscan sensor bridge 依赖:

    bash 复制代码
    . /etc/os-release
    UBUNTU_VERSION="`echo ${VERSION_ID} | sed 's/\.//g'`"
    sudo apt-get install ca-certificates gpg wget
    wget https://developer.download.nvidia.com/compute/nvcomp/5.2.0/local_installers/nvcomp-local-repo-ubuntu${UBUNTU_VERSION}-5.2.0_5.2.0-1_arm64.deb
    sudo dpkg -i nvcomp-local-repo-ubuntu${UBUNTU_VERSION}-5.2.0_5.2.0-1_arm64.deb
    sudo cp /var/nvcomp-local-repo-ubuntu${UBUNTU_VERSION}-5.2.0/nvcomp-*-keyring.gpg /usr/share/keyrings/
    rm nvcomp-local-repo-ubuntu${UBUNTU_VERSION}-5.2.0_5.2.0-1_arm64.deb
    test -f /usr/share/doc/kitware-archive-keyring/copyright ||
    wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
    echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ${VERSION_CODENAME} main" | sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null
    sudo apt-get update
    test -f /usr/share/doc/kitware-archive-keyring/copyright ||
    sudo rm /usr/share/keyrings/kitware-archive-keyring.gpg
    sudo apt-get install kitware-archive-keyring
    sudo apt-get update
    sudo apt install -y cmake=3.31.11* cmake-data=3.31.11* libfmt-dev libssl-dev libcurlpp-dev libyaml-cpp-dev python3-dev nvcomp-cuda-13
  • 启用网络接口并确保相机可被枚举到(假定相机 IP 地址为 192.168.0.2):

    bash 复制代码
    EN0=mgbe0_0
    sudo nmcli con add con-name hololink-$EN0 ifname $EN0 type ethernet ip4 192.168.0.101/24
    sudo nmcli connection modify hololink-$EN0 +ipv4.routes 192.168.0.2/32
    sudo nmcli connection up hololink-$EN0
  • 获取并构建 holoscan sensor bridge:

    holoscan sensor bridge v2.6 版本支持在终端命令行直接运行基于 C++ Li VB1940 加速网络的示例,也支持在 holoscan sensor bridge 容器内运行 Li VB1940 与 IMX274 的 Python 示例。

    第一步,克隆 holoscan sensor bridge 仓库:

    bash 复制代码
    git clone https://github.com/nvidia-holoscan/holoscan-sensor-bridge.git

    要在终端命令行运行基于 SIPL 的 C++ Li VB1940 加速网络示例,使用以下命令:

    bash 复制代码
    cd holoscan-sensor-bridge
    mkdir build && cd build
    cmake -DHOLOLINK_BUILD_SIPL=1 -DHOLOLINK_BUILD_FUSA=1 -DHOLOLINK_BUILD_ROCE=0 ..
    make -j

运行 CoE 加速示例

Holoscan Sensor Bridge 可以通过下面列出的两条不同路径之一,利用 Thor 的硬件加速 CoE 能力。

SIPL

SIPL 是一个模块化、可扩展的图像传感器控制与图像处理框架,它开放了 Thor 的全部硬件能力,包括 CoE 与 ISP 硬件加速。支持 SIPL 的传感器驱动使用统一设备驱动框架(UDDF)编写,JetPack 7.2 已附带 VB1940 的参考 UDDF 驱动。

按以下步骤运行基于 SIPL 的 VB1940 传感器 CoE 示例应用:

  • 获取你相机的 MAC ID:

    bash 复制代码
    ./tools/enumerate/hololink-enumerate

    示例输出:

    none 复制代码
    mac_id=8C:1F:64:6D:70:03 hsb_ip_version=0x2510 fpga_crc=0xffff ip_address=192.168.0.2 fpga_uuid=f1627640-b4dc-48af-a360-c55b09b3d230 serial_number=ffffffffffffff interface=mgbe0_0 board=Leopard Eagle
  • 更新下列配置文件中的 ip_addressmac_address 字段(每个文件中有多处):

    注意: 随附的 JSON sipl_config 文件与 JP7.2 兼容。对于 JP7.1,请从 HSB 2.5.0 发布版本中拉取源文件并做必要修改。

    none 复制代码
    ../examples/sipl_config/vb1940_single.json
    ../examples/sipl_config/vb1940_dual.json
  • 允许 root 访问 X 显示(如果使用 SSH,请确保已设置 DISPLAY):

    bash 复制代码
    xhost +
  • 运行 sipl_player 应用(硬件 ISP 采集模式):

    bash 复制代码
    ./examples/sipl_player --json-config ../examples/sipl_config/vb1940_single.json
    ./examples/sipl_player --json-config ../examples/sipl_config/vb1940_dual.json
  • RAW 采集模式(未经适当 ISP 处理时图像质量较差):

    bash 复制代码
    ./examples/sipl_player --json-config ../examples/sipl_config/vb1940_single.json --raw
    ./examples/sipl_player --json-config ../examples/sipl_config/vb1940_dual.json --raw

FuSa

FuSa 是 JetPack 7.1+ 引入的新 API,它开放了对 Thor CoE 数据捕获路径的访问,但不提供 SIPL 所具备的额外相机控制与 ISP 访问能力。这使得应用可以在 CoE 加速环境中直接控制 Holoscan Sensor Bridge 及其连接的传感器,绕开对 SIPL 及其 UDDF 驱动实现的需求。这样应用就可以遵循更传统的 Holoscan Sensor Bridge 实现方式------传感器控制由应用直接管理,而不是由外部驱动管理。正因如此,基于 Holoscan Sensor Bridge 提供的现有参考驱动,IMX274、VB1940 与 TauroTech DA326 Hawk 传感器都有相应的 FuSa 示例应用。

针对 IMX274、VB1940 与 TauroTech DA326 Hawk,随附了若干以 fusa_coe_ 为前缀的 FuSa 示例应用(Hawk 变体:fusa_coe_max96716a_playerfusa_coe_hawk_single_link_playerfusa_coe_hawk_dual_link_playerfusa_coe_single_network_stereo_hawk_player)。C++ 示例应用可以原生运行(不使用容器),由上面的主机设置步骤完成构建;Python 变体则必须在 Holoscan Sensor Bridge 容器中运行。

注意: 默认情况下,python/setup.py 不会启用所需的 FuSa 或 SIPL 组件,除非它检测到必需的 /dev/coe* 设备,或设置了 COE_OFFLOAD 环境变量。在官方提供的 docker 容器中,或在受支持平台上的原生 Python 绑定构建中,均无需额外操作。

例如,运行 C++ VB1940 播放器示例时,执行以下命令(将 IP 地址替换为你的设备地址):

bash 复制代码
./examples/fusa_coe_vb1940_player --hololink 192.168.0.2
  • 在 holoscan sensor bridge 容器内构建并运行 Li VB1940、IMX274 与 TauroTech DA326 Hawk 的 Python 示例,将在用户指南后续页面中讲解。

2.5 x86 Linux

当主机是运行 Linux、配备 NVIDIA 独立显卡的 x86 PC 时,使用本节内容。

x86 上的捕获路径

  • 基于 socket 的接收器 ------ 名称以 linux_ 开头的示例(例如 linux_imx274_player)使用的标准 Linux 网络协议栈路径。它不需要 ConnectX 网卡;使用任何能到达传感器桥的以太网接口即可,IP 与 PTP 配置指引与其他主机相同。注意:此路径没有加速,往往无法跟上典型传感器(如相机)数据流所需的数据速率,会导致间歇性数据丢失。该路径主要用于开发目的。

  • RoCE 加速接收器 ------ 使用 RDMA over Converged Ethernet 连接传感器桥,要求该链路上有 Mellanox/NVIDIA ConnectX 网卡。接口设置要求(地址、路由、环形缓冲区、MTU)与 IGX 或 DGX Spark 一致:传感器桥必须能通过其分配的地址(如 192.168.0.2)到达,配置方案与上面 IGXDGX Spark 小节相同(请将 $IN0$EN0 等设备名适配到你的系统)。

RoCE 路径上的 GPUDirect RDMA

使用 RoCE 并通过 GPUDirect RDMA 写入 GPU 显存需要满足以下条件:

  • 工作站级 NVIDIA GPU(消费级与移动版 GPU 不支持 GPUDirect RDMA)。
  • 主机上安装 NVIDIA 开放内核驱动包(例如 nvidia-driver-open)。
  • ConnectX 网卡与 GPU 在 PCIe 拓扑中互为对等体(peer),使网卡能够直接对 GPU 执行 RDMA(平台固件、root port 布局与 IOMMU 设置必须允许端到端完成此操作)。

满足这些要求后,帧缓冲可以驻留在 GPU 显存中,从传感器桥接收的数据可以通过 RDMA 直接写入 GPU 显存。当 GPU 与驱动支持 GPUDirect 注册、但主机 PCIe 系统路径实际上无法将 RDMA 写操作送达该显存时,从传感器桥接收的数据实际上不会写入 GPU 显存,通常会导致数据错误(例如黑屏/空白图像帧)和/或元数据不匹配错误。如果是这种情况,必须将构建配置为强制使用锁页(pinned)主机内存(见下一节)。

x86 上的演示容器

在主机上安装 Docker、Docker Buildx 与 NVIDIA Container Toolkit。使用 dGPU 选项构建演示镜像(见「构建」一章):

bash 复制代码
sh docker/build.sh --dgpu

当 GPUDirect RDMA 无法端到端工作时

可能出现 RoCE RDMA 看似正常、但对已注册 GPU 显存的 RDMA 写操作实际并未成功的情况------例如 GPU 支持 GPUDirect,但 PCIe 配置不允许 ConnectX 网卡作为 RDMA 对等体到达 GPU。其症状包括黑屏或空白图像,以及应用日志中出现类似如下的行:

none 复制代码
ERROR 6.6634 roce_receiver.cpp:826 get_next_frame tid=0x61 -- Metadata psn=0 but received_psn=483318.

这是需要禁用 GPU VRAM 重新构建的强信号,重建后 RoCE 接收器将改用锁页主机内存:

  • 演示容器:docker/build.sh 传入 --disable-roce-gpu-vram(与往常一样同时带上 --dgpu)来构建镜像。例如:

    bash 复制代码
    sh docker/build.sh --dgpu --disable-roce-gpu-vram
  • 原生 CMake 构建: 配置时加上:

    bash 复制代码
    -DHOLOLINK_ROCE_USE_GPU_VRAM=OFF

使用锁页主机内存代替 GPU VRAM 可启用部分加速路径:网卡仍会通过 RoCE 直接 RDMA 到系统内存,绕过 Linux 网络子系统;但之后 GPU 读取这些数据时仍需经过 PCIe 传输。

当你的机器满足上述 GPUDirect RDMA 要求时,默认构建保持 HOLOLINK_ROCE_USE_GPU_VRAM 开启,即可使用完全加速的 GPUDirect RDMA 路径。该路径已在内部完成验证,验证平台为基于 AMD Threadripper 的 Lenovo ThinkStation 工作站,配备 ConnectX-6 Dx 网卡与 Quadro RTX 6000 GPU。

2.6 所有配置的通用步骤

现在,对所有配置执行:

  • 为运行非加速网络示例配置网络接收缓冲区:Holoscan sensor bridge 支持使用非加速的 Linux socket 网络运行 Li VB1940、IMX274 与 TauroTech DA326 Hawk。为了让这些示例获得最佳性能,请增大 Linux socket 的网络接收缓冲区:

    bash 复制代码
    echo 'net.core.rmem_max = 31326208' | sudo tee /etc/sysctl.d/52-hololink-rmem_max.conf
    sudo sysctl -p /etc/sysctl.d/52-hololink-rmem_max.conf
  • 确保 $EN0 被设置为连接到 HSB 的以太网控制器名称。某些安装步骤需要重启,重启会清除该变量,因此请按照上文说明针对你的配置重新正确设置。

  • $EN0 上启用 PTP。这会使接收数据所携带的时间戳与主机时间同步。

    在开机时运行 phc2sys 工具,将 $EN0 中的时钟与系统时钟同步。首先安装 linuxptp 工具:

    bash 复制代码
    sudo apt update && sudo apt install -y linuxptp

    接下来,创建一个用于运行 phc2sys 的 systemd 服务文件:

    bash 复制代码
    PHC2SYS_SERVICE=/etc/systemd/system/phc2sys-$EN0.service
    cat <<EOF | sudo tee $PHC2SYS_SERVICE >/dev/null
    [Unit]
    Description=Copy system time to $EN0
    Requires=NetworkManager.service
    After=NetworkManager.service
    After=timemaster.service
    
    [Service]
    Type=simple
    ExecStartPre=timeout 3m bash -c "until [ \"\$(nmcli -g GENERAL.STATE device show $EN0)\" = \"100 (connected)\" ]; do sleep 1; done"
    ExecStart=/usr/sbin/phc2sys -c $EN0 -s CLOCK_REALTIME -O 0 -S 0.0001
    
    [Install]
    WantedBy=multi-user.target
    EOF

    将其配置为开机自启,并立即启动:

    bash 复制代码
    sudo chmod u+x $PHC2SYS_SERVICE
    sudo systemctl enable phc2sys-$EN0.service
    sudo systemctl start phc2sys-$EN0.service

    接下来,运行 ptp4l$EN0 发送 PTP SYNC 报文:

    bash 复制代码
    cat <<EOF | sudo tee /etc/linuxptp/hsb-ptp.conf >/dev/null
    # This configuration is appropriate for NVIDIA Holoscan sensor bridge
    # applications, where PTP messages are sent over L2 and a 1/2 second interval.
    [global]
    logSyncInterval -1
    logMinDelayReqInterval -1
    network_transport L2
    EOF

    为它创建一个 systemd 服务文件:

    bash 复制代码
    PTP4L_SERVICE=/etc/systemd/system/ptp4l-$EN0.service
    cat <<EOF | sudo tee $PTP4L_SERVICE >/dev/null
    [Unit]
    Description=Send PTP SYNC messages to $EN0
    After=phc2sys-$EN0.service
    
    [Service]
    Type=simple
    ExecStart=/usr/sbin/ptp4l -i $EN0 -f /etc/linuxptp/hsb-ptp.conf
    
    [Install]
    WantedBy=multi-user.target
    EOF

    最后,运行它:

    bash 复制代码
    sudo chmod u+x $PTP4L_SERVICE
    sudo systemctl enable ptp4l-$EN0.service
    sudo systemctl start ptp4l-$EN0.service
  • 仅针对使用 CUDA 12 的 Orin iGPU 配置(Jetpack 6 与 IGX 1.X):安装 NVIDIA DLA 编译器。使用推理的应用在初始化时需要它;部分 iGPU 的 OS 镜像未包含该组件。

    bash 复制代码
    sudo apt update && sudo apt install -y nvidia-l4t-dla-compiler
  • 使用你的开发者账号登录 NVIDIA GPU Cloud(NGC):

    bash 复制代码
    docker login nvcr.io
    Username: $oauthtoken
    Password: <Your token key to NGC>
    WARNING! Your password will be stored unencrypted in /home/<user>/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    
    Login Succeeded

现在请继续阅读「构建」一章,构建并测试 Holoscan Sensor Bridge 容器。


3. 构建(Build)

3.1 构建 Holoscan Sensor Bridge 容器

Holoscan sensor bridge 主机软件包含构建演示容器的说明。该容器用于运行所有 holoscan 测试与示例。

  1. 如果还没有获取源码,请从 GitHub 拉取 sensor bridge 源代码:

    bash 复制代码
    git clone https://github.com/nvidia-holoscan/holoscan-sensor-bridge
  2. 构建 sensor bridge 演示容器。对于配备独立 GPU 且 OS 配置为 dGPU 的 IGX Orin,以及配备 NVIDIA 独立显卡的 x86_64 Linux 主机(见「主机设置」中的 x86 Linux 小节),使用 dGPU 选项;对于这里列出的其余平台,使用下面的 iGPU 选项。

    iGPU:

    bash 复制代码
    cd holoscan-sensor-bridge
    sh docker/build.sh --igpu

    dGPU:

    bash 复制代码
    cd holoscan-sensor-bridge
    sh docker/build.sh --dgpu

3.2 在演示容器中运行测试

要运行 sensor bridge 演示容器,请在 GUI 中的终端里执行:

bash 复制代码
xhost +
sh docker/demo.sh

这将带你进入 Holoscan sensor bridge 演示容器内的 shell 提示符。(注意:iGPU 配置在启动演示容器时会显示 "Failed to detect NVIDIA driver version" 的消息,可以忽略。)现在你已经可以运行 sensor bridge 应用了。

3.3 Holoscan sensor bridge 软件回环测试

Sensor bridge 主机软件包含一个以回环(loopback)模式运行的测试套件,无需任何 sensor bridge 硬件。该测试通过生成 UDP 报文并经由 Linux 回环接口发送来工作。

在演示容器内的 shell 中执行:

bash 复制代码
pytest

注意:该测试套件会有意向软件栈中注入错误。只要 pytest 显示所有测试均已通过,单个测试输出的任何错误消息都可以忽略。如果 pytest 本身报告失败,请参阅故障排查(troubleshooting)页面。

对于配备 sensor bridge 设备与 IMX274 的系统,测试套件还可以执行额外的测试,以证明设备与网络连接工作正常。

首先,确保 sensor bridge 固件是最新的。

对于 IGX 配置,将传感器桥设备上的两个 SFP+ 接口分别连接到两个 QSFP 连接器,然后执行:

bash 复制代码
sh ./test-igx-cpnx100-imx274.sh

对于 AGX Orin,只支持一路相机,因此只连接 SFP+ 0。在 AGX 上以如下方式运行设备测试:

bash 复制代码
sh ./test-agx-cpnx100-imx274.sh

如果工作不正常,请查看故障排查页面。


4. 示例(Examples)

Holoscan sensor bridge 的 Python 示例应用位于 examples 目录下。

以下是在 AGX Thor、DGX Spark、IGX 与 Jetson AGX Orin 平台上运行这些应用的说明。

4.1 选择适合平台的示例

Holoscan Sensor Bridge 支持多种硬件加速传输策略,兼容范围广泛的主机。每个示例都硬编码到特定的接收器类型;示例通过文件名前缀来标识所使用的接收算子。

RoceReceiver(ConnectX 主机)

  • 文件名中没有任何前缀的示例使用 RoCEv2 加速网络接收算子,需要配备 ConnectX 的平台,如 IGX Orin、IGX T7000 或 DGX Spark。在这些系统上,传感器模组必须连接到 ConnectX 对应的端口,而不是 RJ45 连接器。 AGX Orin、AGX Thor 与 IGX T5000 系统无法运行这些示例。
  • 对于 IGX T7000 上的加速网络示例,必须将 CUDA_VISIBLE_DEVICES 环境变量设置为与图形 GPU 配置相匹配的值,其默认为 iGPU。例如,如果配置为 dGPU 图形,imx274_player 必须将 CUDA_VISIBLE_DEVICES 设为 0,以便 RDMA 与图形都使用 dGPU。
  • 只要容器是用相应的 iGPU 或 dGPU 设置构建的,这些示例在 iGPU 与 dGPU 配置下都可以工作。

LinuxReceiver(非加速)

  • linux 开头的示例使用非加速的 Linux Sockets API 网络接收算子。这些示例可在所有系统上运行。

FusaCoeCapture(仅限 Thor MGBE)

  • fusa_coe 开头的示例使用 Thor 的 MGBE 接口上的硬件加速 CoE 能力,需要 AGX Thor 或 IGX T5000。传感器模组必须连接到主机的 QSFP MGBE 端口,而不是 RJ45 端口。

SiplCameraOutput(仅限 Thor MGBE)

  • sipl_ 开头的示例使用 SIPL 相机处理栈,需要 AGX Thor 或 IGX T5000。传感器模组必须具有 UDDF 驱动,并连接到主机的 QSFP MGBE 端口,而不是 RJ45 端口。

4.2 IMX274 播放器示例

要在配备 ConnectX 的主机上运行 IMX274 视频播放器示例,在演示容器中执行:

Python:

bash 复制代码
python3 examples/imx274_player.py

C++(需先构建,见下文 C++ 示例构建说明):

bash 复制代码
./examples/imx274_player

对于非加速主机:

bash 复制代码
python3 examples/linux_imx274_player.py

关于 IMX274 播放器应用源码的逐行解析文档可在用户指南中找到;该示例展示了架构文档中描述的基本 sensor bridge 工作流程。按 Control/C 停止视频播放器。

4.3 Leopard imaging VB1940 Eagle 播放器示例

此示例与上面的 IMX274 播放器示例类似,只是使用 LI VB1940 Eagle 相机替代 IMX274。要在 ConnectX 加速主机上运行 LI VB1940 Eagle 高速视频播放器,在演示容器中执行:

bash 复制代码
python3 examples/vb1940_player.py

对于非加速主机:

bash 复制代码
python3 examples/linux_vb1940_player.py

最后,在 AGX Thor 或 IGX T5000 上运行 SIPL 加速网络 Python 示例:

bash 复制代码
python3 ./examples/sipl_player.py --json-config ./examples/sipl_config/vb1940_single.json

4.4 MAX96716A 解串器播放器示例

TauroTech DA326 传感器桥板载有一颗 Analog Devices MAX96716A GMSL 解串器,其中内置了视频图案生成器(VPG,Video Pattern Generator)。

max96716a_player 示例驱动 VPG 从解串器的 MIPI CSI-2 输出发出合成数据流,无需任何额外硬件。

Python:

对于 ConnectX 主机:

bash 复制代码
python3 examples/max96716a_player.py

对于非加速配置:

bash 复制代码
python3 examples/linux_max96716a_player.py

对于 AGX Thor 与 T5000,使用 MGBE 与 FuSa CoE 加速接收器:

bash 复制代码
python3 examples/fusa_coe_max96716a_player.py

C++:

C++ 示例需要先构建。从仓库根目录执行:

bash 复制代码
mkdir -p build && cd build
cmake ..
make -j

生成的可执行文件位于 build/examples/。从 build/ 目录即可运行 max96716a_player 的各个变体。

对于 ConnectX 加速主机:

bash 复制代码
./examples/max96716a_player

对于非加速配置:

bash 复制代码
./examples/linux_max96716a_player

对于 AGX Thor 或 IGX T5000,使用 FuSa CoE 加速接收器:

bash 复制代码
./examples/fusa_coe_max96716a_player

4.5 Hawk 相机 + Tauro Tech DA326 播放器示例

此示例与上面的 IMX274、VB1940 播放器示例类似,使用 TauroTech DA326 传感器桥板并连接一个或多个 Hawk 相机模组。

请注意以下必需参数:

  • 单链路(single-link)应用:--channel A|B 用于选择要使用的 GMSL 链路;--sensor left|right|both 用于选择启用哪个(些)传感器的接收。
  • 双链路(dual-link)应用:--sensor left|right 用于选择启用哪一侧传感器的接收(两条 GMSL 链路都会被使用)。

运行时使用 --help 可查看完整选项列表。

Python:

对于 ConnectX 加速平台:

bash 复制代码
python3 examples/hawk_single_link_player.py

对于非加速配置:

bash 复制代码
python3 examples/linux_hawk_single_link_player.py

对于 AGX Thor 或 T5000 MGBE,使用 FuSa CoE 加速接收器:

bash 复制代码
python3 examples/fusa_coe_hawk_single_link_player.py

对于通过 DA326 的两个 GMSL 连接器接入两个 Hawk 模组的情况,还提供双链路变体。

对于 ConnectX 加速平台:

bash 复制代码
python3 examples/hawk_dual_link_player.py

对于非加速配置:

bash 复制代码
python3 examples/linux_hawk_dual_link_player.py

对于 AGX Thor 或 IGX T5000,使用 FuSa CoE 加速接收器:

bash 复制代码
python3 examples/fusa_coe_hawk_dual_link_player.py

C++:

C++ 示例需要先构建。从仓库根目录执行:

bash 复制代码
mkdir -p build && cd build
cmake ..
make -j

生成的可执行文件位于 build/examples/。从 build/ 目录即可运行 Hawk 播放器的各个变体。

对于 ConnectX 加速平台:

bash 复制代码
./examples/hawk_single_link_player

对于非加速主机:

bash 复制代码
./examples/linux_hawk_single_link_player

对于 AGX Thor 或 T5000,使用 FuSa CoE 加速接收器:

bash 复制代码
./examples/fusa_coe_hawk_single_link_player

对于通过 DA326 的两个 GMSL 连接器接入两个 Hawk 模组的情况,双链路变体:

对于 ConnectX 加速平台:

bash 复制代码
./examples/hawk_dual_link_player

对于非加速主机:

bash 复制代码
./examples/linux_hawk_dual_link_player

对于 AGX Thor / T5000,使用 FuSa CoE 加速接收器:

bash 复制代码
./examples/fusa_coe_hawk_dual_link_player

4.6 运行 TAO PeopleNet 示例

tao-peoplenet 示例演示了对实时视频流运行推理。TAO PeopleNet 提供的模型可以在给定图像中检测行人、包和人脸。在此示例中,当检测到这些目标时,会在实时视频上叠加显示边界框。

注意:元数据传递在与 InferenceOp 一起使用时存在一个未解决问题,因此这些示例的应用中显式禁用了它。

前提条件:从 NGC 网站下载 PeopleNet ONNX 模型:

bash 复制代码
wget --content-disposition 'https://api.ngc.nvidia.com/v2/models/org/nvidia/team/tao/peoplenet/pruned_quantized_decrypted_v2.3.3/files?redirect=true&path=resnet34_peoplenet_int8.onnx' -O examples/resnet34_peoplenet_int8.onnx

对于配备 ConnectX 加速网络控制器接口、使用 IMX274 相机的系统:

bash 复制代码
python3 examples/tao_peoplenet.py

对于使用 IMX274 相机的非加速配置:

bash 复制代码
python3 examples/linux_tao_peoplenet.py

最后,在 AGX Thor 上使用 LI VB1940 相机运行 SIPL 加速网络 Python 示例:

bash 复制代码
python3 ./examples/sipl_tao_peoplenet.py --json-config ./examples/sipl_config/vb1940_single.json

这将在 GUI 中启动 Holoscan 可视化器,显示来自 IMX274/Li VB1940 设备的实时视频流;当捕获到人物图像时,会叠加显示红/绿边界框。按 Ctrl/C 退出。关于此应用的更多信息请参阅用户指南相应页面。

4.7 运行人体姿态(body pose)示例

前提条件:从 YOLOv8 网站下载 YOLOv8 ONNX 模型并生成人体姿态 ONNX 模型。在 Holoscan sensor bridge 演示容器内执行:

注意: 运行 Jetpack 7.2 的原厂 AGX Orin 开发套件可能没有足够磁盘空间安装依赖。在安装下面的 Python 依赖之前,请通过清理未使用的软件包或 docker builder 缓存来确保有充足的磁盘空间。

从仓库根目录 holoscan-sensor-bridge 执行:

bash 复制代码
apt-get update && apt-get install -y ffmpeg
pip3 install ultralytics onnx
cd examples
yolo export model=yolov8n-pose.pt format=onnx
trtexec --onnx=yolov8n-pose.onnx --saveEngine=yolov8n-pose.engine.fp32
cd -

注意,此转换步骤只需执行一次:yolov8n-pose.engine.fp32 文件包含转换后的模型,是运行演示所需的全部内容。已安装的组件会在容器退出后被遗忘;之后再次运行演示时不需要这些组件。

对于 ConnectX 加速主机,在 sensor bridge 演示容器内启动使用 IMX274 相机的人体姿态估计:

bash 复制代码
python3 examples/body_pose_estimation.py

对于非加速主机,在演示容器内以如下方式启动人体姿态估计示例:

bash 复制代码
python3 examples/linux_body_pose_estimation.py

最后,在 AGX Thor 上使用 Li VB1940 相机运行 SIPL 加速网络 Python 示例:

bash 复制代码
python3 ./examples/sipl_body_pose_estimation.py --json-config ./examples/sipl_config/vb1940_single.json

这将在 GUI 中启动 Holoscan 可视化器,显示来自 IMX274/Li VB1940 设备的实时视频流,并以绿色叠加层显示人体姿态网络模型找到的关键点。关于此应用的更多信息请参阅用户指南相应页面。

按 Ctrl/C 退出。

4.8 运行立体 IMX274、Leopard imaging Li VB1940 Eagle 与 TauroTech DA326 Hawk 示例

stereo_imx274_player.py 示例展示了两条独立的流水线,分别对应双摄像头模组上的每一路相机。请确保主机与 Holoscan sensor bridge 设备之间的两个网络端口都已连接。

bash 复制代码
python3 examples/stereo_imx274_player.py

这将启动一个包含两帧画面的可视化器显示,一帧为左通道,另一帧为右通道。

为了汇聚较低带宽的数据流,你可以参考以下将两路相机汇聚到单个网络端口的示例:

ConnectX 加速主机 + IMX274:

bash 复制代码
python3 examples/single_network_stereo_imx274_player.py

非加速主机 + IMX274:

bash 复制代码
python3 examples/linux_single_network_stereo_imx274_player.py

ConnectX 加速主机 + Li VB1940 Eagle:

bash 复制代码
python3 examples/single_network_stereo_vb1940_player.py

非加速主机 + Li VB1940 Eagle:

bash 复制代码
python3 examples/linux_single_network_stereo_vb1940_player.py

AGX Thor 或 IGX T5000 上使用 Li VB1940 相机的 SIPL Python 示例:

bash 复制代码
python3 ./examples/sipl_player.py --json-config ./examples/sipl_config/vb1940_dual.json

使用 TauroTech DA326 传感器桥与 Hawk 相机模组时,Hawk 上的两个 AR0234 传感器共用一条通往 DA326 板载解串器的 GMSL 链路;single_network_stereo_hawk_player 示例将它们汇聚到 DA326 的 SFP+ 端口:

ConnectX 加速主机 + TauroTech DA326 Hawk:

bash 复制代码
python3 examples/single_network_stereo_hawk_player.py --channel A|B

非加速主机 + TauroTech DA326 Hawk:

bash 复制代码
python3 examples/linux_single_network_stereo_hawk_player.py --channel A|B

AGX Thor + TauroTech DA326 Hawk,使用 FuSa CoE 加速接收器:

bash 复制代码
python3 examples/fusa_coe_single_network_stereo_hawk_player.py --channel A|B

希望将传感器映射到特定数据通道的应用,可以使用 use_sensor API,这些示例中对此做了演示。许多主机将网络带宽限制为 10Gbps,因此仅支持以 1080p 模式观察立体视频。

4.9 TSN IMX274 播放器示例

examples/linux_tsn_imx274_player.py 在 Linux IMX274 播放器的基础上扩展了时间敏感网络(TSN,Time-Sensitive Networking)支持。它在传感器虚拟端口与 EVT 通道上配置 802.1Q VLAN 标记,并在启动流水线之前对 FPGA 的 PTP 引擎进行编程。此示例可在所有支持 Linux Receiver 的平台上运行(AGX Orin、AGX Thor、DGX Spark 与 IGX)。

主机网络前提条件

在运行播放器之前,主机网卡上必须已存在 VLAN 子接口,并且传感器桥 IP 必须分配到该子接口上,以便内核将带 VLAN 标记的帧递交给 UDP socket:

bash 复制代码
# 创建 VLAN 子接口(将 <iface> 与 <vlan-id> 替换为与你设置相匹配的值)
sudo ip link add link <iface> name <iface>.<vlan-id> type vlan id <vlan-id>
sudo ip link set <iface>.<vlan-id> up

# 将传感器桥 IP 分配到该子接口
sudo ip addr add 192.168.0.101/32 dev <iface>.<vlan-id>

这些命令在重启后不会保留。请将它们加入启动脚本或网络管理器配置中以使其永久生效。

主机 PTP 服务

--ptp-profile 参数控制 FPGA 被编程为使用哪种 PTP 规范(profile)。主机 PTP 守护进程必须与之匹配。一共使用两个 systemd 服务------同一时间只应运行其中一个:

--ptp-profile Profile 需运行的主机服务
1(默认) gPTP (IEEE 802.1AS) gptp4l-<iface>.service
0 IEEE 1588 E2E ptp4l-<iface>.service

默认的主机设置会创建并启动 ptp4l-<iface>.service(IEEE 1588 E2E)。如需使用 gPTP,请按如下方式一次性创建该服务(将 <iface> 替换为你的网卡名,例如 enP5p3s0f0np0):

bash 复制代码
# 创建 gPTP 配置文件
cat <<EOF | sudo tee /etc/linuxptp/gptp.conf >/dev/null
[global]
gmCapable               1
priority1               100
priority2               100
domainNumber            0
logAnnounceInterval     0
logSyncInterval         -3
syncReceiptTimeout      3
assume_two_step         1
path_trace_enabled      1
follow_up_info          1
transportSpecific       0x1
ptp_dst_mac             01:80:C2:00:00:0E
network_transport       L2
delay_mechanism         P2P
EOF

# 创建 systemd 服务单元
GPTP4L_SERVICE=/etc/systemd/system/gptp4l-<iface>.service
cat <<EOF | sudo tee $GPTP4L_SERVICE >/dev/null
[Unit]
Description=Send gPTP (802.1AS) on <iface>
After=phc2sys-<iface>.service

[Service]
Type=simple
ExecStart=/usr/sbin/ptp4l -i <iface> -f /etc/linuxptp/gptp.conf

[Install]
WantedBy=multi-user.target
EOF

sudo chmod u+x $GPTP4L_SERVICE
sudo systemctl daemon-reload
sudo systemctl enable gptp4l-<iface>.service

切换到 gPTP:

bash 复制代码
sudo systemctl stop ptp4l-<iface>.service
sudo systemctl start gptp4l-<iface>.service
journalctl -u gptp4l-<iface>.service -f   # 等待出现 LOCKED

切换到 IEEE 1588 E2E:

bash 复制代码
sudo systemctl stop gptp4l-<iface>.service
sudo systemctl start ptp4l-<iface>.service
journalctl -u ptp4l-<iface>.service -f   # 等待出现 grandmaster 或 LOCKED

注意:按照 802.1AS 规范,gPTP 报文不带 VLAN 标记,因此无论 VLAN 如何配置,gPTP 服务都运行在物理接口上。

运行示例

bash 复制代码
python3 examples/linux_tsn_imx274_player.py

默认情况下,播放器使用 gPTP(IEEE 802.1AS,profile 1)、VLAN ID 2、传感器 PCP 6、EVT PCP 4。所有这些都可以在命令行覆盖:

bash 复制代码
# 使用 IEEE 1588 E2E profile 代替 gPTP
python3 examples/linux_tsn_imx274_player.py --ptp-profile 0

# 覆盖 VLAN ID 与 PCP 值
python3 examples/linux_tsn_imx274_player.py --vlan-id 10 --sensor-pcp 5 --evt-pcp 3

# 覆盖 PTP 域编号
python3 examples/linux_tsn_imx274_player.py --ptp-domain 1

完整选项参考:

选项 默认值 说明
--ptp-profile 1 PTP profile:0 = IEEE 1588 E2E,1 = gPTP (IEEE 802.1AS),2 = IEEE 1588 P2P
--ptp-domain 0 与主机 PTP 守护进程匹配的 PTP 域编号
--vlan-id 2 与交换机和主机子接口匹配的 12 位 VLAN ID
--sensor-pcp 6 传感器数据流量的优先级码点(PCP)
--evt-pcp 4 FPGA 事件通知的优先级码点(PCP)
--camera-mode 0 IMX274 传感器模式
--headless 无显示运行
--frame-limit 收到 N 帧后退出

关于源码的详细解析,请参阅用户指南中的 TSN IMX274 播放器应用章节。

4.10 RoCE TSN IMX274 播放器示例

examples/tsn_imx274_player.py 是 TSN IMX274 播放器的 RoCE 变体。它使用相同的 VLAN 与 PTP 配置,但数据经由 RoCE v2 而非 Linux socket 发送。由于 ConnectX 网卡会在硬件中剥离 VLAN 标记,因此无需主机 VLAN 子接口--------vlan-id--sensor-pcp--evt-pcp--ptp-profile--ptp-domain 选项的用法与 Linux TSN 播放器相同。

bash 复制代码
python3 examples/tsn_imx274_player.py

4.11 运行 GPIO 示例

examples/gpio_example_app.py 是一个使用传感器桥 GPIO 接口的简单示例,演示如何设置 GPIO 方向、读取 GPIO 引脚输入值以及向 GPIO 引脚写入输出值。运行该应用:

bash 复制代码
python3 examples/gpio_example_app.py

这会启动一个文本显示界面,循环切换不同的预设引脚配置,并在不同引脚设置之间留出时间,以便测量或回读引脚值。关于 GPIO 示例应用的更多信息,请参阅用户指南中的应用结构章节。

4.12 使用 Jetson 硬件 ISP 的示例

examples/linux_hwisp_player.py 展示了用 Jetson 硬件 ISP 单元处理由 IMX274 实时采集的 Bayer 帧的示例。此示例支持 iGPU 配置下的 Jetson Orin AGX 与 IGX Orin 700。此示例不支持 AGX Thor;关于硬件 ISP 的用法请参考 SIPL 示例。

在启动 docker 运行之前,先以 enableRawReprocessing=1rawReprocessModulePartName="A6V26" 标志设置 nvargus-daemon。这使我们能够用 ISP 处理由 Holoscan sensor bridge 设备采集的 imx274 Bayer 帧,且该更改在重启后依然保持。在主机系统中执行:

bash 复制代码
sudo su
pkill nvargus-daemon
export enableRawReprocessing=1
export rawReprocessModulePartName="A6V26"
nvargus-daemon
exit

要运行该示例,在演示容器内执行:

bash 复制代码
python3 examples/linux_hwisp_player.py

这将运行带可视化显示的应用,展示实时采集画面。注意,自 Jetpack 6 起默认相机模式已更改,现在默认为 4K 帧。此示例兼容 Jetpack 7.2+。

注意:如果用户希望撤销以 enableRawReprocessing=1 标志运行 nvargus-daemon 的设置,请执行以下命令:

bash 复制代码
sudo su
pkill nvargus-daemon
unset enableRawReprocessing
unset rawReprocessModulePartName
nvargus-daemon
exit

4.13 运行 IMX274 延迟(Latency)应用示例

对于 IGX 系统,examples/imx274_latency.py 展示了如何使用时间戳对硬件与软件流水线进行性能剖析。此示例演示了记录 FPGA 在数据采集时发出的时间戳,以及在帧接收与流水线执行的各个点上于主机侧测量的时间戳。运行结束时,应用将输出一份包含平均值、最小值与最大值的时长与延迟报告。

在运行该应用之前,请确保已在你的设置上启用 PTP 同步,然后使用以下命令运行示例:

bash 复制代码
python3 examples/imx274_latency.py

在非加速主机上运行延迟示例应用:

bash 复制代码
python3 examples/linux_imx274_latency.py

此示例无法在 AGX Thor 上运行。

4.14 运行 ECam0M30ToF 播放器应用

ecam0m30tof_player.py 应用演示了如何采集并显示来自 ECam0M30ToF 飞行时间(ToF)相机的深度和/或红外(IR)数据,使用 RoCE(RDMA over Converged Ethernet)实现高性能数据传输,并利用 Holoviz 算子的 DEPTH_MAP 渲染增强深度可视化效果。通过将接收算子从 RoceReceiverOp 改为 LinuxReceiverOperator,可以修改此应用使其在 Jetson AGX 上运行。

前提条件:ECam0M30ToF 相机已连接到 Hololink 设备。

运行该应用使用以下命令:

bash 复制代码
python3 examples/ecam0m30tof_player.py --hololink 192.168.0.2 --camera-mode=<0|1|2>

相机配置

  • --camera-mode:选择相机模式(0:DEPTH_IR,1:DEPTH,2:IR

此示例无法在 AGX Thor 上运行。

4.15 运行 CPU 与 GPU 帧校验示例

帧校验示例演示了如何访问帧元数据,以检测丢帧、帧时间戳错位和帧 CRC 错误。这些示例记录 FPGA 在数据采集时发出的时间戳、帧号与 CRC32 数据。运行期间,丢帧、时间戳错位与 CRC32 错误会被检测并报告。运行结束时,应用会输出一份包含平均值、最小值与最大值的时长与延迟报告。这些数值在应用运行期间收集,用于评估各种检测机制对流水线延迟的影响。

IMX274

Linux 接收器

对于非加速配置,examples/linux_imx274_frame_validation.py 使用标准 Linux socket 进行网络通信,并采用基于 CPU 的 CRC 校验。

在运行该应用之前,请在你的设置上启用 PTP 同步,然后使用以下命令运行示例。在 AGX Orin 系统上运行帧校验示例:

bash 复制代码
python3 examples/linux_imx274_frame_validation.py

由于此示例中的 CRC32 计算由 CPU 完成,按原样使用该示例检测 CRC32 错误会引发丢帧错误。因此 CRC32 错误检测默认未启用。要每 N 帧启用一次 CRC32 检测,使用 --crc-frame-check 选项:

bash 复制代码
python3 examples/linux_imx274_frame_validation.py --crc-frame-check 50

在此示例中,应用将每 50 帧检查一次 CRC32 帧错误。

RoCE 接收器

对于 ConnectX 加速平台,examples/imx274_frame_validation.py 提供高性能帧校验,使用 nvCOMP 5.0 实现 GPU 加速 CRC 检查。此示例使用加速网络接收算子,需要 ConnectX SmartNIC 控制器。

在运行该应用之前,请在你的设置上启用 PTP 同步,然后使用以下命令:

bash 复制代码
python3 examples/imx274_frame_validation.py

与 Linux 版本中基于 CPU 的 CRC 校验不同,使用 nvCOMP 5.0 的 GPU 加速 CRC 速度足够快,默认即可校验每一帧。CRC 校验默认以 --crc-frame-check 1 启用。要完全禁用 CRC 校验,使用 --crc-frame-check 0

执行结束时,应用会输出一份 CRC 校验报告,显示已处理的总帧数、检测到的 CRC 错误数与成功率,随后是包括帧时间、传输延迟、算子延迟与处理时间在内的详细性能指标。

要校验立体相机配置:

bash 复制代码
python3 examples/stereo_imx274_frame_validation.py
性能

在 IGX-dGPU 上、单相机 4K 分辨率配置下,nvCOMP CRC 计算性能(基于 1000 帧测量):

none 复制代码
Minimum: 275 us
Maximum: 390 us
Average: 295 us

关于启动性能的说明: HSDK 流水线在启动时的运行时性能可能不稳定,通常是由于 GPU 内核初始化。这很可能导致 CRC 校验失败:当流水线慢于相机帧率时,接收缓冲可能被新数据覆盖,从而触发 CRC 检查所要发现的那种失败。一旦流水线完全初始化并能跟上接收数据的速度,就不应再出现这些错误。我们主要在立体相机场景中观察到该问题。因此,我们的测试(见 tests/test_module_imx274_pattern.py)在开始时跳过 CRC 检查,例如仅在收到 15 帧之后才开始检查。用户应用很可能也会采用类似的启动阶段处理,以避免因这一已知情况产生误导性错误。

此示例无法在 AGX Thor 上运行。

Li VB1940 Eagle

FUSA CoE 接收器(nvCOMP)

对于 AGX Thor 与 T5000,examples/vb1940_fusa_nvcomp_crc_validation.py 提供高性能帧校验,使用 nvCOMP 5.0 实现 GPU 加速 CRC 检查。此示例使用 FUSA CoE 捕获算子实现加速网络数据传输。

在运行该应用之前,请在你的设置上启用 PTP 同步,然后使用以下命令:

bash 复制代码
python3 examples/vb1940_fusa_nvcomp_crc_validation.py

使用 nvCOMP 5.0 的 GPU 加速 CRC 速度足够快,默认即可校验每一帧。应用在完整 CSI 帧(包括 CSI 头与尾部字节)上计算 CRC,以匹配相机 FPGA 的 CRC 计算方式。

执行结束时,应用会输出一份 CRC 校验报告,显示已处理的总帧数、检测到的 CRC 错误数与成功率,随后是包括帧时间、FUSA 捕获延迟、算子延迟与处理时间在内的详细性能指标。

性能

在 AGX Thor 上、Li VB1940 Eagle 相机配置下,nvCOMP CRC 计算性能(基于 1000 帧测量):

none 复制代码
Minimum: 554.4 us
Maximum: 631.0 us
Average: 614.3 us

4.16 运行 PVA 帧校验示例

PVA CRC 校验示例演示了使用 NVIDIA PVA(可编程视觉加速器,Programmable Vision Accelerator)进行硬件加速 CRC 计算来校验相机帧。这些示例将 PVA 计算出的 CRC 值与相机 FPGA 内嵌的 CRC 值进行比对,以检测数据损坏。

关于要求与构建说明,请参阅 PVA CRC README。

要运行 PVA CRC 校验示例,首先设置 LD_LIBRARY_PATH 环境变量(运行任何应用之前都必须设置)。在演示容器内执行:

bash 复制代码
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/aarch64-linux-gnu/tegra/:/opt/nvidia/pva-sdk-2.9/lib/aarch64-linux-gnu/:/usr/lib/aarch64-linux-gnu/nvidia

在 ConnectX 加速系统上运行 IMX274 PVA CRC 校验示例:

bash 复制代码
python3 examples/imx274_pva_crc_validation.py --frame-limit 100

在 AGX Thor 或 IGX T5000 上运行 Li VB1940 Eagle PVA CRC 校验示例:

bash 复制代码
python3 examples/vb1940_fusa_pva_crc_validation.py --frame-limit 100

性能

IMX274

在 IGX-dGPU 上、单相机 4K 分辨率配置下,PVA CRC 计算性能(基于 1000 帧测量):

none 复制代码
Minimum: 412 us
Maximum: 442 us
Average: 414 us
Li VB1940 Eagle

在 AGX Thor 上、单相机 1080p 分辨率配置下,PVA CRC 计算性能(基于 1000 帧测量):

none 复制代码
Minimum: 106 us
Maximum: 137 us
Average: 111 us

4.17 运行 UART 双板示例

examples/uart_dual_board_loopback.py 测试两块板之间的 UART 通信。

硬件设置:将板 1 的 GPIO 10(TX)连接到板 2 的 GPIO 11(RX),并将板 2 的 GPIO 10(TX)连接到板 1 的 GPIO 11(RX)。引脚位置请参阅 Lattice Bajoran 板 GPIO 引脚位置说明。

支持两种模式:单向tx/rx),一块板发送、另一块接收;以及 dual,两块板同时收发。

单向(tx/rx)------一板发送,一板接收:

bash 复制代码
# 终端 1(接收方):
python3 examples/uart_dual_board_loopback.py --mode rx --hololink 192.168.2.2

# 终端 2(发送方):
python3 examples/uart_dual_board_loopback.py --mode tx --hololink 192.168.0.2

Dual 模式------两块板同时收发:

bash 复制代码
# 终端 1(板 1):
python3 examples/uart_dual_board_loopback.py --mode dual --hololink 192.168.0.2 --test-string "HELLO" --expected-rx-string "WORLD"

# 终端 2(板 2):
python3 examples/uart_dual_board_loopback.py --mode dual --hololink 192.168.2.2 --test-string "WORLD" --expected-rx-string "HELLO"

传入 --modetxrxdual)、--hololink 指定各板 IP;在 dual 模式下还可选 --test-string--expected-rx-string--flow-control。运行 --help 查看全部选项。

UART FIFO 大小为 256 字节。两个应用都会相应地对数据分块,并校验发送与接收的数据是否一致。

4.18 运行 I2S 音频采集示例

这两个示例从板卡采集 I2S 音频并通过 ALSA 播放(可选写入 WAV 文件)。它们走 I2S 接收(RX)路径;板载数字麦克风(DMIC)驱动 I2S 时隙。

设置:使用演示启动脚本在主机上运行,该脚本会启动挂载了 PulseAudio 的演示容器,使解码后的音频从主机的扬声器或耳机播放出来。

RoCE 接收器

examples/audio_recorder.py 将音频流式传输到 ConnectX 加速主机。

bash 复制代码
# 实时播放:
sh docker/demo.sh python3 examples/audio_recorder.py

# 边播放边录制到 WAV 文件,2000 帧后停止:
sh docker/demo.sh python3 examples/audio_recorder.py --output capture.wav --frame-limit 2000

# 仅采集(不播放):
sh docker/demo.sh python3 examples/audio_recorder.py --no-playback --output capture.wav

传入 --hololink 指定板卡 IP;--sensor 选择 I2S 传感器索引(hololink-lite 上默认为 2;其他板卡可能不同);--output 写入小端立体声 WAV;--frame-limit 在 N 帧后停止(省略则一直运行直到 Ctrl-C 中断);--no-playback 仅采集;--alsa-device 选择输出设备。运行 --help 查看全部选项。

音频以 48kHz 立体声 32 位 PCM 格式交付。两个 I2S 时隙作为立体声对转发(时隙 0 -> 左声道,时隙 1 -> 右声道);当 DMIC 只驱动一个时隙时,另一个时隙携带总线上当前的任意数据,并出现在相应声道中。

FuSa CoE(MGBE)接收器

examples/audio_recorder_fusa.py 将音频流式传输到 AGX Thor 或 IGX T5000。

bash 复制代码
# 实时播放:
sh docker/demo.sh python3 examples/audio_recorder_fusa.py

# 边播放边录制到 WAV 文件,2000 帧后停止:
sh docker/demo.sh python3 examples/audio_recorder_fusa.py --output capture.wav --frame-limit 2000

# 仅采集(不播放):
sh docker/demo.sh python3 examples/audio_recorder_fusa.py --no-playback --output capture.wav

参数含义同上。音频同样以 48kHz 立体声 32 位 PCM 格式交付;两个 I2S 时隙作为立体声对转发(时隙 0 -> 左声道,时隙 1 -> 右声道);当 DMIC 只驱动一个时隙时,另一个时隙携带总线上当前的任意数据,并出现在相应声道中。

4.19 子帧处理(Sub-Frame Processing)示例

子帧处理允许高分辨率传感器数据帧在到达时被逐步处理与显示,从而降低延迟并实现渐进式显示。关于子帧处理工作原理的详细信息,请参阅用户指南中的子帧处理应用章节。

IMX274 子帧播放器示例

子帧 IMX274 播放器示例演示了以子帧(而非完整帧)为单位处理与显示相机帧。这为高分辨率相机实现了更低延迟的可视化。

Python:

bash 复制代码
# 使用 ConnectX 加速网络控制器
python3 examples/sub_frame_imx274_player.py --sub-frame-rows 540

# 非加速配置(例如 AGX Orin、AGX Thor)
python3 examples/linux_sub_frame_imx274_player.py --sub-frame-rows 540

C++(构建后):

bash 复制代码
# 使用 ConnectX 加速网络控制器
./examples/sub_frame_imx274_player --sub-frame-rows 540

# 非加速配置
./examples/linux_sub_frame_imx274_player --sub-frame-rows 540

--sub-frame-rows 参数指定每个子帧的行数。

注意: sub_frame_rows 必须能整除帧高。例如,有效值为 --sub-frame-rows 540(2160 ÷ 540 = 4 个子帧)。

VB1940 子帧可视化器示例

子帧 VB1940 播放器示例演示了使用 SubFrameVisualizerOp 进行与显示同步的采集的子帧处理。子帧在到达时被逐步可视化:每个子帧被合成到其在显示帧中的位置,而无需等待完整帧完成。采集时序通过 FPGA PTP/PPS 输出与显示刷新同步,从而最小化端到端延迟。

bash 复制代码
$BUILD_DIR/examples/sub_frame_vb1940_player --sub-frame-rows 248

--sub-frame-rows 参数指定每个子帧的行数。VB1940 默认模式为 2560×1984 @ 60fps。

注意: sub_frame_rows 必须能整除帧高。对于 1984 行,有效值包括 248(8 个子帧)、496(4 个子帧)和 992(2 个子帧)。

其他选项:

  • --fullscreen:全屏模式运行(默认:true)
  • --exclusive-display:使用独占显示模式以降低延迟
  • --camera-mode :选择 VB1940 传感器模式(默认:VB1940_MODE_2560X1984_60FPS
  • --use-sensor:连接两个传感器时选择传感器索引(0 或 1,默认:0)
  • --frame-limit:收到指定帧数后退出(默认:一直运行)

关于与显示同步采集的工作原理,请参阅应用指南中的 SubFrameVisualizerOp 详细说明。

子帧处理模式

子帧示例支持两种显示模式:

  • 子帧合成器模式 (IMX274 示例):子帧由 SubFrameCombinerOp 累积成完整帧缓冲后,再传给 HolovizOp 显示。采集时序独立于显示刷新率。

  • 子帧可视化器模式 (VB1940 示例):子帧在到达时由 SubFrameVisualizerOp 直接合成到显示上。采集通过 PTP/PPS 与显示 FPO(First Pixel Out,首像素输出)事件同步,因此每次显示刷新都展示最新可用数据,延迟最小。

子帧配置参数

  • sub_frame_rows :每个子帧的行数。设为 0 则禁用子帧处理(完整帧模式)。必须能整除帧高。

性能考量

  • 内存 :更小的子帧可降低内存需求,但会增加处理开销。SubFrameCombinerOp 会等待所有子帧到达后再输出完整帧;若某个子帧丢失且下一帧已开始,则会输出一个不完整的帧。

  • 网络:子帧大小应与网络数据包大小对齐,以尽量减少不完整的子帧并提升效率。


相关推荐
小孔龙2 小时前
Android GPU 渲染管线:一帧画面如何走上屏幕
android·性能优化·gpu
Eloudy2 天前
RFSoC-PYNQ → RK-XCKU5P-F 移植记录
fpga
tiantianuser2 天前
NVME-oF IP 设计10:设计目标是什么?
rdma·高速传输·cmac·roce v2·nvme of
tiantianuser2 天前
NVME-oF IP 设计11 : 控制面与数据面干什么用?
网络协议·rdma·高速传输·roce v2·nvme of
Eloudy2 天前
ubuntu 22.04安装 Mellanox 的 MFT 工具包
rdma
mounter6253 天前
高性能网络技术演进与创新探索:RDMA、eBPF/XDP 深度解析及 LSF/MM/BPF 2023 专题演讲
linux·ebpf·linux kernel·kernel·rdma·xdp
ARM+FPGA+AI工业主板定制专家3 天前
国产化RK3576+FPGA架构|晶圆传输机器人高速定位+AI瑕疵检测一体化方案
fpga开发·架构·机器人·嵌入式·fpga·工控·机器人运控
吴佳浩3 天前
一文讲透AI算力单位:TFLOPS、PFLOPS、TOPS、稀疏算力,到底怎么算、怎么比?
人工智能·ai编程·gpu
VNDR3 天前
vLLM 在 RTX 4060 上的推理性能调优全记录
gpu