# ASRLab AVL Team Training Note ( ROS Tutorials - Beginner Level )
contributed by < `qwe661234` >
###### tags: `asrlab`
[實作程式碼](https://github.com/qwe661234/ROS_beginner)
## 1. ROS Installation
ubuntu 20.04 要選擇版本 ROS Noetic Ninjemys
`sudo apt install ros-noetic-desktop-full`
## 2. FileSystem
Package: ROS的模組,使用者可以自己定義一個模組,也可以引用別人的模組或是函式庫
Manifsts (package.xml): 定義模組的一個文件,每個模組會有一個這樣的xml文件,用來表示該模組的版本、作者、或是其他相依的模組等等。
### command
* rospack
* rospack find [package_name] : get information about packages
* rospack list : list all package
* roscd <package-or-stack>[/subdir] : change directory
* rosls <package-or-stack>[/subdir] : list files in a package by name
* echo $ROS_PACKAGE_PATH : 可得到 ROS package 存放路徑
## 3. Creating a ROS Package & Building a ROS Package
### Create
* catkin_create_pkg 會建立資料夾名稱為 <package_name> 且在此資料夾中建立四個檔案
1. include/ : 放標頭檔
2. src/ : 放實作檔
3. CMakeLists.txt : 給 cmake 建檔用的
4. package.xml : package 描述檔
### package.xml
* description tag : package description
```xml
<description> XXX package</description>
```
* maintainer tag: maintainer information
```xml
<maintainer email="user@todo.todo">user</maintainer>
```
* license tags: list some license you use
```xml
<license>BSD</license>
```
* dependencies tags: list the packages' and tools' name you depend on
``` xml
<buildtool_depend>tool_name</buildtool_depend>
<build_depend>package_name</build_depend>
```
::: warning
Create 出來的 Packages (such as beginner_tutorials) 要放在 catkin workspace 的 src 資料夾中才能執行 `catkin_make`
[Solution](https://answers.ros.org/question/222344/rospack-error-no-such-package-beginner_tutorials/)
:::
### command
* catkin_create_pkg <package_name> [depend1] [depend2] [depend3] : create your package ( depend1, 2, 3 可以在建立該模組時先預設好其相依的模組 )
* catkin_make 建立兩個新的資料夾
* build : cmake建置專案時需要的
* devel : 本地開發環境的建置
* rospack
* rospack depends1 [package_name] : show direct dependencies
* rospack depends [package_name] : show indirect dependencies
::: warning
使用此 command 須先安裝 python3-rosdep
`sudo apt install python3-rosdep`
:::
## 4. ROS Nodes
Node 是 ROS 系統內的最小單位,位在 Package 底下,表示執行的程式。而一個 Package 可以有很多個 Node,用來執行不同任務。

* Node 的特色:
1. 可以降低程式的複雜度(可以拆分成不同的 Node)
2. reliable (一個 Node crash 不會影響到其他的 Node)
3. Node 名稱不能重複,確保正確的溝通
ng -h
### master node
master 是 ROS 系統中一個特殊的 Node,他是 node 與 node 之間的溝通橋樑,因此在執行 node 之前一定要先用 master 開啟,開啟方法 `roscore`

### command
* rosnode
* rosnode list : 列出執行中的node
* rosnode info [node] : 查看特定node資訊
* rosnode ping : 檢查特定node運行狀況
* rosnode kill : 中止特定node ( kill rosout 會馬上重新執行 roscore )
* rosrun
* rosrun [package] [node_name] : 幫你找出並執行node
* rosrun [package] [node_name] __name:=my_turtle : 更改節點名稱
::: info
在執行 rosnode list 時,會一直出現 rosout 這個 node
rosout 有點像 log,會將錯誤訊息記錄下來,因此他會一直在後台運行,取得其輸出的 log 檔可透過 `roscd log` 到達存放 log 檔的資料夾中
:::
## 5. Topic & Message
### Topic
類似 Message 的標籤,協助 Publisher & Subscriber 之間的溝通,Topic 會檢查 Publisher 發布了新的資訊,並把資訊傳給訂閱這個 Topic 的 Subscriber
* Publisher: 發布關於某個 Topic 的 Message 給 Topic
* Subscriber: 接收由 Topic 傳來的關於某個 Topic 的 Message

Publisher 和 Subscriber 的關係可以是一對一、一對多、多對一和多對多
### Message
Message 即 Topic 的資訊,兩個 Node 在透過 Topic 傳遞資料的時候,必須先講好這個傳遞的格式 (Message type),每個 Topic 都需要先定義好要使用怎樣的 Message Type
### command
* rostopic
* rostopic list : 列出所有目前存在的 Topic
* rostopic info <topic_name> : 顯示關於某個 Topic 的詳細資料 (Type, Publisher, Subscriber 等等)
* rostopic echo /topic_name : 監聽這個 Topic (通常用於開發 Publisher 的 debug)
* rostopic pub <topic-name> <topic-type> [data...] : 充當 publisher 對某個 Topic 發送訊息 (通常用於開發 Subscriber 的 debug)
* rosmsg show [message] : show information of a specific message
* `rosrun rqt_graph rqt_graph` or `rqt_graph` : 產生圖片來視覺化 Publisher & Topic & Subscriber 之間的關聯
///補圖
## 6. Client & Server & Services
1. Client : 發 Request 給 Service 等待接收 Service 回傳的 Response
2. Service: 接收 Client 的 Request 並將 Request 發給 Server, 接著接收由 Server 處理完的 Response 並回傳此 Response 給 Client
3. Server : 接收 Service 傳來的 Request 並將處理後的 Response 發給 Service

### Services & Topic 差異
1. Topic 中,Publisher 和 Subscriber 可以多對多,但是 Service 中,只能一個 Server 對多個 Client,意即只能一對多。
2. Topic 的 Subscriber 是採用持續監聽的方式,不會因為收到一行訊息就中止,而 Service 一次只能接收一條 Request,再回傳一條 Response 回去。
### command
* rosservice
* rosservice list : 列出所有目前存在的 Service
* rosservice info <service_name> : 顯示關於某個 Service 的詳細資料 (Type, Args 等等)
* rosservice call <service_name> [arg1 arg2 ...] : 呼叫特定 Service 並傳入參數
## Action
1. action 的原理跟 service 很像,不過 service 只會送一個request出去然後等待 response 回傳,action 可以在執行該 request 時進行 timeout、callback 等計算,讓action 在執行的過程中可以被中斷或是回傳任務狀態。
2. action 的執行分為 `action server` 和 `action client` ,API 統一包在 ros actionlib 內,如圖:

3. action client 和 action server 串接的方式是透過 ros .action file 定義 action 的protocol,主要分為三個部分: Goal, Feedback 和 Result
* Goal: 執行的目標(指令),以洗碗機為例,就是先定義要使用的洗碗機 id
* Result: 執行的結果,也就是洗完碗了沒
* Feedback: 執行期間的一些反饋值,例如現在洗碗的進度是幾 %
## 7. Msg & Srv file
### .msg file
用來定義 msg 的格式 (message type)
* 建立的 message 檔案都需要放在 /msg 中
:::warning
建立好 msg file 後可能會遇到 **Cannot load message class for .... Are your messages built?**
[Solution](https://answers.ros.org/question/187071/cannot-load-message-class-for-are-your-messages-built/) : 重新執行指令 source devel/setup.bash
:::
### .srv file
用來定義 service 的 request 和 response 的格式
```c
request type
---
response type
```
### command
* rosmsg
* rosmsg list : 顯示目前已定義的 msg
* rosmsg packages : 查看目前已定義的 msg 被放在哪些package底下
* rosmsg package <package_name> : 查看某個特定的 package 底下有哪些 msg
* rosmsg show <package_name>/<msg_name> : 顯示該 msg 的詳細資訊
* rosmsg info <package_name>/<msg_name> : 顯示該 msg 的詳細資訊
* rossrv
* rossrv list : 顯示目前已定義的 srv
* rossrv packages : 查看目前已定義的 srv 被放在哪些package底下
* rossrv package <package_name> : 查看某個特定的 package 底下有哪些 srv
* rossrv show <package_name>/<srv_name> : 顯示該 srv 的詳細資訊
* rossrv info <package_name>/<srv_name> : 顯示該 srv 的詳細資訊
## 8. parameter server & launch file
### parameter server
ros master 底下內建了一個 parameter server,就是用來控管全域變數的,可以透過 rosparam 來設定以及取得全域變數
### command
* rosparam
* rosparam list : 顯示目前已設定的 parameter
* rosparam set <parameter_name> <value> : 設定 parameter
* rosparam get <parameter_name> : 取得 parameter 的值
* rosparam delete <parameter_name> : 刪除 parameter
* rosparam dump [file_name] [namespace] : 產生一份存取目前變數的 yaml 檔
* rosparam load [file_name] [namespace] : 將存取變數得 yaml 檔 load 進來使用
### launch file
launch file 是用來放置一些預設的參數、或是一些需要事先執行的程式,比如設定好的 parameter 會在 masternode 中止後消失,下一次需要的話必須重新設定,而將只要這些變數設置於 lanuch file 中, 執行 launch file 時就會幫你設置這些變數
Example:
```xml
<launch>
<param name="/print_frq" type="double" value="2.0" />
<node name="talker" pkg="beginner_tutorials" type="talker" />
</launch>
```
### command
* roslaunch [package] [filename.launch] : 執行 launch file
## 9. ROS Debug Tool
### rqt_console & rqt_logger_level
用來檢視 node 的 output, 可以選擇看特定類別的 output (DEBUG, WARN, INFO, and ERROR)

### rosbag
rosbag 是一個用來錄製與回放的工具,他可以記錄某個 topic 輸出的訊息,並在之後可以重新執行一遍記錄檔中的訊息
### command
* rosbag
* rosbag record <topic_name> : rosbag 針對特定 topic 接收到的訊息進行紀錄
* rosbag info <bag_name> : 查看紀錄檔的詳細資料
* rosbag play <bag_name> : 執行紀錄檔
Reference:
* [ROS自學筆記 ](https://ithelp.ithome.com.tw/users/20112348/ironman/1965)
* [ROS Tutorials](http://wiki.ros.org/ROS/Tutorials)
* [A excellent Chinese article of the tutorial (1) ](https://makerpro.cc/2019/01/ros1-0-message-system-part1/#comment-18042)
## spin vs spinOnce
* 如果你在 call spin or spinOnce 前有做其他 funciton A, B, C
使用 spin 的呼叫順序
```c=
A();
B(); //假設在執行其他行程式碼的時候收到/topic送來的message
C();
ros::spin(); //在呼叫這行的時候才會執行上面已經定義的callback function
```
```c=
A
B
C
callback function
callback function
callback function
```
使用 spinOnce 的呼叫順序
```c=
// spinOnce 通常搭配 while
while(ros::ok()){
A();
B();
C();
ros::spinOnce();
}
```
```c=
A
B
C
callback function
A
B
C
callback function
```