2019年7月1日 星期一

ROS 2 communication with DDS part 2

ROS 2 ardent

以下會介紹ROS 2 用來查詢node , topic 及service 的指令是如何用DDS 實作的
目的是,我們可以直接用DDS 實作,但是ROS 2 也可以看得懂內容
因為探索方式,是靠嘗試、爬github 及一些網路文章,所以不會太深入ROS 2 的設計細節

注意ROS 2 的專有名詞
重點
想要Node 被看到,participant 的UserData QoS 設值為"name=hello;"
想要Topic 被看到,partition 設為rt
想要Topic 被ROS 2操作,IDL 須符合ROS 2 規範
想要Service 被看到,須同時建立Request 及Reply 兩個Topic,並設partition 分別為rq 及rr
想要Service 被操作,IDL 須符合ROS 2 規範

Node

何謂node?

一個node 並非一台電腦(或是平台),而是一個可以被ROS 2 看得懂的process 
所以一台電腦內,可以有很多個node

查詢node

ROS 2 的用戶會用指令查詢有哪些node 存在
目前功能極為簡陋,僅能顯示node 名稱,而且名稱可以重複
karlkwchen@karlkwchen-VirtualBox:~$ ros2 node -h
usage: ros2 node [-h]
                 Call `ros2 node <command> -h` for more detailed usage. ...
 
Various node related sub-commands
 
optional arguments:
  -h, --help            show this help message and exit
 
Commands:
  list  Output a list of available nodes
 
  Call `ros2 node <command> -h` for more detailed usage.
 
 
karlkwchen@karlkwchen-VirtualBox:~$ ros2 node list -h
usage: ros2 node list [-h] [--spin-time SPIN_TIME] [-a] [-c]
 
Output a list of available nodes
 
optional arguments:
  -h, --help            show this help message and exit
  --spin-time SPIN_TIME
                        Spin time to wait for discovery (in seconds)
  -a, --all             Display all nodes even hidden ones
  -c, --count-nodes     Only display the number of nodes discovered

至於node name 是如何查詢的呢? 根據我爬ROS 2 Github repo 找到create node 的source code,內有一段程式碼及註解是關於create node 時,node name 如何被處理的部分 
DDS 的participant 有一個UserData QoS,可以用來攜帶關於participant 的資訊
因為一隻DDS 程式只能建立一次participant ,與ROS node name 行為相似,所以目前是將node name 放入這個QoS 內
例如:node name 為hello,則儲存為name=hello;
這個QoS 在DDS 底層會被轉為built-in topic (DDS 內部用的topic ),只要去subscribe 這個built-in topic 就能得到node name
同理,想要讓用DDS 開發的任何程式被ros2 node 指令看到,就是使用這個UserData QoS
// Communicate the ROS Node name as DDS Builtin Participant Topic userData
 
  //   For extensibility and backwards compatibility a format is applied that must be understood.
 
  //   The format specifies a list of name-value pairs,
 
  //   Format (byte ascii string) syntax : { <name> '=' <value> ';' }*
 
  //   A <name> is a string and a <value> is a sequence of octets.
 
  //   The '=' and ';' characters are reserved delimiters.
 
  //   For <name> only alphanumeric character are allowed.
 
  //   For <value> there is no limitation, ';' can be used as part of the <value> when escaped by
 
  //   a second ';'.
 
  //   Implemented policy value: "name=<node-name>;"
 
  //   userData not following this policy will be ignored completely.
 
 
 
 
  DDS::DomainParticipantQos dpqos;
 
  size_t length = strlen(name) + strlen("name=;") + 1;
 
  dp_factory->get_default_participant_qos(dpqos);
 
  dpqos.user_data.value.length(static_cast<DDS::ULong>(length));
 
  snprintf(reinterpret_cast<char *>(dpqos.user_data.value.get_buffer(false)), length, "name=%s;",
 
    name);
 
 
 
 
  participant = dp_factory->create_participant(
 
    domain, dpqos, NULL, DDS::STATUS_MASK_NONE);
 
  if (!participant) {
 
    RMW_SET_ERROR_MSG("failed to create domain participant");
 
    return NULL;
 
  }


Topic

何謂Topic ?

在ROS ,Topic 指pub /sub 模型,其傳輸的message 為msg,於ROS 2 剛好完全貼合DDS 的topic 設計
ROS 2 用戶會用以下指令與topic 互動
可以查topic name / topic type ,也可以直接用指令收送該topic
karlkwchen@karlkwchen-VirtualBox:~$ ros2 topic -h
usage: ros2 topic [-h] [--include-hidden-topics]
                  Call `ros2 topic <command> -h` for more detailed usage. ...
 
Various topic related sub-commands
 
optional arguments:
  -h, --help            show this help message and exit
  --include-hidden-topics
                        Consider hidden topics as well
 
Commands:
  echo  Output messages from a topic
  list  Output a list of available topics
  pub   Publish a message to a topic
 
  Call `ros2 topic <command> -h` for more detailed usage.
 
 
karlkwchen@karlkwchen-VirtualBox:~$ ros2 topic list -h
usage: ros2 topic list [-h] [--spin-time SPIN_TIME] [-t] [-c]
 
Output a list of available topics
 
optional arguments:
  -h, --help            show this help message and exit
  --spin-time SPIN_TIME
                        Spin time to wait for discovery (in seconds)
  -t, --show-types      Additionally show the topic type
  -c, --count-topics    Only display the number of topics discovered

查詢Topic

只要DDS 程式的partition 設為rt 就可以被看到,所以最簡單的與ROS 2 隔離就是用partition 區分
至於ROS 2底層是接收所有在rt partiton 內的topic 的方法同樣為使用DDS 的built-in Topic

操作Topic

雖然任何topic 只要partition 在rt 就會被查詢到,但要能夠使用echo / pub 去收送該topic,必須topic type 符合ROS 2 的規範才行
不過如果要支援ROS 2,會先從ROS 2 建立msg 再轉成idl 給DDS 開發使用,我想這部分問題不大
因為msg 及idl 最終都要給ROS 2 用戶

Service

何謂Service ?

service 在ROS 是指request & reply 模型,其底層是由reqeust topic 及reply topic 組成,但ROS 2 的service API 在呼叫request 時,會強制等reply 
service 傳輸的message 叫做srv,srv 會被轉成msg 再轉成idl 
request topic 會被分到rq 的partiton 內,reply topic 則在rr 的partition 內
karlkwchen@karlkwchen-VirtualBox:~$ ros2 service -h
usage: ros2 service [-h] [--include-hidden-services]
                    Call `ros2 service <command> -h` for more detailed usage.
                    ...
 
Various service related sub-commands
 
optional arguments:
  -h, --help            show this help message and exit
  --include-hidden-services
                        Consider hidden services as well
 
Commands:
  call  Call a service
  list  Output a list of available services
 
  Call `ros2 service <command> -h` for more detailed usage.
 
karlkwchen@karlkwchen-VirtualBox:~$ ros2 service list -h
usage: ros2 service list [-h] [--spin-time SPIN_TIME] [-t] [-c]
 
Output a list of available services
 
optional arguments:
  -h, --help            show this help message and exit
  --spin-time SPIN_TIME
                        Spin time to wait for discovery (in seconds)
  -t, --show-types      Additionally show the service type
  -c, --count-services  Only display the number of services discovered

查詢Service

目前查詢功能,只能看到name , type 及計數
跟查詢Topic 原理類似,想要讓DDS 寫的request topic 及reply topic 被ROS 2 操作,必須partiton 分別為rq 及rr
除此之外,這兩個topic name 是有規範的
假設我想模擬提供一個ROS 2 Service 叫做hello,那在DDS 須建立helloRequest 及helloReply 兩個topic,成雙成對才會被指令查詢到
type 則與Topic 稍微有不同,ROS 2 會在原本的idl 外面再包一層idl 描述
具體用途應該是判斷Request Topic 從誰發出的,因為Reply 只會回給發出Request 的對象

操作Service

因為Service 為request 及reply 的模型,不會有人只接收reply
所以指令只有call service 
跟操作Topic 類似的規範,Request Topic 及Reply Topic 的type 必須跟ROS 2 的規則一樣
同樣如果是從建立ROS 2 的srv 轉出的兩份idl 拿去實作,就不會有問題
我們自己開發的DDS 程式不一定要同一支程式內收Request 及發Reply ,只要確保有任何DDS 程式會發送Reply Topic 就好了
要注意QoS 要為Reliable

沒有留言:

張貼留言

NoSQL Redis intro

Redis是一個使用ANSI C編寫的開源、支援網路、基於記憶體、可選永續性的鍵值對儲存資料庫。 支援rdb 及aof 兩種儲存方式 From  https://zh.wikipedia.org/wiki/Redis Redis 目前擁有兩種資料...