室外低速自動導航車的設計(5)——ROS MAP轉換爲JPEG並在APP上進行顯示

    第4節我們說到ROS與APP之間的地圖交互與座標系變換,今天我們來實現一個與ROS地圖對接的APP,實現以下功能:

    1)機器人的ROS地圖能夠通過網絡方式傳輸到APP上,同時APP上能顯示機器人位置

    2)使用者繪製APP中地圖上的某個區域,這個點能在ROS中以PoseArray的形式發佈出來。

    我們首先來使用Python完成一個APP的設計:

1. APP向機器人請求二維地圖,並獲取地圖的原點位置

1.1 ROS地圖轉化爲JPEG壓縮序列(機器人端)

    首先,機器人的ROS系統中,二維地圖是以nav_msgs/OccupancyGrid這個消息格式存儲於內存中的,我們要通過程序,將這個地圖讀取出來,讀取出來以後轉換爲一個OpenCV的Mat矩陣,然後使用OpenCV的函數將矩陣變爲序列,當APP請求機器人地圖時,以壓縮JPEG的形式發送給APP。

    其中由ROS地圖向JPEG序列轉碼的代碼區段如下(Python):    

def Call4JPEGMAP(self):
        H=self.ros_Map.info.height
        W=self.ros_Map.info.width
        #首先構造一個H行W列的矩陣
        buffer=np.zeros((H,W),dtype=np.uint8)

        #ROS中的地圖是串行數據,要將數據傳輸到Mat矩陣中
        for y in range(H):
            for x in range(W):
                if self.ros_Map.data[y*W+x]==-1: buffer[y][x]=10
                elif self.ros_Map.data[y*W+x]==0: buffer[y][x]=255
                else: buffer[y][x]=0
        if len(buffer)==0: return 'MAP INVALID'     #如果沒有收到地圖,就返回字符串(或者一個預製的地圖)
        img_encode = cv2.imencode('.jpg',buffer)[1]      #編碼爲JPEG序列
        data = np.array(img_encode)  #轉化爲numpy的array
        stringData = bytearray(data)   #轉化爲bytearray
        return stringData

    當外部設備通過請求機器人ROS地圖時,機器人向設備反饋編碼後的地圖。有關http的相關內容可以聯繫我,在這裏,我們假設http服務器已經搭建完成。http搭建完成後,我們用一個瀏覽器就能得到機器人編碼的地圖,如下圖,左邊是ROS地圖,右邊是瀏覽器中呈現的地圖:

    可以看到,由於圖片編碼是從左上角開始,而ROS地圖是從右上角開始,所以這兩幅地圖的上下是翻轉的。

1.2 機器人向外部設備發送一幅地圖的全部信息(包含座標系與地圖文件)

    座標系信息包含兩個部分:1)地圖原點座標系   2)機器人實際位置相對於地圖原點的實際座標。

    地圖原點座標在上一節討論過,就是地圖中的一個配置文件。當APP請求地圖的圖片後,APP緊接着要請求地圖的相關配置文件,包括地圖的原點,地圖的各個障礙信息,分區信息以及障礙信息。各個信息都是以JSON格式進行返回的。

    在這裏,我們用一幅圖表示APP與機器人之間的通訊關係:

    

    當APP獲得了地圖以後,就可以對地圖進行加載,顯示了。

2. 外部設備獲取並加載機器人的實時位置

      外部設備可以採用http定時請求的方式獲得機器人的實時位置,這在上一節也講到了。但是我們需要的是,根據機器人地圖的配置文件,對機器人的顯示座標進行合理的變換,讓機器人在地圖上進行顯示。在這裏便涉及到了:1)機器人位置實時更新  2)機器人與地圖之間的座標變換。

2.1  客戶端與ROS地圖之間的座標變換

     首先,爲了保證不同APP之間的一致性,機器人向APP傳輸的數據只能是環境實際數據。同時,在機器人ROS的地圖配置文件中,機器人是以地圖圖片的左下角位置座標來標定原點的。這個也就意味着,客戶端(APP)層面要對地圖進行比例,位置等變換。所以我們現在需要三個基本函數支持:

    1)做出實際座標與位圖座標的比例變換函數:

def Env2Pix(x,y,ratio=0.05):
    return int(x/ratio),int(y/ratio)

def Pix2Env(x:int,y:int,ratio=0.05):
    return x * ratio, y * ratio
    

    2)根據原點與一個點相對於原點的座標,計算它相對於圖片左下角的座標(用於顯示機器人):

    3)根據原點與一個點相對於左下角的座標,計算它相對於原點的座標(用於確定使用者點擊的實際位置):

    這三個基本函數完成後,我們就可以完成整個機器人顯示,和用戶在地圖上點的選取。

2.2 機器人在地圖上位置的正確顯示

     (先吃飯,明天再寫)

 

     歡迎大家關注,你的關注就是雨哥更新的動力~!

     另外,本博客是雨哥在做項目過程中總結提煉的非涉密技術類文檔,歡迎大家轉發,轉載請註明出處,同時不得用於商業用途!

      

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章