AMR ROS2光達搬運機器人- AI物體距離偵測-使用NVIDIA Orin Nano

前言

接續先前的 ROS 系列文章,本篇文章將會分享AMR ROS2光達搬運機器人在AI上的延伸應用,文章內容共有兩段:

第一段是了解如何應用獲得的深度影像,使用StereoLabs ZED 2i深度影像攝影機,從深度影像中取得畫面中心與相機的實際距離

第二段則是將深度影像的應用與AI影像辨識融合,結合上一篇中Jetson Inference ROS2套件detectnet的物件偵測功能,測量偵測到的物件與相機之間的距離

如果還沒有閱讀過前兩篇關於AI影像應用的文章,可以先往回閱讀之前的文章,會更容易了解這次所分享的內容:

AMR ROS2光達搬運機器人-分段路徑規劃與即時影像串流-使用NVIDIA Orin Nano

AMR ROS2光達搬運機器人-AI即時影像推論Jetson Inference-使用NVIDIA Orin Nano

攝影/撰寫 楊子賢 材料表

 

時間 3小時
難度 3(滿分5)

本文

軟硬體背景

  • NVIDIA Jetson Orin Nano
  • StereoLabs ZED 2i
  • Jetpack 5.1.1
  • L4T 35.3.1
  • Ubuntu 20.04 LTS

利用ZED深度影像攝影機取得畫面中心的距離

作為深度影像攝影機,StereoLabs ZED 2i理所當然的可以取得影像的深度,官方也有準備了範例,可以取得影像中心與攝影機的實際距離。在Orin Nano上使用ZED 2i攝影機的方法可以參考之前的文章,內容有提到如何建立並執行ZED攝影機的Docker容器:

首先要建立一個ZED攝影機的Docker容器

[pastacode lang=”bash” manual=”docker%20run%20–runtime%20nvidia%20-it%20–rm%20–privileged%20–network%3Dhost%20%5C%0A%0A%C2%A0%C2%A0–ipc%3Dhost%20–pid%3Dhost%20%5C%0A%0A%C2%A0%C2%A0-e%20NVIDIA_DRIVER_CAPABILITIES%3Dall%20%5C%0A%0A%C2%A0%C2%A0-e%20DISPLAY%20%5C%0A%0A%C2%A0%C2%A0-v%20%2Fdev%3A%2Fdev%20%5C%0A%0A%C2%A0%C2%A0-v%20%2Ftmp%2F.X11-unix%2F%3A%2Ftmp%2F.X11-unix%20%5C%0A%0A%C2%A0%C2%A0-v%20%24HOME%2F.Xauthority%3A%2Froot%2F.Xauthority%20%5C%0A%0A%C2%A0%C2%A0-v%20%24%7BHOME%7D%2Fzed_docker_ai%2F%3A%2Fusr%2Flocal%2Fzed%2Fresources%2F%20%5C%0A%0A%C2%A0%C2%A0–name%20zed_container%20%5C%0A%0A%C2%A0%C2%A0zed_ros2_l4t_image%3Alatest” message=”” highlight=”” provider=”manual”/]

在Docker容器中,開啟ZED攝影機ROS2套件與Rviz

[pastacode lang=”bash” manual=”ros2%20launch%20zed_display_rviz2%20display_zed_cam.launch.py%20camera_model%3A%3Dzed2i” message=”” highlight=”” provider=”manual”/]

接著開啟另外一個終端機,連接到剛才的ZED攝影機Docker容器,並載入ROS2設定檔,才能夠執行下方的範例程式

[pastacode lang=”bash” manual=”docker%20exec%20-it%20zed_container%20bash%0A%0Asource%20%2Fros_entrypoint.sh%0A%0Asource%20install%2Fsetup.bash” message=”” highlight=”” provider=”manual”/]

執行深度距離範例,接著在終端機中就會輸出現在畫面中央與攝影機的距離

[pastacode lang=”bash” manual=”ros2%20run%20zed_tutorial_depth%20zed_tutorial_depth%20–ros-args%20-r%20depth%3A%3D%2Fzed%2Fzed_node%2Fdepth%2Fdepth_registered” message=”” highlight=”” provider=”manual”/]

 

下方是範例中使用的程式碼,這邊有特別註記需要使用正確的服務品質設定(QoS, Quality of Service)才能接收到從ZED套件傳過來的訊息,這邊建立了一個名為depth_qos的服務品質設定,它會盡可能地取得攝影機發布的訊息,並且只會接收新取得的資料。

利用準備好的設定建立一個訂閱者,訂閱來自ZED ROS2套件,名為depth的深度影像訊息,這樣就完成範例程式中關於訂閱的初始設定

關於服務品質的設定與相容性請參考ROS2官方文件

接著要設定訂閱的回呼函式,每當收到訊息後,系統就會呼叫一次這個函式,處理接收到的訊息。為了讀取深度影像的內容,首先要將接收到的影像訊息內容轉為指標(Pointer),這樣就能用影像上的位置,推斷需要的數值在記憶體的所在位置。接著再使用訊息中影像的長寬,找出影像的中心位置,取出記憶體中對應位置的數值,就得到畫面中央與攝影機的距離。

結合影像辨識與深度影像取得物體的距離

有了從深度影像取得距離的方法後,就可以搭配上一篇文章中使用到的Jetson Inference ROS2影像辨識套件,先使用物件偵測來取得物體的位置後,再透過深度影像取得物體與攝影機的距離\

在終端機中開啟ZED深度攝影機的容器,並執行ZED ROS2套件

[pastacode lang=”bash” manual=”docker%20run%20–runtime%20nvidia%20-it%20–rm%20–privileged%20–network%3Dhost%20%5C%0A%0A%C2%A0%C2%A0–ipc%3Dhost%20–pid%3Dhost%20%5C%0A%0A%C2%A0%C2%A0-e%20NVIDIA_DRIVER_CAPABILITIES%3Dall%20%5C%0A%0A%C2%A0%C2%A0-e%20DISPLAY%20%5C%0A%0A%C2%A0%C2%A0-v%20%2Fdev%3A%2Fdev%20%5C%0A%0A%C2%A0%C2%A0-v%20%2Ftmp%2F.X11-unix%2F%3A%2Ftmp%2F.X11-unix%20%5C%0A%0A%C2%A0%C2%A0-v%20%24HOME%2F.Xauthority%3A%2Froot%2F.Xauthority%20%5C%0A%0A%C2%A0%C2%A0-v%20%24%7BHOME%7D%2Fzed_docker_ai%2F%3A%2Fusr%2Flocal%2Fzed%2Fresources%2F%20%5C%0A%0A%C2%A0%C2%A0-name%20zed_container%20%5C%0A%0A%C2%A0%C2%A0zed_ros2_l4t_image%3Alatest%0A%0Aros2%20launch%20zed_wrapper%20zed_camera.launch.py%20camera_model%3A%3Dzed2i” message=”” highlight=”” provider=”manual”/]

在另外一個終端機開啟Jetson Inference的容器,並執行Jetson Inference ROS2套件

[pastacode lang=”bash” manual=”cd%20~%2Fjetson-inference%0A%0Adocker%2Frun.sh%20–container%20dustynv%2Fros%3Ahumble-pytorch-l4t-r35.3.1%0A%0Aros2%20run%20ros_deep_learning%20detectnet%20–ros-args%20-r%20%2Fdetectnet%2Fimage_in%3A%3D%2Fzed%2Fzed_node%2Frgb%2Fimage_rect_color” message=”” highlight=”” provider=”manual”/]

再使用一個終端機開啟AMR Docker容器,執行detect_depth套件與RQT,等待程式啟動完成,在RQT的ImageView畫面中選擇 “/detectnet/person_depth”,就可以看到偵測到的物體距離

[pastacode lang=”bash” manual=”.%2Frun_docker.sh%0A%0Arqt%20-s%20image_view%20%26%20ros2%20run%20detect_depth%20detect_depth” message=”” highlight=”” provider=”manual”/]

STEP1:初始設定

執行後程式所做的第一步是進行初始設定,總共會訂閱三個主題訊息,分別是來自ZED攝影機ROS2套件的深度影像depth_registered、來自Jetson Inference ROS2套件物件偵測程式detectnet的物件資訊detections,以及偵測結果的影像overlay,並發布一個包含物體距離的影像:名為person_depth的影像訊息

這邊使用了message_filter套件當中的訊息同步Approximate Synchronizer,只要設定好訂閱者與接收的時間範圍,它可以把時間相近的訊息整合在一個回呼函式中,以便處理來自不同訊息中的資料

STEP2:轉換影像訊息內容

第二步是在接收到訊息後呼叫的回呼函式當中,跟前面的範例程式相同,將接收到的深度影像訊息內容轉為指標,並保存影像的寬度,後續計算物體在影像上的位置時會使用到。還有使用cv_bridge套件將偵測結果影像訊息轉為容易修改的OpenCV格式,方便之後加上計算出來的距離數值

STEP3:計算物體位置

第三步一樣是在回呼函式當中,從物件偵測訊息中取出物體在影像上的中心座標,利用前面保存的畫面寬度,計算物體在畫面裡的位置,取出記憶體中對應的深度數值。為了避免同時有多個物體時,畫面會被大量的數字覆蓋,這邊把深度數值的精度調整到小數點後兩位,利用OpenCV繪製在偵測結果影像上。如果有不只一個物體被偵測到,就重複執行這一步,直到所有物體都處理完成,最後再用cv_bridge套件把OpenCV格式的結果影像轉換成ROS2影像訊息並發布

使用Rviz或是RQT訂閱上面發送的person_depth影像訊息就可以看到帶有距離數值的結果影像,圖中數字單位為公尺。

以上是ROS2搬運機器人結合專業景深攝影機的深度影像應用,後續會繼續分享ROS2上的各種應用,敬請期待喔!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *