1. 程式人生 > 其它 >ROS中的機器人通訊

ROS中的機器人通訊

目錄:

ROS通訊

ROS中的多機器人通訊

  1.單個roscore和公共網路

  2.群組/名稱空間的使用

  3.基於群組/名稱空間的多機器人系統構建示例

多master概念簡介

  1.multimaster_fkie功能包簡介

  2.安裝multimaster_fkie功能包

  3.設定multimaster_fkie功能包

多機器人應用示例

ROS通訊

下面介紹ROS中兩個節點如何使用ROS話題相互通訊。

圖1.8展示了節點間通過話題進行通訊的過程。如圖1.8所示,有兩個節點分別名為talker和listener。talker節點將名為Hello World的字串訊息釋出到名為/talker的話題中,而listener節點訂閱此話題。整個過程包含了三個階段,在圖中分別標記為(1)、(2)和(3),讓我們看看每個階段發生了什麼:

(1):在執行ROS中的任何節點之前,我們首先啟動master。啟動後,它將等待其他節點。當talker節點(釋出者)開始執行時,它將連線到master,並與master交換其所要釋出話題的詳細資訊,包括話題名稱、訊息型別和釋出節點URI。master的URI是一個全域性值,所有節點都可以連線到它。master通過列表維護與其連線的釋出者。每當釋出者的詳細資訊發生更改時,列表將自動更新。
(2):當我們啟動listener節點(訂閱者)時,它將連線到master並交換節點的詳細資訊,例如要訂閱的話題、其訊息型別和節點URI。與釋出者類似,master也維護一個訂閱者列表。

(3):每當出現針對同一話題的訂閱者和釋出者時,master將進行訂閱者和釋出者URI的交換,幫助兩個節點建立連線和交換資料。訂閱者和釋出者建立連線後,就不需要master的角色了。資料並不流經master,而是直接在相互連線的節點間交換訊息。

ROS中的多機器人通訊

ROS系統是一個分散式計算環境,它不僅可以在一臺機器上執行多個節點,而且可以在多臺相互通訊的機器上執行,只要這些機器在同一個網路上。這一功能特性在機器人應用中十分有用,因為某些感測器需要複雜的機器進行支撐。

例如,如果我們有一個移動機器人通過其感測器(如超聲波感測器和攝像頭)感知環境,那麼它可能需要一個簡單的處理器,用來與超聲波感測器所連線的微控制器進行序列通訊。但是像攝像頭這樣的感測器可能需要更復雜的處理器來處理其資訊。我們可以利用AWS或Google Cloud等雲服務來處理攝像頭資料,而不是使用高階計算硬體(通常成本高昂,有的體積龐大)。
這個系統所需要的就是一個良好的無線連線。超聲波感測器節點可以在機器人上的簡單計算機中執行,攝像頭影象處理節點可以在高效能的雲上執行,並通過無線通訊與機器人的計算機通訊(需要注意的是,攝像頭節點將位於機器人的簡單計算機上)。下面讓我們學習如何用ROS在多個機器人或機器之間建立通訊。

1.單個roscore和公共網路

在同一網路中建立不同機器之間通訊的最簡單方法是通過網路配置進行通訊建立。讓我們考慮圖6.2所示的示例。

假設這個例子是一個工業4.0用例。機器人有一臺計算機負責其控制和移動操作,機器人與伺服器計算機共享其狀態和執行狀況,伺服器計算機分析機器人的執行狀況,並幫助預測事件或機器人本身可能發生的故障。機器人和伺服器計算機都在同一個網路中。

為了讓ROS理解它們並在它們之間進行通訊,我們假設伺服器計算機是主計算機(即master)。因此,roscore將在伺服器計算機上執行,機器人上的計算機將向這個ROS master提供任何必要的話題資訊。要實現這一點,我們需要為每個計算機分別設定主機名和IP,以幫助區分兩者並幫助它們彼此通訊。假設伺服器計算機的IP為192.168.1.1,機器人上計算機的IP為192.168.1.2,roscore執行在伺服器計算機上,機器人上的計算機連線到伺服器計算機上,在每個計算機系統中設定以下環境變數。

在伺服器計算機上,使用以下命令設定:

$ export ROS_MASTER_URI=http://192.168.1.1:11311
$ export ROS_IP=http://192.168.1.1

在機器人計算機上,使用以下命令設定:

$ export ROS_MASTER_URI=http://192.168.1.1:11311
$ export ROS_IP=http://192.168.1.2

那麼,上述命令的作用是什麼呢?實際上,通過上述命令,我們將ROS_MASTER_URI設定成了伺服器計算機的IP,並且連線網路上的其他計算機(例如我們的機器人計算機),以便它們連線到特定的ROS master上。此外,為了幫助區分不同的計算機,我們通過ROS_IP環境變數為計算機設定顯式名稱。

Tips:也可以使用ROS_HOSTNAME來代替ROS_IP,引數值為在/etc/hosts下定義為條目的機器人名稱。相應的參考示例網址為http://www.faqs.org/docs/securing/chap9sec95.html。可以將前面的環境變數條目直接複製到對應的bash檔案中,以避免每次新開啟一個終端時都需要重新呼叫相應變數值。
有時可能發生時間和話題同步的問題,可能還會看到一個關於未來外推的TF警告。這些通常是計算機系統時間不匹配的結果(即時間不同步)。
可以通過ntpdate工具來進行確認,安裝命令為:

$ sudo apt install ntpdate

執行以下命令來測試其他計算機的時間:

$ ntpdate -q 192.168.1.2

如果存在不匹配的問題,則需要通過以下命令安裝chrony來進行匹配處理:

$ sudo apt install chrony

可以通過編輯機器人計算機上的配置檔案來獲取伺服器計算機上的時間,方法為通過以下命令來修改/etc/chrony/chrony.conf:

$ server 192.168.1.1 minpoll 0 maxpoll 5 maxdelay .05

Tips:可以從https://chrony.tuxfamily.org/manual.html瞭解更多資訊。

公共網路問題

現在,我們知道了如何在同一網路中不同機器上的節點之間進行通訊。但是,如果不同機器上的節點具有相同的話題名稱,那該怎麼辦?考慮圖6.3所示的示例。

對於一個移動機器人而言,move_base節點需要感測器和地圖資訊來通過cmd_vel命令給出軌跡點。如果我們計劃在應用程式中使用另一個移動機器人,則由於兩個機器人位於同一網路中,因此它們之間可能具有相同的通訊話題,而這將導致通訊衝突。兩個機器人可能會嘗試執行相同的命令並執行相同的操作,而不是單獨執行任務。這是使用通用ROS網路的主要問題之一。機器人無法理解哪一個是自己的控制動作,因為它們在網路中具有相同的話題名稱。我們將在下一節中學習如何克服這種情況。

2.群組/名稱空間的使用

如果讀者較為深入地學習過ROS線上教程,就會知道如何解決這個問題。讓我們考慮以turtlesim為例來看待這個問題。使用以下命令啟動turtlesim節點:
開啟一個終端視窗,執行以下命令:

$ initros1
$ roscore

開啟另一個終端視窗,執行以下命令:

$ initros1
$ rosrun turtlesim turtlesim_node

檢查rostopic列表來檢視cmd_vel以及turtle1的位姿資訊。下面來通過以下命令在GUI下建立另一個turtle:

$ rosservice call /spawn 3.0 3.0 0.0 turtle2

執行上述命令將會發生什麼情況呢?我們生成了一個新的turtle,並且具有相同的話題名稱,但是添加了一個字首/turtle2。這在ROS中稱為名稱空間技術,主要用於多機器人場景。現在,我們重新定義了圖6.3中的示例,使其變成了圖6.4所示的樣子。

由圖6.4可見,每個機器人都有自己的話題,分別以機器人名稱作為字首。機器人之間也可能有一些共同的話題,比如/map話題,這是因為兩個機器人都在同一個環境中。在下一節中,我們將學習如何將這個名稱空間技術用於我們在第3章中建立的機器人上。

3.基於群組/名稱空間的多機器人系統構建示例

下面介紹如何以第3章中構建的移動機器人底座為基礎,構建多機器人系統。可以從https://github.com/PacktPublishing/ROS-Robotics-Projects-SecondEdition/tree/master/chapter_3_ws/src/robot_description下載工作空間。將上述檔案下載到一個新的工作空間並編譯。通過以下命令啟動機器人底座:

$ initros1
$ roslaunch robot_description base_gazebo_control.xacro.launch

讀者將會在Gazebo中看到機器人底座模型,如圖6.5所示。

現在,我們的目的是在Gazebo上“繁殖”另一個機器人,因此我們把機器人命名為robot1和robot2。在前面的base_gazebo_control.xacro.launch檔案中,我們將載入了機器人和控制器配置的空Gazebo世界傳送到ROS伺服器並載入控制器節點。這裡我們也需要這麼做,但目標不止一個機器人。為此,我們將在名稱空間群組標籤下啟動機器人。在載入機器人的URDF時,我們需要確保使用tf_prefix引數和<robot_name>字首來區分不同的機器人變換。

最後,我們必須在載入控制器時使用ns引數,並且在啟動控制器節點時使用--namespace引數來區分每個機器人的控制器。這些更改可以應用於robot1,如下所示:

  <group ns="/robot1">
  <param name="tf_prefix" value="robot1" />
   <rosparam file="$(find robot_description) /config/control.yaml"
command="load" ns="/robot1" />
     <param name="/robot1/robot_description" command="$(find xacro)/xacro --
inorder $(find robot_description)/urdf/robot_base.urdf.xacro nsp:=robot1"/> <node name="urdf_spawner_1" pkg="gazebo_ros" type="spawn_model" args="-x -1.0 -y 0.0 -z 1.0 -unpause -urdf -model robot1 -param robot_description " respawn="false" output="screen"> </node> <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher_1"> <param name="publish_frequency" type="double" value="30.0" /> </node> <node name="robot1_controller_spawner" pkg="controller_manager" type="spawner" args="--namespace=/robot1 robot_base_joint_publisher robot_base_velocity_controller --shutdown-timeout 3"> </node> </group>

 如果要啟動兩個機器人,則只需將上述程式碼塊複製並貼上兩次,然後在第二個複製的程式碼塊中將robot1替換為robot2。可以隨心所欲地建立多個塊。為了簡單起見,我們將此程式碼塊移動到另一個名為multiple_robot_base.launch的啟動檔案中。啟動兩個這樣的機器人的完整程式碼可以在GitHub上找到(網址為https://github.com/PacktPublishing/ROS-Robotics-Projects-SecondEdition/blob/master/chapter_6_ws/src/robot_description/launch/multiple_robot_base.launch)。主啟動檔案位於GitHub上的robotbase_simulation.launch下,該檔案啟動Gazebo空世界和multiple_robot_base啟動檔案。

啟動兩個機器人後,視窗如圖6.6所示。

rostopic列表如圖6.7所示。

Tips:需要說明的是,上述示例僅為群組標籤的簡單應用演示,並且不是群組的唯一表示方法。讀者可以嘗試通過合適的變數和迴圈來建立自己的多機器人系統。
至此,我們使用名稱空間構建了多機器人系統並且啟動了該系統,下面介紹這種方法的侷限性。

使用群組/名稱空間存在的問題

雖然群組/名稱空間的方法確實達到了在同一型別機器人之間通訊的目的,但在使用這項技術時還存在一些侷限性。例如,當我們的機器人載入了一些特性時,對它們進行設定可能會很有挑戰性,因為在這些特性中,我們必須嘗試為機器人附帶的幾乎所有啟動檔案提供名稱空間。這一過程將會耗費大量時間,而且安裝過程會很棘手。如果設定不當,則還可能會導致混亂,因為在出現問題時,系統不會提供任何診斷或異常提示。
假設讀者計劃購買一個機器人底座,如Husky或TurtleBot。要同時使用它們,需要為每個機器人設定封裝檔案(必需的名稱空間啟動檔案)。我們選擇使用某一型號的機器人底座的原因在於它們具備開箱即用的特性,我們希望不需要專門為自己的應用程式進行功能包設定。但是,我們最終需要在可用檔案的基礎上建立其他檔案,這將需要更多的開發時間。此外,通過群組/名稱空間的方法,rostopic列表將載入一個帶有特定機器人名稱字首的複雜話題列表。如果只想控制機器人中選定的話題,並將其顯示給主master,這時該怎麼辦?如果我們還需要知道機器人在網路中的連線狀態,比如哪些處於連線狀態、哪些處於斷開狀態呢?

對於上述問題,我們將在接下來給出解決方案。

多master概念簡介

為了理解多master的概念,讓我們考慮一個工業用例,如圖6.8所示。
假設我們有類似移動機械臂的機器人(如我們在第3章中建立的工業移動機械臂)來裝卸貨物,並且至少有5個這樣的機器人在進行該工作。另外,假設有一些機械臂與機器一起工作,用於操作應用,例如將材料裝載到加工區,然後裝載到傳送帶上,解除安裝產品以進行配送。最後,還有一箇中央系統用於監控所有這些機器人的任務和健康狀況。對於這樣的工業用例,將會有多個本地網路連線到一個公共網路(即中央系統所在的位置)。

ROS中定義了相應的機制來幫助我們實現上述多機器人協作的需求,ROS提供了通用的工具用於在ROS子系統間進行通訊。該工具為名為multimaster_fkie的功能包。

1.multimaster_fkie功能包簡介

multimaster_fkie功能包包括兩個主要的節點:
·master_discovery節點。
·master_sync節點。
master_discovery節點幫助我們檢測網路中的其他ROS master,識別網路中的任何更改,並與其他ROS master共享這些更改。master_sync節點幫助其他ROS master將其話題和服務與本地ROS master同步。multimaster_fkie功能包能夠有效地幫助同一網路中的ROS master只與同一網路共享必要的話題資訊,並將其他豐富的話題資訊儲存在本地網路中。
下面我們將通過一些例子來幫助讀者理解multimaster_fkie功能包的安裝、設定和使用過程。

Tips:可以從http://wiki.ros.org/multimaster_fkie瞭解更多有關multimaster_fkie的資訊。

2.安裝multimaster_fkie功能包

我們通過源的方式安裝multimaster_fkie功能包,步驟如下:
1)在系統中安裝pip工具,命令如下:

$ sudo apt install python-pip

2)安裝pip之後,將多master程式碼倉庫複製到我們的工作空間中,並編譯構建我們的功能包,命令如下:

$ cd chapter_6_ws/src
$ git clone https://github.com/fkie/multimaster_fkie.git
multimaster
$ rosdep update
$ rosdep install -i --as-root pip:false --reinstall --from-paths
multimaster

執行上述命令後,讀者將會遇到並接受幾次依賴項安裝提示,請確保接受了所有的依賴項安裝請求,因為安裝依賴項之後才能編譯構建工作空間。
3)這裡我們使用catkin_make_isolated命令構建工作空間,該命令將分別構建功能包,而不是將其構建為一個功能包,命令如下:

$ cd ..
$ catkin_build_isolated

執行上述步驟後,我們就完成了功能包的安裝,下面讓我們體驗一下該功能包的使用。

3.設定multimaster_fkie功能包

進行multimaster_fkie功能包設定的最佳方法是在兩個系統中分別執行以下示例,主要包含三個步驟:
1)設定主機名和IP地址。
2)檢查並啟用多播功能。
3)設定檢查與測試。
下面詳細介紹每個步驟。

1.設定主機名和IP地址

假設我們有兩個系統,分別命名為pc1和pc2,下面按照以下步驟進行系統設定:
1)在pc1上,進入/etc/hosts檔案並做以下修改:

127.0.0.1 localhost
127.0.0.1 pc1

192.168.43.135 pc1
192.168.43.220 pc2

2)在pc2上,進入/etc/hosts檔案並做以下修改:

127.0.0.1 localhost

    127.0.0.1 pc1

    192.168.43.135 pc1
    192.168.43.220 pc2

由於上述檔案位於系統資料夾下,因此對其修改需要sudo許可權。
3)讀者應當還記得,前面的示例中添加了ROS_MASTER_URI和ROS_IP。讓我們對每臺計算機使用各自的IP和ROS_MASTER_URI在各自的bash指令碼中執行相同的操作,具體參考步驟4。
4)使用命令$sudo gedit~/.bashrc開啟bash指令碼檔案,操作如下:

  • 在pc1的bash指令碼檔案中使用如下程式碼:
export ROS_MASTER_URI=http://192.168.43.135
export ROS_IP=192.168.43.135
  • 在pc2的bash指令碼檔案中使用如下程式碼:
export ROS_MASTER_URI=http://192.168.43.220
export ROS_IP=192.168.43.220

在此基礎上,讓我們檢查並啟用多播功能。

2.檢查並啟用多播功能

要在多個roscore之間進行同步處理,需要檢查每臺計算機上是否啟用了多播功能。該功能在Ubuntu中通常被禁用。要檢查它是否已啟用,需要使用以下命令:

$ cat /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

如果該值為0,則表示啟用了多播功能;如果值為1,則需要使用以下命令將該值重置為0:

$ sudo sh -c "echo 0 >/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts"

啟用後,使用以下命令檢查多播IP地址:

$ netstat -g

標準的IP通常是220.0.0.x,因此在每臺計算機中ping該IP以檢視計算機之間是否正在進行通訊。在本書的例子中,我們的多播IP是220.0.0.251,因此220.0.0.251是兩臺計算機中檢查連線的ping地址:

$ ping 220.0.0.251

下面讓我們對上述設定進行檢查和測試。

3.設定檢查與測試

在每個終端視窗中,分別啟動roscore:

$ initros1
$ roscore

現在,轉到相應的multimaster_fkie功能包資料夾,在每臺計算機上執行以下命令:

$ rosrun fkie_master_discovery master_discovery _mcast_group:=220.0.0.251

在上述命令中,_mcast_group的數值是我們使用netsat命令獲得的多播IP地址。
如果網路設定正確,則應看到master_discovery節點標識了每臺計算機中的roscore,如圖6.9所示。

現在,要在每臺ROS master的話題之間進行同步,需要在每臺計算機中執行master_sync節點。如我們所見,multimaster_fkie功能包已經設定好。讓我們用一個示例來試著更好地理解這一點。

多機器人應用示例


讓我們試著從一臺PC上啟動機器人模擬,並在另一臺PC上用遙控器控制機器人。我們將使用在6.4.3節給出的示例中設定的機器人。假設前面的設定沒有變化,讓我們執行在一臺PC上啟動的多機器人,命令如下:

1)在pc1上,執行以下命令:

$ initros1
$ roslaunch robot_description robotbase_simulation.launch

2)開啟新的終端視窗,啟動master_discovery節點,命令如下:

$ initros1
$ source devel_isolated/setup.bash
$ rosrun fkie_master_discovery master_discovery _mcast_group:=224.0.0.251

3)開啟新的終端視窗,啟動master_sync節點,命令如下:

$ initros1
$ source devel_isolated/setup.bash
$ rosrun fkie_master_sync master_sync

現在,在pc2上執行必要的命令。我們假設已經在pc2的終端視窗中啟動了roscore,下一步是在新的終端視窗中分別啟動master_discovery節點和master_sync節點,具體命令見步驟4、5。
4)開啟新的終端視窗,執行以下命令:

$ initros1
$ rosrun fkie_master_discovery master_discovery _mcast_group:=224.0.0.251

5)再次開啟新的終端視窗,執行以下命令:

$ initros1
$ rosrun fkie_master_sync master_sync

進行了話題同步後,我們將會看到一個視窗,如圖6.10所示。
6)執行$rostopic list命令,可以看到/robot1和/robot2的話題同步了。嘗試使用以下帶有適當話題名稱的命令移動機器人。我們應該看到機器人在移動。

$ rosrun rqt_robot_steering rqt_robot_steering

模擬視窗中機器人運動的簡單表示如圖6.11所示。
如果需要選擇特定話題進行同步,請檢視master_sync.launch檔案以獲取必要的引數列表。可以通過使用ROS引數(rosparam)sync_topics指定所需的話題來完成此操作。