---
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`

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

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

## 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,需要把網路設定,調成```橋接介面卡```,並且實體電腦接到區網

**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)

2.
```
$ rqt_graph
```
[ROS wiki](http://wiki.ros.org/rqt_graph)

3.
```
$ rqt_plot
```
[ROS wiki](http://wiki.ros.org/rqt_plot)

## 建立工作空間
[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())
```