---
# System prepended metadata

title: ROS
tags: [' 教學3', 教學, ' python', ' AUV']

---

---
tags: 教學, 教學3, AUV, python
---
:::info
https://hackmd.io/@NCTU-auv/Ska3nlA2L
:::
[TOC]

# ROS

## Installation

[官網安裝說明](http://wiki.ros.org/melodic/Installation/Ubuntu)
Ver: ros-melodic-desktop-full

```bash=
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
sudo apt update
sudo apt install ros-melodic-desktop-full
apt search ros-melodic
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
source ~/.bashrc
sudo apt install python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential
sudo apt install python-rosdep
sudo rosdep init
rosdep update
```

- 安裝成功與否測試
```bash==
roscore
```
最後按`Ctrl+C`結束`roscore`

![](https://i.imgur.com/xTxRQ5k.png)

## ROS簡介
- ROS 是在 Linux 中的，專門設計來控制機器人與自動化裝置的軟體架構。
- [ROS自學筆記](https://charlyhuangrostutorial.wordpress.com/ros-%E8%87%AA%E5%AD%B8%E7%AD%86%E8%A8%98/)
![](https://i.imgur.com/p5nDCgf.png)

#### 基本結構
##### Workspace工作空間
如果沒有工作空間，那就不能使用 ROS，就假設這是個虛擬平台，連結著所有的節點。
##### Package包裹
包裹中可以存放所需的節點。通常一個包裹代表一個特定的任務，節點則是任務的拆解子任務。
##### Node節點
節點，就是執行檔。通常會包含輸入與輸出資料。編譯完後，就可以直接當一塊積木，鑲嵌在其他積木上。
##### Launch file
ROS 中通常在包裹中都會有一個 Launch 資料夾，裡面存放不同的 launch 文件，只要執行一個 launch 文件，便會一次啟動所有需要的節點。

## 啟動ROS核心
```
roscore
```
![](https://i.imgur.com/xTxRQ5k.png)

## rostopic指令
[ros wiki說明](http://wiki.ros.org/rostopic)
- ```$ rostopic list```: 列出現在ros上所有的topic
- ```$ rostopic echo <topic-name>``` : 顯示某個topic上的數值
- ```$ rostopic info <topic-name>``` : 顯示某個topic的資訊
- ```$ rostopic pub <topic-name> <topic-type> [data...]``` : 在某個topic上發布資料
- 範例
    - 在其中一個terminal下指令```$ rostopic pub /test std_msgs/String hello```
    - 在另一個terminal下指令```rostopic list```，可以看到多一個topic
    - 在第二個terminal下```rostopic echo /test```，並從新執行第一個terminal的指令，可以看到傳到topic上的data

## ROS 多台電腦連線
這幾台電腦必須在同一個內網下
使用VirtualBox，需要把網路設定，調成```橋接介面卡```，並且實體電腦接到區網
![](https://i.imgur.com/5KUpEIT.png)

**My_ASUS_7661**
**12345678**
**192.168.43.212**

```
$ vim ~/.bashrc
```
在文件中加上
```
export ROS_IP=<自己的IP>
export ROS_MASTER_URI=http://<roscore機器的IP>:11311
```

查看自己IP的方法
```
$ ifconfig
```
若要確認有沒有連上ros，可以下指令```$ rostopic list```，看有沒有回應

## turtle_eric

執行後有五隻烏龜
可以透過```/turtle/<num>/forward``` : 讓他們前後移動。
可以透過```/turtle/<num>/turn``` : 讓他們左右旋轉。
可以透過```/turtle/<num>/position``` : 知道他所在的座標。
可以透過```/turtle/<num>/heading``` : 知道他所面對的方向。
* 烏龜顏色對應


| 編號 | 顏色 |
| ---- | ---- |
| 1    |  藍    |
| 2    |    紅  |
| 3    |    黃  |
| 4    | 綠 |
| 5     |   黑   |

* 移動方法
```
$ rostopic pub /turtle/1/forward std_msgs/Int32 100
$ rostopic pub /turtle/1/turn std_msgs/Int32 100
```
* 監測位置
```
$ rostopic echo /turtle/1/position
$ rostopic echo /turtle/1/heading
```

* 下載方法
```
$ cd ~/catkin_ws/src
$ git clone https://github.com/EricPwg/turtle_eric
$ cd ..
$ catkin_make
```

* 執行方法

終端機1
```
$ roscore
```

終端機2
```
$ rosrun turtle_eric my_turtle.py
```

終端機3
```
$ rosrun turtle_eric turtle_contorl.py
```

## ROS 可視化工具

1. 
```
$ rviz
```
[ROS wiki](http://wiki.ros.org/rviz)
![](https://i.imgur.com/RIhX9kh.png)

2. 
```
$ rqt_graph
```
[ROS wiki](http://wiki.ros.org/rqt_graph)
![](https://i.imgur.com/KWTo8bj.png)

3. 
```
$ rqt_plot
```
[ROS wiki](http://wiki.ros.org/rqt_plot)
![](https://i.imgur.com/ROsJrMI.png)

## 建立工作空間
[ros wiki 說明](http://wiki.ros.org/catkin/Tutorials/create_a_workspace)
- 建立一個工作空間(範例)
```
$ source /opt/ros/melodic/setup.bash
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/
$ catkin_make
```

- 為了讓ros可以認得自己的工作空間，需要source自己工作空間下的```setup.bash```
- 如果上述步驟都照著範例做，可以直接下指令```$ source ~/catkin_ws/devel/setup.bash```或是直接將```source ~/catkin_ws/devel/setup.bash```加在```~/.bashrc```的最後一行，在每次開啟新終端機的時候自動執行。

## ROS Package建立
[ROS wiki](http://wiki.ros.org/ROS/Tutorials/CreatingPackage)

:::info
格式
```
$ catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
```
:::

```
$ cd ~/catkin_ws/src
$ catkin_create_pkg image_test std_msgs rospy sensor_msgs cv_bridge
```

## python code寫法

### import
```python=
#!/usr/bin/env python
# license removed for brevity

import rospy
from std_msgs.msg import Int32
from std_msgs.msg import Float32
#from std_msgs.msg import <data-type>
```

### ros node初始化
```
rospy.init_node(<node-name>, anonymous=True)
```

### Publisher
[ros wiki](http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28python%29)
```
pub1 = rospy.Publisher(<topic-name>, <topic-type>, queue_size = <queue_size>)
```
- queue_size : 最多暫存資料數目

### Subscriber
```
rospy.Subscriber(<topic-name>, <topic-type>, <handle-function>)
```
- handle-function定義
```python=
def <handle-function>(data):
    ...
```


#### 範例程式

```python=
#!/usr/bin/env python
#license removed for brevity

# import rospy基本功能
import rospy
from std_msgs.msg import Int32
from std_msgs.msg import Float32
from std_msgs.msg import Int32MultiArray

import turtle
import time

forward_value = 0
turn_value = 0

#ros node初始化
rospy.init_node('Turtle_view', anonymous=True)

#turtle初始化
tur = turtle.Turtle()
tur.shape("turtle")
tur.color("blue")

# Subscriber handle function 
def forward_hd(data):
    global forward_value
    forward_value = data.data

def turn_hd(data):
    global turn_value
    turn_value = data.data

# publisher定義
pub1 = rospy.Publisher('/turtle/position', Int32MultiArray, queue_size = 10)
pub2 = rospy.Publisher('/turtle/toward', Float32, queue_size = 10)

#Subscriber定義
rospy.Subscriber('/turtle/forward', Int32, forward_hd)
rospy.Subscriber('/turtle/turn', Int32, turn_hd)

#主程式
while not rospy.is_shutdown():
    time.sleep(0.5)
    tur.forward(forward_value)
    forward_value = 0
    tur.right(turn_value)
    turn_value = 0
    pos = tur.position()
    pos = [pos[0], pos[1]]
    pub_data = Int32MultiArray(data = pos)
    pub1.publish(pub_data)
    pub2.publish(tur.heading())

```