使用 ROS 和 NVIDIA Isaac SDK 建構機器人應用程式

作者 NVIDIA Developer

機器人作業系統(Robot Operating System,ROS)提供了許多軟體函式庫和工具,協助建構機器人應用,包括框架、演算法、感測器和機器人平台。其廣受世界各地的機器人專家和研究人員採用。生態系統的套件和函式庫持續湧入,使機器人專案的入門變得更容易。

圖 1:使用 ROS 橋接器連接 Isaac 與 ROS 軟體堆疊。

NVIDIA Isaac SDK 是可以加速開發與部署 AI 機器人的開放式機器人平台。Isaac SDK 帶來一個可以在 NVIDIA Jetson 平台上,以及在 GPU 上高效率處理的軟體框架 Isaac Engine。其同時包含 AI 和 GPU 加速演算法 Isaac GEM,並與 Isaac Sim 整合,以利用 NVIDIA RTX 進行真實感模擬。使用 Isaac SDK ROS 橋接器,即可在以 ROS 為基礎的應用程式堆疊中使用這些功能(圖 1)。讓開發人員和研究人員可以利用這兩個平台建構機器人應用。

本文示範如何使用 ROS 橋接器,從 ROS 格式的攝影機拍攝影像,並將其與 Isaac GEM(Superpixel)搭配使用。透過範例,我們也可以瞭解如何使用 Isaac ROS 橋接器,將 Isaac GEM 和 Isaac Sim 與 ROS 應用程式堆疊及模組進行連接。最後將說明如何為 ROS 轉 Isaac 或 Isaac 轉 ROS 情境編寫訊息轉換器(ROS 橋接器)。

開始著手

首先,在電腦上安裝 ROSIsaac SDK。您可以使用 ROS 橋接器進行以下操作:

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

或者,您可以下載及儲存 ROS bag

roslaunch realsense2_camera rs_from_file.launch
rosbag_filename:="PathToRosBag"

圖 2 所示為 ROS 橋接器的實際畫面。ROS 攝影機影像(或在 ROS rviz 中視覺化的 ROS bag)是饋送至稱為 Superpixel 的 Isaac SDK GEM(在 Isaac Sight 中視覺化)。下一節將介紹如何進行。

圖 2:使用 ROS 橋接器連接至 Isaac GEM。

ROS 影像上的 Isaac Superpixel GEM

在 Isaac SDK 中有許多經過 GPU 加速的電腦視覺演算法,Superpixel(超像素)為其中之一。超像素是外觀相似的相連像素群組。超像素分割可將影像分成為數百個非重疊的超像素,而不是數千或數百萬個個別像素。利用超像素,可以在更具有意義的區域上運算特徵,以及減少使用演算法的輸入實體數量。有許多複雜性和效能各異之不同的超像素演算法。Isaac SDK 具有使用於 RGB-D 影像的 GPU 加速超像素建置

在此範例中,是從 ROS 產生 RGB-D 輸入感測器訊息。之後,Isaac Superpixels GEM 會使用此 ROS 影像產生超像素分割。

首先,在 NVIDIA Jetson 裝置上安裝 ROS。欲深入瞭解與 Isaac SDK 搭配使用的 ROS 安裝需求,請參閱 Install ROS。您可以在偏好的任何 Jetson 裝置上完成此操作。

接著將 RGB-D 攝影機(例如 Realsense 435d)連接至 Jetson 開發人員套件。您也可以使用 ROS Realsense rosbag,例如 structured.bag。若想要啟動 ROS Realsense 攝影機驅動程式,以及開始產生色彩和深度 sensor_msg 類型,請遵循說明

您需要 ROS 橋接器轉換器,將 ROS 訊息轉換成 Isaac 影像深度 proto 訊息(如先前的範例所示),以供 Isaac Superpixels GEM 使用。修改現有的 RosToImage 轉換器,將 ROS 深度訊息納入現有的色彩影像訊息中。請在已下載 Isaac SDK 的開發工作站上執行此操作(圖 3)。

bool RosToImage::rosToProto(const sensor_msgs::Image::ConstPtr& ros_message,
                            std::optional& ros_time,
                            alice::ProtoTx& tx_proto) {
  ros_time = ros_message->header.stamp;
  auto builder = tx_proto.initProto();
  std::vector& 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(&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(&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 的流程。

圖 3:ROS 訊息轉 Isaac proto 轉換器:ROS 主題
  • ROS 轉換器分別使用 RosToImageRosToCameraIntrinsics,將 ROS depth/ColorCamerainfo 主題轉換成 Isaac proto。
  • SuperPixel 短程式碼使用 ROS 攝影機驅動程式影像產生超像素分割。

以下程式碼範例是說明 Isaac app.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_superpixels-pkg -d 
jetpack43 -h <robot_ip> 

在 Jetson 裝置上,使用自訂的應用程式名稱執行應用程式:

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

最後,使用 Isaac Sight 檢查 Superpixels GEM 的輸出。

影片 1:ROS 橋接器,ROS 影像轉 Isaac proto。

針對 ROS 導航堆疊使用 Isaac Global Localization GEM

ROS 導航堆疊可因為使用 Isaac SDK GPU 加速 Global Localization GEM 解決機器人綁架問題而受益。

Isaac SDK 2020.1 版本提供在使用 Global Localization GEM 的 Isaac Sim Unity3D中,引導 ROS TurtleBot 3 Waffle Pi範例。以下範例為包含 Isaac Sim 等內容的完整應用程式,但是 ROS 使用者可以僅使用 Global Localization GEM。

從本文章之脈絡,回顧 Isaac 版本文件中的範例應用程式。首先,請瞭解 ROS 主題使用之不同的 Isaac ROS 橋接器轉換器。圖 4 所示為具有 Isaac Global Localization GEM 之 ROS TurtleBot3 應用程式,使用的各種 Isaac ROS 橋接器轉換器。Isaac Global Localization 使用的 ROS 橋接器為 PoseMessageToRos,將輸出 /initialpose 發布至 ROS TurtleBot3 應用程式。

圖 4:在 Isaac SDK 的 ROS Turtlebot3 參考應用程式中,是使用 Isaac ROS 橋接器。

Isaac PoseMessageToRos 轉換器的作用如下:從 Isaac 中,將 Global Localization 演算法的輸出接收為 PoseTreeEdgeProto::Reader,並將 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 Sim Unity3D 和 ROS 通訊的 Isaac SDK 應用程式:

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 導航前往目標,而 ROS 導航也是使用 Isaac Global Localization GEM。您可以從 Isaac 端,在 Isaac Sight 中監視機器人,或從 ROS 端,在 rviz 中監視。請在 Sight 中拖曳地圖視窗的 pose_as_goal 標記,以變更導航目標。

影片 2:使用 Isaac SDK GEM 的 ROS TurtleBot 3 應用程式。

開發自訂 ROS 橋接器轉換器

在圖 3 和圖 4 中,標準 ROS 成像主題已轉換成 Isaac proto,以在其上執行 Perception GEM。Isaac SDK 具有可以在 ROS 訊息與 Isaac 訊息之間轉換的 ROS 橋接器轉換器。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,  
      alice::ProtoTx& tx_proto) override;
}; 

Proto2 類型從 Isaac 轉換成 ROS custom_msgs::Custom2 類型的轉換器,如下所示。

class Proto2ToRos : public ProtoToRosConverter<Proto2, custom_msgs::Custom2> {
 public:
  bool protoToRos(const alice::ProtoRx& 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 短程式碼在 Isaac 應用程式中接收 ImageProto 資料,並將其發布至 ROS。換言之,它將資料從 ImageProto 轉換成 sensor_msgs::Image

結論

本文章是示範 ROS 開發人員如何使用 NVIDIA Isaac SDK 進行協作。您已經學會如何在現有的 ROS 應用程式中,選擇性使用 Isaac GEM,例如全域局部化、低延遲、高保真感知演算法,而您經常使用的解決方案仍在 ROS 中。您同時學會了如何自訂新的 ROS-Isaac 橋接器轉換器。

我們希望能聽到您使用 Isaac SDK 進行 ROS 協作的經驗。請在 Isaac 論壇上與我們分享您的 ROS 橋接器轉換器和意見。

若需要更多資訊,請參閱以下資源:

專為虛擬協作和即時擬真模擬所打造的開放平台 – NVIDIA Omniverse