ros多機通信完整試坑教程
前言:
- 老規矩,先講講爲啥要做這個項目。因爲機器人上的工控機沒有辦法加顯卡,所以無法跑TensorFlow-GPU,如果用CPU的話,一個是時間太長,二是消耗資源太多。
所以必須得將圖像處理模塊,放到筆記本上。剛好看到古月居大佬的書《ros機器人開發實踐》中,介紹瞭如何設置。emmm,下面會介紹書上的一些bug。。。。 - 感覺現在的時間越來越不夠用了,連寫博客的時間都不想花了。今天抽一個小時簡單記錄一下吧,希望我走過的坑,能夠給大家節約一些時間。
- 遇到的坑有:
1 . 根據古月大佬書上的教程,只能實現從機的訂閱,從機並不能發佈topic到主機(host)上
2 . 我用的是路由器無線通信,通信速度有問題,訂閱的話題是Kinect V2相機的數據,數據量大,頻率高,通過這種通信方式,經常會丟包
3 . 訂閱壓縮話題:/kinect2/hd/image_color_rect/compressed
系統介紹:
- 主機:移動機器人,控制主機是工控機,CPU是i5 6200U
- 從機:筆記本,CPU是i7 6500 ,GPU GT960M
- 相機:Kinect V2,連接在工控機上。
- 軟件包:基本的Kinect V2的庫函數,具體安裝,可以參考這個教程:ubuntu16.04+ros kinetic+kinect2.0錯誤解決方案+小技巧
- 工控機連的是一個無線路由,然後讓筆記本也連上,使二者處於同一個局域網
- 都需要安裝openssh,這個直接 sudo apt-get install openssh 就好了
- 在筆記本上遠程操作工控機(主機),需要這樣:
ssh [email protected]
- 上面的iim是你被遠程操作的工控機的用戶名,換成你自己的就好了,後面的IP是工控機在局域網中的IP
- 登錄後,就可以操作launch 相機了——
roslaunch kinect2_bridge kinect2_bridge.launch
- 就可以拿到話題了。接下來就可以想辦法做你需要做的事兒了
1、設置IP和~/.bashrc文件:
- 先找兩臺機子的IP地址:
ifconfig
根據這篇教程的介紹,可以知道這些東西的含義:
-
如果電腦連接的時有線網,則顯示結果中,etho 部分的 inet addr 後面就是該電腦的 IP 地址;
-
如果電腦連接的是無線,則 wlan0 部分的 inet addr 後就是 IP 地址。
- 分別瞭解了之後,需要在兩臺機子上的/etc/hosts文件加入對方的IP地址和對應的計算機名字
舉例如下:
在工控機上終端操作,或者遠程操工控機(計算機名爲iim):
sudo vim /etc/hosts
這裏的筆記本(計算機名爲 lyl )的IP地址是192.168.199.124,其實連到局域網的時候不是這個,因爲編輯博客,所以連的是外網。假設就是上面的那個。
然後加上這段:
192.168.199.124 lyl
前面的IP,後面的是名字,儘量對齊
之後的筆記本端的文件整體如下:
127.0.0.1 localhost
127.0.1.1 lyl
192.168.31.124 lyl
192.168.31.182 iim
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
工控機的就不放了,差不多。
古月大佬說,最好ping一下,看看通信是否正常:
在筆記本上
ping iim
正常就好了
- 設置ROS_MASTER_URI,這裏的就比較複雜。
我剛開始按照古月的教程,首先文件就寫錯了一個:bashrc 寫成了 bzshrc
更重要的是,他只是在從機,也就是我這裏的筆記本上設置了這個參數,這樣的話,只能保證筆記本可以訂閱主機(工控機)的話題,但是無法發佈話題出去!
具體的表現,可以用這個顯示:
rostopic echo /yourtopic_name
可以發現,咦,一個東西都打印不出來!
遇到這個問題,我搜了很多教程,我剛開始都以爲ros不支持從機發布話題,後來直接看了官方教程,提到了雙方都得設置ROS_MASTER_URI,我才知道被坑了。
列一波搜到的有用的教程:
- 在多臺機器上運行ROS
- ROS網絡設置
- -這倆都是wiki上的教程
- 多臺機器之間的通信問題
- 這沒啥用
- 網絡上的ROS很慢
- 這個是一樣遇到話題傳遞速度過慢的問題,貼過來,是幫助大家自己搜索類似的關鍵詞。
- Kinect訂閱點雲代碼(point)
- 這大概是我這幾天所做的工作的筆記了,對以後有用的都貼上來了
- 在ros中python訂閱壓縮圖片話題的教程
- 不完全適合Kinect V2的包,我後來發現,完全可以用更簡潔的。這裏得注意OpenCV2和OpenCV3是不一樣的
- rospy訂閱壓縮圖片採用CvBridge().compressed_imgmsg_to_cv2(ros_img)
- 第45個案例,用於深度圖的解壓縮還是比較合適的,底下我還是會將我自己是成功的貼出來。
接着上面的來
- 從機-筆記本上需要設置的內容,可以看看:
把這段加到筆記本中的 ~/.bashrc 文件中
export ROS_HOSTNAME=lyl
export ROS_MASTER_URI=http://iim:11311
同理在主機-工控機上這個文件中加上這段:
export ROS_HOSTNAME=iim
export ROS_MASTER_URI=http://iim:11311
設置好IP後,最好 source ~/.bashrc 刷新一下,就可以通信了。
第二個bug——圖像話題會丟包、延遲等問題
主要原因,可能是因爲用的是WiFi無線網絡,帶寬有限,視頻流數據龐大,所以經常會丟包。獲取不到話題。
所以沒辦法,我只能訂閱壓縮過的話題——
/kinect2/hd/image_depth_rect/compressed
整體思路大致如下,分析直接看註釋吧,要吃飯了,我不想繼續寫了
#導入消息類型,壓縮的和未壓縮的
from sensor_msgs.msg import CompressedImage
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image
import rospy
import numpy as np
import cv2
class Detect(object):
def __init__(self):
self.start_time = time.time()
#訂閱網絡壓縮話題,並且,消息類型換成壓縮的
self.image_sub = rospy.Subscriber("/kinect2/hd/image_color_rect/compressed",CompressedImage, self.rgb_callback,queue_size=1)
self.depth_sub = rospy.Subscriber("/kinect2/hd/image_depth_rect/compressed",CompressedImage, self.depth_callback,queue_size=1)
self.bridge = CvBridge()
def rgb_callback(self,image):
try:
#嘗試轉換壓縮圖片信息到CV2可以直接用的格式。後面加不加bgr8好像都行。
self.rgb_image = self.bridge.compressed_imgmsg_to_cv2(image, "bgr8")
#用上面的和下面的都行,都是會轉成rgb的圖,但是對於第二個深度圖就不合適了,只能用上面的
# np_arr = np.fromstring(image.data,np.uint8)
# opencv3 is this ,and opencv2 is cv2.CV_LOAD_IMAGE_COLOR
# self.rgb_image = cv2.imdecode(np_arr,cv2.IMREAD_COLOR)
except CvBridgeError as e:
print(e)
rospy.loginfo('convert rgb image error')
def depth_callback(self,depth):
try:
print("depth_start:")
self.depth_image = self.bridge.compressed_imgmsg_to_cv2(depth)
print(self.depth_image.shape)
except CvBridgeError as e:
print(e)
rospy.loginfo('convert depth image image error')
這裏的代碼,只提供參考,應該是很難直接運行的,具體直接運行的代碼有機會再貼出來吧。
反正通過這樣,基本上可以實現少丟包,低延遲的效果。
具體的數字,可以看看:
- 在工控機本地,rostopic hz /kinect2/hd/image_color_rect/compressed
- 大概是30Hz
- 在筆記本上我訂閱的頻率大概是14Hz,然後訂閱兩個的話,應該會降低一些。
- 而我的識別模塊,大概是3Hz的頻率,所以完全可以等得起這個。