---
# System prepended metadata

title: ROS
tags: [嵌入式]

---

# ROS 
#### 組員: A1105129 吳祥毅 M1115114 楊皓翔
#### 指導老師:林宏益
---
### 一、實驗目的 
將軟硬體整合，實現ROS的Topic功能
### 二、實驗原理
利用樹莓派控制L298n用以掌控兩側馬達轉速，並在樹莓派中使用ROS內Topic功能控制車輛
### 三、實驗材料
1. Raspberry Pi 1
2. L298n
3. Dc-Dc converter
4. 小車
### 四、實驗步驟&結果
1. 將車子本體組裝完畢
![S__22781958](https://hackmd.io/_uploads/BkabM9jV6.jpg =70%x)

2. 一側馬達的Vcc&GND，應放置在一起，再放入L298n的Channel
:::info
需先確認馬達轉向相同，才能將一側馬達的線相互接起來
:::
3. 利用`pinout`或說明書查看腳位，將L298n與樹莓派相互連接
:::warning
總共7個腳位，in1,in2,in3,in4,en1,en2,GND
:::
![S__22781957](https://hackmd.io/_uploads/BkTq-coVT.jpg  =70%x)

4. 開始撰寫Topic內的Pub&Sub
:::success
 
> 我是先撰寫好GPIO程式並測試過後，再轉移到robot_sub.py裡面

**robot_pub.py** 

``` pyhton=
#!/usr/bin/python3

import rospy
from std_msgs.msg import String

rospy.init_node('robot_command_publisher')
pub = rospy.Publisher('/robot_control', String, queue_size=10)
rate = rospy.Rate(10)

while not rospy.is_shutdown():
command = input("Enter command (forward/backward/right_turn/left_turn/stop): ")
pub.publish(command)
rate.sleep()

```
**robot_sub.py**
``` pyhton=
#!/usr/bin/python3

import RPi.GPIO as GPIO
import rospy
from time import sleep
from std_msgs.msg import String

in1 = 17
in2 = 18
in3 = 22
in4 = 23
en_left  = 27
en_right = 24

GPIO.setmode(GPIO.BCM)
GPIO.setup(in1, GPIO.OUT)
GPIO.setup(in2, GPIO.OUT)
GPIO.setup(in3, GPIO.OUT)
GPIO.setup(in4, GPIO.OUT)
GPIO.setup(en_left , GPIO.OUT)
GPIO.setup(en_right, GPIO.OUT)

left_pwm  = GPIO.PWM(en_left , 1000)
left_pwm.start(40)
right_pwm = GPIO.PWM(en_right, 1000)
right_pwm.start(40)

def stop():
    GPIO.output(in1, GPIO.LOW)
    GPIO.output(in2, GPIO.LOW)
    GPIO.output(in3, GPIO.LOW)
    GPIO.output(in4, GPIO.LOW)
def left_for():
    GPIO.output(in1, GPIO.LOW)
    GPIO.output(in2, GPIO.HIGH)
def right_for():
    GPIO.output(in3, GPIO.LOW)
    GPIO.output(in4, GPIO.HIGH)
def left_back():
    GPIO.output(in1, GPIO.HIGH)
    GPIO.output(in2, GPIO.LOW)
def right_back():
    GPIO.output(in3, GPIO.HIGH)
    GPIO.output(in4, GPIO.LOW)
    
def control_robot(data):
    command = data.data
    if command == 'stop' or command == 's':
        stop()
    elif command == 'forward' or command == 'f' :
        left_for()
        right_for()
        sleep(2)
    elif command == 'backward' or command == 'b':
        left_back()
        right_back()
        sleep(2)
    elif command == 'right_turn' or command == 'r':
        left_for()
        right_back()
        sleep(2)
    elif command == 'left_turn' or command == 'l':
        left_back()
        right_for()
        sleep(2)
    stop()
    
rospy.init_node('robot_controller')
rospy.Subscriber('/robot_control', String, control_robot)

try:
    rospy.spin()
except KeyboardInterrupt:
    left_pwm.stop()
    right_pwm.stop()
    GPIO.cleanup()
```
:::

5. 在package內的CMakelists.txt，新增以下指令
:::danger
要放在CMakelists.txt的最後面，因為CMake有優先順序問題
:::
```
catkin_install_python(PROGRAMS 
  scripts/publisher.py
  scripts/subscriber.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
```
6. 回到workspace進行編譯，`catkin_make`，便會開始進行編譯
![image](https://hackmd.io/_uploads/B1_npPoVa.png =70%x)
7. 編譯好後，輸入`roscore &`，使其在背景執行
8. 開啟`tmux`並使用`Crtl+b %`開多個視窗以利操作，接輸入`source devel/setup.bash` ，用以建立環境
9. 分別在兩個視窗打開`rosrun robot_control robot_sub.py`  `rosrun robot_controlrobot_pub.py`，並執行對應指令，便可實現ROS Topic的功能
![image](https://hackmd.io/_uploads/SkjV6KiN6.png =70%x)

11. 皆大歡喜 :+1: 
### 五、實驗討論&心得
雖然一開始拿到散亂的零件，有種無從下手的感覺，但隨著把車體構建出來，並可以實際運作，依然是成就感滿滿。透過自己動手組裝，更了解到線路的走線與零件的擺放都是大學問。一直在(動手做-面臨問題-解決問題)中循環，也學會從挫敗中學習，像是CMakelist的優先順序，或是編譯問題，都是一次次的試錯中學習，面對不足並彌補不足。 :+1:
### 六、參考文獻

:::danger
* 參考文獻 : [助教的HackMD](https://hackmd.io/@neko-yoru/rJrW8nbkp) :100: / [ChatGPT](https://chat.openai.com) :+1: 

:::
:::info
* 編輯人員 ：[name=吳祥毅]
:::