图形/仿真

使用 ROS 和 NVIDIA Isaac SDK 构建机器人应用程序

 

Robot 操作系统( ROS )提供了许多软件库和工具来帮助构建机器人应用程序,包括框架、算法、传感器和机器人平台。它在世界各地的机器人专家和研究人员中非常受欢迎。来自生态系统的软件包和库的不断涌入使得机器人项目的启动变得很容易。

图 1 。使用 ROS 桥接器连接 ISAAC 和 ROS 软件堆栈。

NVIDIA ISAAC 软件开发工具包 是一个开放的机器人平台,旨在加速人工智能驱动机器人的开发和部署。 ISAAC SDK 带来了一个软件框架, ISAAC 引擎,用于在 NVIDIA Jetson 平台和 GPUs 上高效处理。它还包括人工智能和 GPU 加速算法, ISAAC GEMS ,以及与 ISAAC Sim 卡的集成,用于 NVIDIA RTX 供电的照片真实模拟。这些功能可以使用 ISAAC SDK ROS 桥在基于 ROS 的应用程序堆栈中使用(图 1 )。这使得开发人员和研究人员可以利用这两个平台来构建机器人应用程序。

在这篇文章中,我们将向您展示如何使用 ROS 桥从 ROS 格式的相机中获取图像,并将其与 ISAAC GEM (超级像素)一起使用。通过示例,我们还研究了将 ISAAC GEMs 和 ISAAC Sim 与 ROS 应用程序堆栈以及使用 ISAAC ROS 桥的模块相连接。最后,我们解释如何为 ROS 到 ISAAC 或 ISAAC 到 ROS 场景编写一个消息转换器( ROS 桥)。

入门

首先,在您的电脑上安装 ROS ISAAC 软件开发工具包 。下面是使用 ROS 网桥的操作:

bazel run packages/ros_bridge/apps/ros_to_superpixels
roslaunch realsense2_camera rs_rgbd.launch

或者,您可以 下载并保存 ROS 包

roslaunch realsense2_camera rs_from_file.launch rosbag_filename:="PathToRosBag"

图 2 显示了 ROS 桥的作用。 ROS 相机图像(或 ROS rviz 中可视化的 ROS 包)被输入名为 Superpixel 的 ISAAC SDK GEM (在 ISAAC 视线中可视化)。下一节将讨论这是如何实现的。

Image shows converting ROS camera image to Isaac proto for Isaac GEM.
图 2 。使用 ROS 桥连接到 ISAAC GEMs。

ISAAC ROS 图像上的超级像素GEMs

ISAAC SDK 中有许多计算机视觉算法是 GPU 加速的。其中之一就是超级像素。超级像素是一组外观相似的连接像素。超像素分割将图像分成数百个不重叠的超级像素(而不是数千或数百万个单独的像素)。通过使用超级像素,您可以计算更有意义的区域上的特征,并减少用于消耗算法的输入实体的数量。有许多不同的超像素算法,其复杂度和性能各不相同。 ISAAC SDK 附带了一个 GPU – 加速超像素 RGB-D 图像的实现

在本例中,您将从 ROS 生成 RGB-D 输入传感器消息。此 ROS 图像随后被 ISAAC 超级像素GEMs消耗,以产生超级像素分割。           

首先,在 NVIDIA Jetson 设备上安装 ROS 。有关使用 ISAAC SDK 的 ROS 安装要求的更多信息,请参阅 安装 ROS 。这可以在任何您喜欢的 Jetson 设备上完成。

接下来,将 RGB-D 摄像头(如 Realsense 435d )连接到 Jetson 开发工具包。您也可以使用 ROS realseness rosbag ,例如 structured.bag 。要启动 ROS Realsense 相机驱动程序并开始生成颜色和深度 sensor_msg 类型,请遵循 instructions

您需要一个 ROS 桥转换器来将 ROS 消息转换成 ISAAC 图像深度 proto 消息(如前面的示例所示),供 ISAAC 超级像素 GEM 使用。修改现有的 RosToImage 转换器,以包括 ROS 深度消息和现有彩色图像消息。在下载了 ISAAC SDK 的开发工作站上执行此操作(图 3 )。

bool RosToImage::rosToProto(const sensor_msgs::Image::ConstPtr& ros_message,
                            std::optional<ros::Time>& ros_time,
                            alice::ProtoTx<ImageProto>& tx_proto) {
  ros_time = ros_message->header.stamp;
  auto builder = tx_proto.initProto();
  std::vector<SharedBuffer>& buffers = tx_proto.buffers();
  // This converter is currently only supporting rgb8 color encoding and 16UC1 depth encoding
  if (ros_message->encoding == "rgb8") {
      ImageConstView3ub rgb_image =
          CreateImageView<uint8_t, 3>(static_cast<const uint8_t*>(&ros_message->data[0]),
                                      ros_message->height, ros_message->width);
      Image3ub color_image(rgb_image.dimensions());
      Copy(rgb_image, color_image);
      show("image", [&](sight::Sop& sop) { sop.add(rgb_image); });

      ToProto(std::move(color_image), builder, buffers);
  } else if (ros_message->encoding == "16UC1") {
      // ROS depth image with 16UC1 encoding is of type uint8_t
      ImageConstView1ui16 image = CreateImageView<uint16_t, 1>(
          reinterpret_cast<const uint16_t*>(&ros_message->data[0]),
          ros_message->height, ros_message->width);
      Image1f depth_image(image.dimensions());
      ConvertUi16ToF32(image, depth_image, 0.001);

      ToProto(std::move(depth_image), builder, buffers);
  } else {
      reportFailure("Unsupported image format: %s", ros_message->encoding.c_str());
      return false;
  }

  builder.setRows(ros_message->height);
  builder.setCols(ros_message->width);
  builder.setDataBufferIndex(0);

  return true;
}

图 3 显示了 ROS 主题到 ISAAC proto 的流程。

ROS messages converted to Isaac proto using a ROS bridge.
图 3 。发送给 ISAAC proto converter 的 ROS 消息: ROS 主题
  • ROS 转换器 分别使用 RosToImageRosToCameraIntrinsics 帮助将 ROS RosToCameraIntrinsicsCamerainfo 主题转换为 ISAAC proto 。
  • 超级像素代码 使用 ROS 相机驱动程序图像来产生超像素分割。

下面的代码示例演示了如何使用 ISAAC 应用程序. json 文件查找 ROS 桥转换器边缘和配置:

{
  "name": "ros_to_superpixels",
  "modules": [
    "sight"
  ],
  "graph": {
    "nodes": [
      {
        "name": "ros_to_perception",
        "subgraph": "packages/ros_bridge/apps/ros_to_perception.subgraph.json"
      },
      {
        "name": "superpixels",
        "subgraph": "packages/superpixels/apps/superpixels.subgraph.json"
      }
    ],
    "edges": [
      {
        "source": "ros_to_perception.subgraph/interface/color",
        "target": "superpixels.subgraph/interface/color"
      },
      {
        "source": "ros_to_perception.subgraph/interface/depth_intrinsics",
        "target": "superpixels.subgraph/interface/depth_intrinsics"
      },
      {
        "source": "ros_to_perception.subgraph/interface/depth",
        "target": "superpixels.subgraph/interface/depth"
      }
    ]
  },
  "config": {
    "ros_to_perception.ros_converters": {
      "RosToDepth": {
        "channel_name": "/camera/depth/image_rect_raw"
      },
      "RosToCameraIntrinsics": {
        "channel_name": "/camera/color/camera_info"
      },
      "RosToImage": {
        "channel_name": "/camera/color/image_raw"
      }
    }
}

现在,从开发工作站将应用程序部署到 Jetson 设备上:

bob@desktop:~/isaac$  ./engine/build/deploy.sh --remote_user <username_on_robot> -p //packages/ros_bridge/apps:ros_to_superpixel-pkg -d jetpack43 -h <robot_ip>

在 Jetson 设备上运行应用程序并使用自己的应用程序名称:

bob@jetson:~/$ cd deploy/<bob>/ros_to_superpixel/
bob@jetson:~/deploy/<bob>/ros_to_superpixel$ packages/ros_bridge/apps/ros_to_superpixel

最后,使用 ISAAC Sight 检查 Superpixels GEM 的输出(图 6 )。

视频一。罗斯桥,罗斯认为它 ISAAC 因此。

对 ROS 导航堆栈使用 ISAAC 全局定位程序

ROS 导航堆栈可以从使用 ISAAC SDK GPU – 加速的全局本地化 GEM 来解决 绑架机器人问题 中获益。

ISAAC sdk2020 . 1 版本有一个 example 来导航 Isaac Sim  Unity 3D 中的 ROS TurtleBot 3 Waffle Pi ,它使用了全局本地化 GEM 。下面的例子是一个带有 ISAAC Sim 等的完整应用程序,但是 ROS 用户只能自由使用 Global Localization GEM 。

在本文的上下文中,从 ISAAC 发布文档 重新访问 示例应用程序 。首先,了解用于 ROS 主题的不同的 ISAAC ROS 桥转换器。图 2 显示了不同的 ISAAC ROS 桥转换器用于 ROS TurtleBot3 应用程序和 ISAAC 全球本地化 GEM 。用于 ISAAC 全局本地化的 ROS 桥转换器是 PoseMessageToRos ,它将输出 /initialpose 发布到 ROS TurtleBot3 应用程序。

图 4 。 ISAAC SDK 中 ROS Turtlebot3 参考应用中使用的 ROS 桥。

ISAAC PoseMessageToRos 转换器的工作如下:从 ISAAC 内部接收全局定位算法的输出,并将 initialpose 主题发布给 ROS 。下面的代码示例显示了这种转换。

bool PoseMessageToRos::protoToRos(PoseTreeEdgeProto::Reader reader, const ros::Time& ros_time

geometry_msgs::PoseWithCovarianceStamped& ros_message) {
  // Read data from Isaac type
  const Pose3d pose = FromProto(reader.getPose());
  const auto& translation = pose.translation;
  const auto& rotation = pose.rotation.quaternion();
  // Populate data for ROS type
  ros_message.header.stamp = ros_time;
  ros_message.header.frame_id = get_frame_id();
  ros_message.pose.pose.position.x = translation.x();
  ros_message.pose.pose.position.y = translation.y();
  ros_message.pose.pose.position.z = translation.z();
  ros_message.pose.pose.orientation.x = rotation.x();
  ros_message.pose.pose.orientation.y = rotation.y();
  ros_message.pose.pose.orientation.z = rotation.z();
  ros_message.pose.pose.orientation.w = rotation.w();
 if (get_report_success()) {
    reportSuccess();
  }
  return true;
}

现在,看看 ROS 桥转换器的工作。通过运行以下命令启动 small-warehouse 场景:

bob@desktop:~isaac_sim_unity3d/builds$ ./sample.x86_64 --scene small_warehouse --scenarioFile ~/isaac/packages/navsim/scenarios/turtlebot3_waffle_pi.json --scenario 0

运行 ISAAC SDK 应用程序,该应用程序与 ISAAC Sim Unity3D 和 ROS 进行通信:

bob@desktop:~/isaac$ bazel run packages/ros_bridge/apps:ros_to_navigation_unity3d -- --more apps/assets/maps/virtual_small_warehouse.json --config ros_navigation:packages/ros_bridge/maps/small_warehouse_map_transformation.config.json,ros_navigation:packages/ros_bridge/apps/ros_to_navigation_turtlebot3_waffle_pi.config.json

在 ROS 中推出 TurtleBot3 :

TURTLEBOT3_MODEL=waffle_pi roslaunch turtlebot3_navigation turtlebot3_navigation.launch map_file:=$(realpath packages/ros_bridge/maps/small_warehouse.yaml)

在输出中, ISAAC Sim 显示了一个基于 ROS 导航的机器人导航到目标,它也使用了 ISAAC 全局定位 GEM 。从 ISAAC 侧,您可以在 ISAAC 视线和 ROS 侧的 rviz 监控机器人。通过拖动 Map 窗口的 pose_as_goal 标记更改导航目标。

视频二。 ROS TurtleBot 3-app 使用 ISAAC SDK GEM 。

定制 ROS 桥变换器的研制

在图 3 和图 4 中 , 中,标准的 ROS 成像主题被转换成 ISAAC proto 来运行 Perception GEM 。 ISAAC SDK 有 ROS 桥转换器,可以在 ROS 消息和 ISAAC 消息之间进行转换。 NVIDIA 还有一个开源转换器库,作为 ISAAC SDK 的一部分。但是,您可能需要创建一个转换器。

下面的代码示例显示如何将 ROS custom_msgs::Custom1 消息类型转换为 ISAAC Proto1 消息类型:

class RosToProto1 : public RosToProtoConverter<Proto1, custom_msgs::Custom1> {
 public:
  bool rosToProto(const custom_msgs::Custom1::ConstPtr& ros_message,
                    std::optional<ros::Time>& ros_time,  
                    alice::ProtoTx<Proto1>& tx_proto) override;
};

这就是将 Proto2 类型从 ISAAC 转换为 ROS custom_msgs::Custom2 类型的转换器的外观。

class Proto2ToRos : public ProtoToRosConverter<Proto2, custom_msgs::Custom2> {
 public:
  bool protoToRos(const alice::ProtoRx<Proto2>& rx_proto, const ros::Time& ros_time,
                  custom_msgs::Custom2& ros_message) override;
}; 

在 ISAAC 应用程序 JSON 配置文件中添加所需的 ROS 主题名为 channel_name ,如下所示:

      "RosToProto1": {
        "channel_name": "/custom_input",
        ...
      },
      "Proto2ToRos": {
        "channel_name": "/result",
        ...
      }

isaac.ros_bridge.ImageToRos codelet 在 ISAAC 应用程序中接收 ImageProto 数据并将其发布到 ROS 。也就是说,它将数据从 ImageProto 转换为 sensor_msgs::Image

结论

这篇文章展示了 ROS 开发人员如何与 NVIDIA ISAAC SDK 协作。您学习了如何有选择地使用 ISAAC GEMs ,例如,在您现有的 ROS 应用程序中使用全局定位、低延迟、高保真的感知算法,而您最喜欢的解决方案仍然在 ROS 中。您还学习了如何创建自己的新 ROS- ISAAC 桥式转换器。

我们很乐意听听您在 ROS 与 ISAAC SDK 合作方面的经验。在 ISAAC 论坛上与我们联系,提供丰富的 ROS 桥式转换器和反馈。

有关更多信息,请参阅以下资源:

 

Tags