1. 程式人生 > >一 ROS基礎教程

一 ROS基礎教程

ROS教程

這是小弟的學習筆記,有錯求請拍,多指教,謝謝

一 ROS基礎知識

ROS檔案系統介紹

1.功能包集stack

ROS軟體包集合,像Navigation Stack,屬於導航軟體包集合,包含了與導航有關的軟體包,例如地圖軟體包,路徑規劃軟體包,TF座標軟體包,move_base移動控制軟體包等,一整個stack下載後可以任意使用其中的軟體包,每個軟體包都實現其中一個或者好幾個小功能,多個軟體包組成集合實現一個完整的大的功能

http://wiki.ros.org/navigation

2.軟體包package

ROS程式的單元,每個軟體包都包含程式庫,可執行檔案,指令碼。圖中列出的learning_joy軟體包,包含編譯配置檔案CMakeLists.txt,include標頭檔案庫,launch啟動指令碼資料夾,package.xml軟體包概況描述檔案,src程式原始碼庫
figure1

軟體包檔案詳解:

1)編譯配置檔案CMakeLists.txt, 使用cmake編譯時要寫的
2)include標頭檔案庫,如果只是使用ROS中附帶有的標頭檔案,include這個資料夾可能會是空的,但是系統會自動建立,當以後需要用到自己的標頭檔案或者新增別人的標頭檔案時,把標頭檔案新增到該資料夾裡便可正確使用
3)launch啟動指令碼資料夾,裡邊包含了字尾名為launch的啟動指令碼,功能是一次性啟動多個節點,至於什麼是節點,以後會詳細講

figure2

4)清單檔案package.xml,包含軟體包的相關資訊的描述,包括版本號,開發者資訊,各軟體包之間的依賴關係
5)src程式原始碼庫,存放編寫的cpp或者python原始碼檔案

ROS基本框架

1.節點node

節點是ROS機器人系統裡任何操作的單元,可以理解為每一個節點可以實現一個小功能,一個機器人工程就是由多個節點組成的,節點與節點之間可以相互通訊,相互協調完成工作,比如人手臂的運動,運動指令從大腦發出,經過肩膀,手肘,手腕,最後再到手指,觸感的資訊則是反過來傳遞,每個關節理解成一個節點,它們之間可能是相互傳遞訊息,也可能是一個傳送訊息,一個接收訊息;通常,我們在程式設計的時候就是編寫一個個節點

2.話題topic

話題是ROS裡的一個通訊方法,topic裡包含了訊息的名稱,型別,內容,節點可以釋出或者訂閱某個或某幾個話題,以此達到傳遞的目的;話題有兩個重要的性質:a.話題的釋出頻率;b.話題的訊息型別

3.釋出者和訂閱者publisher & subscriber

ROS裡的節點node可能是釋出者或者是訂閱者,甚至兩者都兼備,釋出者就是釋出topic的節點,訂閱者就是訂閱topic的節點,釋出者以一定的訊息型別格式在ROS伺服器上釋出訊息,訂閱者則根據話題名稱在伺服器上訂閱訊息,訊息型別在ROSwiki上有詳細定義
http://wiki.ros.org/std_msgs

還有一些常用軟體包內需要的訊息型別,如:

common_msgs 檢視各類訊息型別
geometry_msgs 運動幾何學相關的訊息型別,包括速度,加速度等
sensor_msgs 感測器相關的訊息型別,包括鐳射雷達,點雲,IMU慣性測量單元,JoySticks遙控手柄,影象等

4.理解ROS的通訊流程

  1. master 節點,管理所有的節點,每個節點都需要先向 master 節點註冊, master 節點會讓釋出者和訂閱
    者進行匹配;所以每次啟動ROS時,都需要先開啟master節點
    [email protected]:~$ roscore
  2. 釋出者和訂閱者之間通過話題來通訊時,資訊不通過 master
  3. 釋出者釋出一個話題,訂閱者進行訂閱
  4. 流程:
    1 )訂閱者傳送建立連結請求
    2 )釋出者進行反饋,確認連結
    3 )訂閱者請求 topic 的資料
    4 )釋出者傳送 topic 資料

建立和編譯 ROS 軟體包

1.建立軟體包

1)建立工作空間

在編寫任何ROS程式之前,都應該先建立一個工作空間workspace,因為使用catkin環境,所以一般網上很多教程都會將工作空間命名為catkin_ws,但其實可以任意命名,工作空間就是一個在~/home目錄下的資料夾。工作空間下是存放軟體包的,所以一般而言,工作空間不需要建立太多,除非某個工程特別龐大,才需要為它獨立建立工作空間

建立工作空間目錄:~$ mkdir -p catkin_ws/src

這裡寫圖片描述

檢視資料夾目錄:tree catkin_ws/

編譯軟體包命令:~/catkin_ws$ catkin_make

即使沒有原始碼檔案,工作空間也是可以通過編譯的,編譯命令要在工作空間資料夾目錄下執行,系統會自動生成build資料夾和devel資料夾,devel資料夾內的檔案與引導路徑有關係,沒有source配置正確的環境變數路徑,即使catkin_make編譯通過,ROS也無法正確識別通過編譯的節點

在工作空間目錄下執行source命令:~/catkin_ws$ source devel/setup.bash

但這個命令只能在該終端內source到正確的環境變數,每次新開啟一個終端,仍需要再次配置,可以修改整個環境:
$ gedit ~/.bashrc
把編輯文字拉到最後,新增:
source ~/catkin_ws/devel/setup.bash
就是新增工作空間下的/devel/setup.bash檔案的路徑,讓終端每次開啟時,都會自動執行source命令
配置完成後,按ctrl+alt+T開啟終端,如果配置不正確,終端會提示找不到路徑
這裡寫圖片描述

2)建立軟體包

軟體包一般在工作空間的src資料夾下建立,否在ROS可能無法定位你的軟體包,命名要避免與ROS的操作指令重複,不能以數字或者符號開頭,並且不允許大寫字母
建立軟體包命令:
格式: catkin_create_pkg pkg_name pkg_depends
例子: catkin_create_pkg testing_pkg roscpp rospy std_msgs

  1. pkg_name是對軟體包的命名;
  2. pkg_depends是軟體包的依賴關係,如roscpp,rospy,std_msgs;軟體包的依賴關係類似依賴某個原始碼或者標頭檔案
  3. 依賴關係分為一級依賴和間接依賴,一級依賴是我們在建立軟體包過程中新增的依賴項,間接依賴是各依賴項之間的關係,
    $ rospack depends1 pkg_name 檢視一級依賴關係
    $ rospack depends pkg_name 檢視所有的依賴關係
3)刪除軟體包

軟體包刪除命令:$ rm -rf 資料夾名稱
再重新編譯

2.編寫測試程式碼步驟

1)先進入軟體包目錄下的src資料夾 $ cd catkin_ws/src/testing_pkg/src/
2)開啟編輯器編寫cpp或者python原始碼

$ gedit talker.cpp $ gedit listener.cpp
如果沒有gedit編輯器,系統會提示安裝gedit $ sudo apt-get install gedit

3)修改編譯配置檔案
4)返回工作空間目錄,編譯程式碼 $ catkin_make

3.編寫釋出者程式碼

1)簡單的釋出者程式碼,釋出者程式碼基本都是這個框架
#include "ros/ros.h"//ROS程式必備的標頭檔案
#include "std_msgs/String.h"//傳遞的訊息型別
#include "sstream"

int main(int argc, char **argv)//寫ROS程式需要加argc,argv,因為init需要傳這兩個引數
{
  ros::init(argc, argv, "talker");//初始化ros,向master註冊一個叫“talker”的節點

  ros::NodeHandle n;//初始化一個控制代碼,就是將ROS例項化

  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
  //釋出者註冊一個叫“chatter”的話題,<訊息型別>,1000是訊息佇列大小
  //訊息佇列相當於快取訊息,如果處理速度不夠快的話訊息會被儲存在佇列中

  ros::Rate loop_rate(10);//執行迴圈的速率,可以理解為釋出訊息的頻率,單位是Hz

  int count = 0;
  while (ros::ok())//ros::ok()函式用來判斷master節點是否正常
  {
    std_msgs::String msg;//宣告變數

    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();

    ROS_INFO("%s", msg.data.c_str());//ROS_INFO()可以在終端列印資料

    chatter_pub.publish(msg);//釋出該訊息

    ros::spinOnce();//動作執行一次
    //ros::spin()是迴圈執行,在沒有while的時候使用

    loop_rate.sleep();//相當於delay函式,因為程式可能不需要0.1s,就是10Hz的頻率就可以傳送完成,所以sleep()函式可以讓程式暫停一會,讓訊息的傳送頻率符合10Hz
  }
  return 0;
}

wiki.ros.org/PublisherSubscriber

4.編寫訂閱者程式碼

1)簡單的訂閱者程式碼
#include "ros/ros.h"
#include "std_msgs/String.h"//要和訂閱的訊息型別所匹配

void chatterCallback(const std_msgs::String::ConstPtr& msg)//回撥函式
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");//初始化ros,向master註冊一個叫“listener”的節點

  ros::NodeHandle n;

  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
  //訂閱者向master註冊自己需要訂閱的話題"chatter",訊息佇列大小是1000,chatterCallback是回撥函式
  //回撥函式的意義是,當訂閱者從自己所訂閱的話題上接收到訊息,回撥函式自動執行

  ros::spin();//因為不在while迴圈體中,所以它要不斷執行,而不是用spinOnce(),只執行一次

  return 0;
}

wiki.ros.org/PublisherSubscriber

5.修改CMakeLists.txt檔案

  1. ctrl+F找到關鍵字 ## Declare a C++ executable
  2. 去掉#註釋項add_executable(${PROJECT_NAME}_node src/test_pkg_node.cpp),將test_pkg_node.cpp修改成自己所要編譯的cpp檔案,如果有多個cpp檔案需要編譯(一個軟體包內可能存在多個節點),則多新增add_executable語句
  3. 找到關鍵字target_link_libraries,將註釋去掉,如果有特別需要新增的依賴庫,可以在這裡新增,一般的編譯過程不需要,因為ROS裡已經揉合了很多第三方庫,例如OpenCV
  4. 每一個軟體包都要配置自己的CMakeLists.txt檔案

6.執行節點

1)先執行master節點 $ roscore
2)執行節點

格式:$ rosrun your_pkg_name your_node_name
例子:$ rosrun testing_pkg talker rosrun testing_pkg listener

3)如果不記得節點名或者軟體包名稱,可以按Tab鍵補全,但一定要記得先source正確的環境變數

7.編寫launch檔案(可選)

1)launch檔案是xml格式的指令碼,我們把需要啟動的節點資訊寫進去,launch指令碼會自動幫我們執行需要的節點,而不需要手動逐個開啟
2)launch指令碼開啟節點的順序是不確定的,這也是ROS節點編寫的一個理念,儘可能讓節點之間的耦合性降低,節點儘可能地獨立完成某項工作
3)進入軟體包資料夾目錄 $ cd catkin_ws/src/testing_pkg/
4)建立launch資料夾 $ mkdir -p launch
5)進入launch資料夾 $ cd launch
6)新建launch檔案 $ gedit testing_pkg.launch
7)編寫launch檔案
語法格式
每個 xml 檔案都包含根元素,根元素由 launch 標籤來定義
<launch>// 開始標籤
<node pkg=”package_name” type=”executable_name” name=”node_name” output=“screen”/>
//type填寫的是與CMakeLists.txt中add_executable修改的test_pkg_node.cpp名稱一致
...
</launch>// 結束標籤,結束標籤都多一個 /
簡單的launch檔案
<launch>
<node pkg="testing_pkg" type="talker" name="talker" output="screen"/>
<node pkg="testing_pkg" type="listener" name="listener" output="screen"/>
</launch>
8)注意
  1. launch 檔案中,啟動節點的時候給 node 重新指定了名稱,會覆蓋掉在原始碼檔案中通過 ros::init 賦予節點的名稱,所以在使用launch啟動時要留意被修改的節點名
  2. 如果 output 沒有定義到 screen ,節點的輸出資訊會在 log 日誌檔案下儲存,檢視方式:
    $ ~/.ros/log/run_id/node_name-number-stour.log

拓展:jason來自星星的部落格教程

8.通過launch檔案啟動節點

1)

格式:$ roslaunch pkg_name launch_name
例子:$ roslaunch testing_pkg testing_pkg.launch

ROS基礎工具

1.rqt_graph

1)通過直觀的圖譜來檢視當前正在執行的節點之間的關係
2)$ rosrun rqt_graph rqt_graph

這裡寫圖片描述

3)graph圖譜會列出節點,話題等資訊

2.rqt_robot_steering

1)rqt_robot_steering是與機器人運動控制的密切相關的ROS工具,它相當於一個節點,可以釋出/cmd_vel型別的訊息,/cmd_vel類訊息包括了機器人直線運動和轉向運動的控制指令,通過滑動條可以十分方便地控制機器人運動
2)$ rosrun rqt_robot_steering rqt_robot_steering

這裡寫圖片描述

Twist&/cmd_vel

3.rviz

1)rviz是一款2D&3D的資料視覺化軟體,提供了豐富的ROS介面,可以建立機器人運動模型,鐳射雷達地圖等,並且進行模擬驗證
2)rosrun rviz rviz

4.rqt_logger_level

1)ROS的一個log日誌檢視器,用於檢查每個節點的日誌資訊,比如說什麼時候哪個節點作出了更改,都會記錄在log日誌下
2)$ rosrun rqt_logger_level rqt_logger_level

這裡寫圖片描述

3)log訊息等級劃分,從Debug到Fatal越來越嚴重

5.rqt_console

1)用來檢視節點輸出資訊,因為有很多訊息並未通過ROS_INFO()函式在終端顯示出來,可以通過console檢視是否有正確輸出
2)rosrun rqt_console rqt_console

這裡寫圖片描述

6.ROS檔案系統工具

1)rospack 獲取軟體包相關資訊,類似一個 find 的命令,只需要知道軟體包的名稱即可
  1. rospack help 檢視 rospack 相關功能的命令
  2. rospack list 列出當前系統中安裝了的軟體包名稱和路徑資訊
  3. rospack list-names 只檢視軟體包名稱
  4. rospack list-names | wc -l 統計有多少個軟體包,| 是一個符號,表示上一個命令的結果是下一個命令的輸入
  5. rospack find [package_name] 查詢軟體包的路徑資訊
2)roscd 軟體包名
直接切換工作目錄到某個軟體包中
3)rosls 軟體包名
直接羅列該軟體包的目錄結構
4)rosed 軟體包 可編輯檔名
直接編輯某個軟體包的可編輯檔案
5)roscp 軟體包名 需要複製的檔名
直接把某個軟體包下的檔案複製到當前的命令列目錄下