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