←新闻详情

NVIDIA Developer · Generative AI更新于 10月27日 19:16

NVIDIA Isaac ROS 5.0 如何用 AI 智能体加速 ROS 2 节点

Accelerating a ROS 2 Node with an AI Agent and NVIDIA Isaac ROS | NVIDIA Technical Blog

AI 导读

NVIDIA 在 ROS Lyrical 中贡献的 rosidl::Buffer 与 CUDA buffer backend 让 ROS 2 节点在运行时条件允许时以零拷贝方式交换 GPU 常驻数据,同时保留标准 ROS 2 消息与节点边界,Isaac ROS 5.0 的全部节点已改用该 CUDA buffer backend。文章以 Depth Anything 3 TensorRT ROS 2 节点为迁移示例,由 AI 编码智能体借助 migrate-node-to-rosidl-buffer 技能完成审计、最小化接口保持重构,并用 NVIDIA Nsight Systems 验证 ROS 边界不再出现负载大小的主机-设备传输。

正文 · AI 翻译

技术博客

sessionStorage.removeItem('facets.search.text'); sessionStorage.removeItem('facets.search.text-copy'); sessionStorage.removeItem('facets.search.filters');

借助 AI 智能体与 NVIDIA Isaac ROS 加速 ROS 2 节点

2026年9月22日

rosidl::Buffer 与 NVIDIA 贡献的 CUDA buffer backend 使 ROS 2 节点能够在运行时条件允许时通过零拷贝传输交换 GPU 常驻负载,同时保留标准 ROS 2 消息与节点边界。NVIDIA Isaac ROS 5.0 中的所有节点均已更新为使用 CUDA buffer backend,以实现更高效的数据移动。AI 编码智能体使用 migrate-node-to-rosidl-buffer 技能来审计一个 CUDA 加速节点、追踪数据移动、规划最小化的接口保持重构,并验证 CUDA 传输路径已启用。Depth Anything 3 TensorRT ROS 2 节点演示了此次迁移:订阅选项接受 CUDA 支持的缓冲区,TensorRT 推理将结果直接写入 CUDA 缓冲区支持的消息存储,而可选的 CPU 工作则与优化后的发布路径保持分离。验证使用 NVIDIA Nsight Systems 确认 ROS 边界处不存在负载大小的主机-设备传输,并检查当两端均满足要求时 msg->data.get_backend_type() 报告为 "cuda"。后续步骤:下载 NVIDIA Isaac ROS 5.0 以获取加速的机器人软件栈。查阅 ROS 2 Lyrical rosidl::Buffer 与 CUDA buffer backend 文档以了解上游能力。安装本文使用的 migrate-node-to-rosidl-buffer 智能体技能。

由 NVIDIA Nemotron 提供支持。AI 生成的内容可能不完整地概括信息。请核实重要信息。了解更多

GPU 加速可以加快计算密集型机器人工作负载,但仅靠快速的 CUDA 内核并不能保证快速的 ROS 2 图。当消息在节点之间移动时,它们可能继续被序列化或通过 CPU 内存复制,从而削弱将感知和 AI 工作负载保留在 GPU 上的优势(图 1)。

借助上游的 rosidl::Buffer 抽象以及 NVIDIA 近期贡献给 ROS Lyrical 的 CUDA buffer backend,ROS 2 节点可以在运行时条件允许时通过零拷贝传输交换 GPU 常驻负载,同时保留标准 ROS 2 消息与节点边界。NVIDIA Isaac ROS 5.0 中的所有节点均已更新为使用 CUDA buffer backend,并受益于 rosidl::Buffer 所实现的更高效数据移动。

现有的 ROS 2 节点只需极少改动即可采用 rosidl::Buffer。更具挑战性的任务是确定需要更新的正确边界。这需要对内存分配、序列化、流所有权和回退行为进行仔细审计。

本教程将引导您把该审计转化为由智能体驱动的工作流。AI 编码智能体使用专门构建的 migrate-node-to-rosidl-buffer 技能来检查现有的 CUDA 加速节点、追踪数据移动、规划最小化的接口保持重构,并验证 CUDA 传输路径确实已启用。您将学习如何使用该智能体技能更新节点以采用 CUDA buffer backend。由此得到的加速工作负载随后可部署在 NVIDIA Jetson AGX Thor 上。

在 ROS 2 Lyrical 中,诸如 uint8[] 之类的可变长度原始类型数组字段在生成的 C++ 代码中由 rosidl::Buffer 表示。默认的 CPU 支持的 rosidl::Buffer 行为类似于现有 ROS 2 代码所期望的 std::vector 接口,从而保持源代码兼容性。该可插拔抽象还允许平台供应商支持外部管理的存储,而无需定义单独的 ROS 消息类型。

图 1. 消息经由非 CUDA buffer backend 加速的 ROS 2 图的典型路径

图 2. 新的 CUDA buffer backend 为 ROS 开发者简化了整个流水线中的 CUDA 加速

rosidl::Buffer 与 CUDA buffer backend 共同将内存共享和数据生命周期管理置于标准 ROS 2 字段之后。这意味着该上游能力更易于在 GPU 加速的机器人应用中采用,因此您可以专注于节点逻辑,同时为不兼容的对端保留 CPU 回退。

本教程以 Depth Anything 3 (DA3) TensorRT ROS 2 节点为例。DA3 模型可从任意数量的视觉输入中预测空间一致的几何结构,无论是否已知相机位姿。

我们的目标是更新该节点以采用所引入的 CUDA buffer backend,从而利用 rosidl::Buffer 特性带来的性能提升。该节点作为迁移示例特别有用,因为其算法已经过 GPU 加速。

该节点的回调将传入的 ROS 图像转换为 OpenCV 视图,使用 NVIDIA TensorRT 运行单目度量深度推理,将得到的 cv::Mat 转换回 ROS 图像,并将其作为浮点深度图像发布。

代码本身很直接,但由 CPU 支撑的 ROS 边界包围着一个 GPU 原生算法。对于 CPU 生产者或消费者而言,这个 CPU 边界是合适的,但当两侧的节点都已经能够生产和消费 CUDA 内存时,它就没有必要了。在这种情况下,两次负载大小的主机传输、主机内存分配以及序列化工作,就成为了接口处的一项优化机会。

因此,目标并不是重新设计模型或替换其标准消息;相反,目标是在保留现有 ROS 契约的同时,允许输出的 Image.data 字段承载来自合适后端的存储。

AI 编码智能体非常适合开展这类调查工作:追踪负载在回调和辅助库中的流转、找出主机与设备之间的边界、保持节点契约不变,并协调源码、依赖、启动和测试方面的改动。

migrate-node-to-rosidl-buffer 技能将这一分析转化为可重复的工作流。它不会用模板替换节点,也不会自动重写代码,而是引导智能体执行以下步骤:

借助 rosidl::Buffer 迁移技能,智能体更新节点的依赖和接口,以采用 CUDA buffer 后端。大部分改动是调整 TensorRT 封装,使其能够接受用于输入和输出数据的 CUDA buffer 句柄,同时保留其现有 API。ROS 传输层的改动仍然很小:一个订阅选项、一次 CUDA 分配、两次流感知的句柄提取,以及一次发布。无需自定义消息、重复的 CUDA 话题或 CPU/CUDA 发布者分支。

以下各节将说明该技能在节点迁移中会带来的关键改动。

首先,该技能帮助将 CUDA buffer 后端包(cuda_buffer 和 cuda_buffer_backend)添加为额外依赖。消息定义不会改变——节点继续使用 sensor_msgs/msg/Image。

rclcpp::SubscriptionOptions options; options.acceptable_buffer_backends = "cuda";

现有的 image_transport 和 message_filters 拓扑保持不变。订阅选项只是通过它进行转发。

以下摘录包含利用 CUDA buffer API 的关键改动:

auto depth_msg = std::make_unique (); depth_msg->header = bgr_image_msg->header; depth_msg->height = bgr_image_msg->height; depth_msg->width = bgr_image_msg->width; depth_msg->encoding = sensor_msgs::image_encodings::TYPE_32FC1; depth_msg->is_bigendian = false; depth_msg->step = depth_msg->width * sizeof(float);

depth_msg->data = cuda_buffer_backend::allocate_buffer( static_cast (depth_msg->step) * depth_msg->height);

const cudaStream_t stream = tensorrt_depth_anything_->getCudaStream(); { auto input = cuda_buffer_backend::from_input_buffer( bgr_image_msg->data, stream); auto output = cuda_buffer_backend::from_output_buffer( depth_msg->data, stream);

tensorrt_depth_anything_->doInferenceCuda( input.get_ptr(), bgr_image_msg->width, bgr_image_msg->height, bgr_image_msg->step, *camera_info_msg, reinterpret_cast (output.get_ptr()), node_param_.point_cloud_downsample_factor, node_param_.colorize_point_cloud, node_param_.publish_point_cloud, node_param_.enable_debug); } // 在发布前释放由 CUDA 事件跟踪的句柄。

pub_depth_image_->publish(std::move(depth_msg));

每一行都有明确而具体的目的:

该技能保持非 CUDA 路径不变。点云构建和调试可视化在原始节点中是本地 CPU 消费者。启用时,它们可能仍需要一次设备到主机的拷贝和同步。它们并不决定深度话题上交付的表示形式,因此迁移将它们保留为显式的可选边界,而不是使优化后的发布路径变得复杂。

rosidl::Buffer 特性是在 ROS 2 Lyrical 中引入的,因此迁移后的节点预计可在 Lyrical 及更高版本上运行,并需使用受支持的 RMW 实现(rmw_fastrtps_cpp 和 rmw_zenoh_cpp)。

在迁移过程中,核心功能和边界消息类型保持不变,并为该包添加 cuda_buffer 和 cuda_buffer_backend 作为额外依赖,以启用 CUDA buffer 后端。因此,整体构建过程和设置与原始节点保持相似。

要启用 CUDA buffer 后端,请从源码构建这些包。首先从 rosidl_buffer_backends 仓库克隆源码,该仓库托管了当前所有受支持的后端及配套包:

请注意,rosidl::Buffer 的核心功能已在 ROS 2 Lyrical 中构建完成,因此无需重新构建 ROS 2 核心包。

rosidl::Buffer 后端被设计为 ROS 2 插件。在同一工作空间中构建并 source CUDA buffer 后端包,就足以让该后端在运行时对节点可用。

colcon build --symlink-install --packages-up-to cuda_buffer_backend source install/setup.bash

colcon build --symlink-install --packages-up-to depth_anything_v3 source install/setup.bash export RMW_IMPLEMENTATION=rmw_fastrtps_cpp

然后,您可以按照原始仓库中的说明,执行相同的模型准备流程,并使用更新后的 TensorRT 节点运行相同的启动文件。

此次迁移不改变 TensorRT 计算,而是针对其周边的传输环节。要检查 GPU 活动和内存传输,请使用 NVIDIA Nsight Systems。在符合条件的 CUDA 路径上,迁移后的节点不应在其 ROS 边界处出现负载大小的主机到设备或设备到主机传输。请记录变更前后的可比延迟测量结果。

图 3. 迁移后的 DA3 节点在使用 CUDA 支持的 ROS 2 消息存储的同时,保留了 RGB 到深度的结果

rclcpp::SubscriptionOptions options; options.acceptable_buffer_backends = "cuda";

subscription_ = create_subscription ( "/depth_anything_v3/output/depth_image", rclcpp::QoS(1), [this](sensor_msgs::msg::Image::ConstSharedPtr msg) { const std::string backend = msg->data.get_backend_type(); RCLCPP_INFO(get_logger(), "received backend=%s", backend.c_str());

if (backend != "cuda") { throw std::runtime_error("CUDA transport was not negotiated"); } auto input = cuda_buffer_backend::from_input_buffer(msg->data, stream_); consume_on_cuda(input.get_ptr(), stream_); }, options);

请注意,生产代码通常会尝试接受 CPU 回退,而不会抛出错误。

借助所提供的 CUDA buffer API,from_input_buffer() 会在内部自动处理 CPU 回退。用户无需在回调中区分传入消息的 CPU 路径和 GPU 路径。所有 CUDA 内存共享以及必要时的 CPU 到 GPU 转换,均由 CUDA buffer 后端负责处理。

该技能还包含一个验证步骤,可帮助生成用于测试和验证的自定义源节点和汇节点。具体做法是基于生成的源节点和汇节点创建两条流水线,以测试同一个迁移后的节点在无需更改代码的情况下,在 CPU 和 GPU 两种设置下均能正常工作。

相同的工作流可应用于其他具有可变长度原始消息字段的 CUDA 加速 ROS 2 节点。关键在于将优化视为一项端到端的系统任务。AI 智能体会追踪数据移动,识别哪些字段适合使用 GPU 支持的存储,保留标准 ROS 2 接口,并验证优化路径和 CPU 回退路径。这使得迁移可重复进行,而不是一次性的重构。

NVIDIA Isaac ROS 5.0 将此工作流引入加速机器人软件栈,而 NVIDIA Jetson AGX Thor 则提供边缘计算平台,用于在机器人上运行要求严苛的 ROS 2 感知、推理和自主工作负载。

加速 ROS 2 节点既需要优化 GPU 计算,也需要优化数据移动。借助 rosidl::Buffer、NVIDIA CUDA buffer 后端以及 Isaac ROS 5.0 AI 引导的迁移技能,现有的支持 CUDA 的节点只需极少的代码更改即可交换 GPU 常驻数据。这避免了不必要的序列化和 CPU 拷贝,同时保留了标准 ROS 2 消息接口。

来源

NVIDIA Developer · Generative AI