個人認為Topic算是ROS的核心精神之一。在這之前,機器人之間的訊息交換要不就透過Socket,不然就是Memory的操作,實作起來門檻高非常多。而ROS的Topic就是為了解決這個問題而生的,讓機器人之間的訊息交換變得非常簡單。
ROS2
中引入QoS的概念稍微複雜,這裡會盡量簡單的介紹,讓使用者可以快速上手。
Topic的發布和訂閱機制很像Youtube的訂閱+小鈴鐺,只要你訂閱的頻道有新的影片,Youtube就會通知你。ROS的Topic也是如此,只要你(Node)訂閱(Subscribe)的Topic有新發布(Publish)的訊息,ROS就會通知你。
Publisher 和 Subscriber 可以是一對一、一對多、多對一、多對多的關係,同一個Topic可以由多個Publisher發布,也可以由多個Subscriber訂閱。(貴圈真亂
下圖是官方的GIF,可以看到Publisher和Subscriber之間的關係。右側的Node發布訊息到Topic,左側的Node訂閱Topic,當Topic有新的訊息時,左側的Node就會收到。
第二個圖則是展示多個Publisher和Subscriber之間的關係。上方的兩個Publishers皆可以發布訊息至Topic,下方的兩個Subscribers皆可以訂閱Topic,當Topic有新的訊息時,下方的兩個Subscribers就會收到。
ROS2
與ROS
通訊機制上大同小異,但是ROS2
採用Data Distribution Service(DDS)取代原本傳統的TCP/UDP的buffer(queue)機制,在溝通時多了一個Quality of Service
的概念,可以讓使用者針對不同的Topic設定不同的傳輸品質,以確保訊息的可靠性。
QoS Policy底下有八個選項,可以用來設定訊息傳輸的品質和效期:
History
為Keep last
時有效。Liveliness lease duration
。Liveliness lease duration
。上述的無duration的policies,都有一個預設的system default
的選項,會使用middleware預設的值。對於有duration的policies,也都有一個預設的default
的選項,會使用middleware預設的值,其值為infinite
無限長。
ROS
vs. ROS2
功能 | ROS | ROS2 |
---|---|---|
Queue size | queue_size | history & depth policies |
Reliability | roscpp::UDPROS & roscpp::TCPROS | reliability policy |
Durability (一般是給tf publisher) | latching publisher | transient local + depth |
剩下的QoS Policy都是ROS2
獨有的,也就是在ROS
中沒有對應的功能。
ROS2
提供了幾個預設的QoS Profile,可以讓使用者根據情境快速的設定不同的QoS Policy。具體的參數可以參考rclcpp API中以QoS
結尾的class。
Default for Publisher & Subscirber:為了方邊ROS2 Porting,官方預設Publisher和Subscriber的QoS Profile(不在rclcpp API),在不指定的情況下呼叫Publisher和Subscriber的建構子時,會使用這個Profile:
Services:針對Service的QoS Profile,Server和Client。
Sensor Data:隊sensor的資料,我們注重在他的接收即時性,而不是資料的穩定性。也就是說開發者更在意最新的資料,而可以忍受遺失一些資料,所以reliability是best effort,queue size也比較小。
Parameters:Parameter在ROS中是為Service的一種,所以他的QoS Profile類似Service。唯一的不同是depth queue size大很多,這樣parameter client在失去parameter server的情況下依然可以取得參數。
System Default:底層RMW預設的Profile。
以下是ROS2
官方文件中提供的QoS Policy相容性表格,可以讓使用者快速的判斷Publisher和Subscriber之間的相容性。
Compatibility of reliability QoS policies:
Publisher | Subscriber | 相容性 |
---|---|---|
Best Effort | Best Effort | Yes |
Reliable | Best Effort | Yes |
Best Effort | Reliable | No |
Reliable | Reliable | Yes |
Compatibility of durability QoS policies:
Publisher | Subscriber | 相容性 | 訊息結果 |
---|---|---|---|
Volatile | Volatile | Yes | New messages only |
Volatile | Transient Local | No | No communication |
Transient Local | Volatile | Yes | New messages only |
Transient Local | Transient Local | Yes | New and old messages |
這邊先簡單的介紹一下Message,為明天的Topic Publisher和Subscriber做準備。
除了官方有提供個常用的Message(e.g. std_msgs
, sensor_msgs
, geometry_msgs
, nav_msgs
, ...),使用者也可以自行定義Message,只要符合Message格式即可。
自定義的訊息有可以給Topic用的.msg
,也有給Service用的.srv
。具體的使用之後會在另外一篇文章中介紹,這裡僅簡單的介紹一下Message的使用方式。
ROS
比較ROS2
中Message的改動不大,除了多了一層namespace /msg/
,其他的格式都是一樣的。
還有.msg
檔案,ROS
中的Header
在ROS2
中就變成std_msgs/Header
。可以參考ROS
的Image.msg
和ROS2
的Image.msg
。
最主要的差異在header的引入方式,ROS
中是#include <std_msgs/String.h>
,而ROS2
中是#include <std_msgs/msg/string.hpp>
。
ROS Version
#include <std_msgs/String.h>
std_msgs::String msg;
msg.data = "Hello World!";
ROS2 Version
#include <std_msgs/msg/string.hpp>
std_msgs::msg::String msg;
msg.data = "Hello World!";
TODO: Validate the usage of std_msgs::String
in ROS2
.
Python的用法沒有更動
Both ROS & ROS2 Version
from std_msgs.msg import String
msg = String()
msg.data = "Hello World!"