PDF下載地址:node
連接:https://pan.baidu.com/s/1l_FAbn_g04q-Z0lKSxx8tw
提取碼:8lbp git
注:英文原文爲《A Gentle Introduction to ROS》 【美】Jason M. O'Kane著shell
1、緒論編程
2、入門概述bash
1. 安裝:參考 http://wiki.ros.org/cn服務器
(1)sudo rosdep init 初始化rosdep,rosdep用於檢查和安裝軟件包的依賴網絡
(2)rosdep update 初始化rosdep,在根目錄下保存一些文件,文件夾名爲.rosapp
(3)source /opt/ros/ros版本/setup.bashless
(3)測試ROS是否正確安裝編程語言
注:三個終端分別執行指令
2. 經常使用術語和命令
(1)ROS功能包/軟件包:一組用於實現特定功能的相關文件的集合,包括可執行文件和其餘支持文件 //任何能找到且包含package.xml文件的目錄
注:使用catkin編譯生成的可執行文件放在外部標準目錄devel中(源碼外編譯)
(2)節點node:ROS程序的運行實例 running instance
(3)rosrun命令:啓動ROS節點 rosrun 功能包名 可執行文件名 //節點名不必定與可執行文件名相同,可使用 __name:=節點名 顯式設置節點名稱
注:節點名稱必須惟一,不可多個節點擁有相同名稱
(4)消息傳遞機制:節點管理器負責確保發佈節點和訂閱節點能找到對方,隨後消息從發佈節點直接傳遞到訂閱節點,不通過節點管理器轉交
注:節點只管發,無論收,有助於減小節點之間的耦合度;話題可共享,話題和消息的通訊機制是多對多的;服務是一對一的通訊機制
(5)rosmsg show 消息類型名 //輸出消息類型的詳細信息
(6)rostopic pub 話題名 消息類型 消息內容 //命令行手動發佈消息
注:消息內容能夠按照rosmsg show命令的顯示結果進行輸入,也能夠以YAML字典的形式輸入(顯式指明結構域中變量名和值的映射關係)
(7)每一個消息類型均屬於一個特定的包,如turtlesim/Color屬於turtlesim包 //消息類型斜槓/前的是包名,斜槓/後是類型名
注:把包名包含在消息類型中的目的:
3、編寫ROS程序
1. catkin編譯系統試圖一次性編譯同一個工做區中的全部功能包
2. 建立功能包:catkin_create_pkg 包名 //包名只容許使用小寫字母、數字和下劃線,且首字符必須爲字母
3. 清單文件package.xml中聲明的依賴庫並不會在編譯過程當中進行檢查,可是會在將包發佈給他人時,他人會由於沒有安裝依賴庫而編譯報錯
4. CMakeLists.txt中的${catkin_LIBRARIES}變量由find_package(catkin REQUIRED COMPONENTS ...)語句定義
5. source devel/setup.bash //專門爲當前的工做區進行環境變量設置
6. 每一個話題都有一個消息類型,而每一個消息類型都有相應的C++頭文件 //包含消息類型頭文件 #include<包名/類型名.h> 如#include<geometry_msgs/Twist.h>
注:頭文件定義了一個與消息類型對應的C++類,且該類定義在以包名命名的域名空間中,如geometry_msgs::Twist類
7. ros::NodeHandle類維護一個引用計數,僅在第一個NodeHandle對象建立時纔會在節點管理器註冊新的節點 //使用標準的roscpp接口,在單個程序中沒法運行多個節點
8. 建立發佈者ros::Publisher屬於耗時操做,應該每一個話題建立一個發佈者,在程序執行過程當中一直使用相應發佈者 //發佈者建立不要放在循環內,避免爲每條消息生成新的發佈者
9. ros::ok()返回false條件:
10. 訂閱者回調函數:void function_name(const package_name::type_name &msg){ ... }
11. 顯式調用 ros::spin()或ros::spinonce()讓ROS執行回調函數
4、日誌消息 //ROS使用log4cxx庫實現日誌功能
1. ROS日誌系統的核心思想:使程序生成一些簡短的文本字符流,即日誌消息
2. 嚴重級別(遞增):DEBUG、INFO、WARN、ERROR、FATAL
3. 產生日誌消息的基本C++宏
注:日誌系統是面向行的,調用任意宏會生成完整的一行日誌消息 //無需使用std::endl
4. 日誌消息的輸出
(1)控制檯
(2)/rosout 話題:消息類型爲rosgraph_msgs/Log
注:rosout即表示話題,也表示節點
(3)日誌文件:做爲/rosout話題回調函數的一部分,由rosout節點生成
檢查日誌文件大小:rosclean check
刪除日誌文件:rosclean purge
5. 設置日誌級別
(1)經過命令行設置:rosservice call /node-name /set_logger_level ros.包名 level // level參數包括DEBUG、INFO、WARN、ERROR、FATAL
注:參數ros.包名指按期望配置的日誌記錄器logger名稱
(2)經過圖形界面設置:rqt_logger_level
(3)經過C++代碼設置:調用ROS實現日誌功能的log4cxx提供的接口 #include<log4cxx/logger.h>
5、計算圖源命名
1. 計算圖源graph resource:節點、話題、服務和參數的統稱,由短字符串表示的計算圖源名稱進行標識
2. 全局名稱:/turtle1/cmd_vel //優勢:任何地方均可以使用;缺點:須要完整列出其所屬的命名空間
3. 相對名稱 //利用ROS提供的默認命名空間
(1)典型特徵:缺乏全局名稱帶有的前斜槓"/"
(2)解析相對名稱:將當前的默認命名空間名稱加在相對名稱以前,生成全局名稱,如 /turtle1 + cmd_vel => /turtle1/cmd_vel
(3)設置默認命名空間:單獨爲每一個節點設置 //不設置,則使用全局命名空間"/"做爲默認命名空間
優勢:避免在移植和整合來自不一樣來源的節點時發生名稱衝突
4. 私有名稱 //用於節點內部僅與本節點有關的資源,如參數
(1)典型特徵:以一個波浪字符(~)開始
(2)與相對名稱一致,不能徹底肯定自身所在命名空間,須要利用ROS客戶端庫進行名稱解析
(3)不使用當前的默認命名空間,而採用節點名稱做爲命名空間,如 /sim1/pubvel + ~max_vel => /sim1/pubvel/max_vel
(4)私有名稱可用於管理節點的服務,話題不能命名爲私有名稱
注:私有名稱的關鍵字"private"僅代表不使用所在的命名空間,其餘節點能夠經過私有名稱解析後的全局名稱進行訪問 //僅在命名空間層面上有意義,注意與其餘編程語言的不一樣
5. 匿名名稱:非用戶指定的無語義信息的名字
(1)通常用於爲節點命名,使節點的命名保存惟一性
(2)調用ros::init方法時請求一個自動分配的惟一名稱
注:ros::init使用處理器時間在節點的基本名稱後追加文本,保證名字的惟一性
6、啓動文件
1. 目的:利用啓動文件一次性配置和運行多個節點
2. 執行啓動文件:roslaunch 包名 啓動文件名 //若是沒有運行roscore,roslaunch會自動啓動roscore
(1)若是啓動文件不屬於任何功能包,則能夠直接以啓動文件路徑啓動 roslaunch + 啓動文件路徑
(2)啓動文件內的節點幾乎是同一時刻啓動,沒法肯定啓動順序,所以節點之間應儘可能保持獨立
(3)添加-v選項能夠輸出詳細信息:roslaunch -v 包名 啓動文件名
(4)查找啓動文件時,roslaunch工具會同時搜索每一個功能包目錄的子目錄
3. 啓動文件基本元素
(1)根元素:<launch> ... </launch>
(2)啓動節點:
<node
pkg=包名
type=可執行文件名
name=節點名
/>
(3)請求復位:respawn="true" //當節點中止時,roslaunch會從新啓動該節點,可用於應對軟件崩潰、硬件故障等引發的節點停止
(4)必要節點:required="true" //當必要節點停止時,roslaunch會終止全部其餘活躍節點,並退出;與respawn做用相互矛盾,不能同時配置
(5)roslaunch全部節點共享一個終端,針對依賴控制檯輸入的節點來講,須要維護獨立的終端:使用啓動前綴屬性 launch-prefix="命令行前綴"
3. 在命名空間內啓動節點 //經過配置節點元素的ns屬性,壓入命名空間
(1)儘管兩個節點相對名稱相同,可是因爲命名空間不一樣,因此兩個節點相互獨立
(2)因爲話題名稱定義時採用的也是相對名稱,因此話題也分別位於獨立的命名空間
4. 名稱重映射remapping names //從更精細的層面控制節點名稱的修改
(1)基於替換的思想:每一個重映射包含一個原始名稱和一個新名稱,每當節點使用原始名稱時,ROS客戶端庫會將它自動替換爲新名稱
(2)建立重映射
注:重映射元素也能夠做爲節點的子元素:<node ...> <remap from="original-name" to "new-name"/> </node> 此時只應用於所在節點
注:
5. 其餘元素
(1)啓動文件的嵌套:include元素
(2)啓動參數argument:便於配置啓動文件,相似可執行程序中的局部變量(僅在聲明的當前啓動文件內有效,不可被包含的啓動文件繼承)
注:在ROS中,parameter和argument是有區別的
(3)建立組group:大型啓動文件內管理節點的快捷方式
注:僅有0和1爲合法取值,且不能使用布爾運算;也能夠不使用組元素,單獨爲每一個節點設置ns、if和unless
7、參數parameter //配置節點信息的集中式方法
1. 主要思想:使用集中的參數服務器維護一個變量集的值(字典),適用於不會隨時間頻繁變動的信息
2. 經過命令行獲取參數
(1)rosparam list //查看參數列表,輸出 /rosdistro 等全局計算圖源的名稱字符串
(2)rosparam get parameter_name //查詢參數,如 rosparam get /rosdistro 獲得ROS版本
(3)rosparam get namespace //檢索給定命名空間每一個參數的值,如 rosparam get / 查詢全局命名空間/
(4)rosparam set parameter_name parameter_value //設置參數,修改已有參數的值或建立新參數
(5)rosparam set namespace values //設置同一命名空間的多個參數,其中值values要以YAML字典的形式給出參數和值的對應關係
(6)建立和加載參數文件(YAML形式) //可用於場景復現
注:命名空間參數可選,默認爲全局命名空間/
注:
3. 使用C++接口獲取參數 //參數名能夠是全局的、相對的或者私有的
void ros::param::set(parameter_name, input_value);
bool ros::param::get(parameter_name, output_value); //讀取成功返回true,不然代表參數還未指定值
注:在命令行中實現私有參數賦值 rosrun agitr pubvel_with_max _max_vel:=1 //參數max_vel前面添加下劃線_前綴 _param-name:=param-value
4. 在啓動文件中設置參數
(1)<param name="param-name" value="param-value"/> //設置參數,參數名是相對名稱
(2)<node ...> <param name="param-name" value="param-value"/> </node> //在節點元素內包含param元素,不管是否以~或/開頭,參數均爲節點私有參數
(3)<rosparam command="load" file="path-to-param-file"/> //一次性從文件中加載多個參數,等價於rosparam load
注:一般採用 file="$(find package-name)/param-file" 指定文件路徑
8、服務service
1. 與話題消息的區別
2. 執行過程:客戶端節點發送請求數據到服務器節點,而且等待迴應;服務器節點收到請求後,執行相應活動,隨後發送響應數據給客戶端節點;
3. 與話題內容由消息數據類型肯定相似,服務的內容也由服務數據類型決定
4. 從命令行查看和調用服務
(1)rosservice list //列出全部服務
(2)服務通常能夠劃分爲兩類:
5. rosnode info node-name //查看某個節點的服務類型
6. rosservice node service-name //查找提供服務的節點(反向查詢)
7. rosservice info service-name //肯定服務的數據類型,一般也是由包名和類型名組成「包名/類型名」,如turtlesim/Spawn
8. rossrv show 服務數據類型名 //獲取服務數據類型的詳細信息(一系列數據域),注意rosservice和rossrv的區別
注:
9. rosservice call service-name request-content //調用服務,提供請求域的全部值,如rosservice call /spawn 3 3 0 Mikey 在位置(3, 3)處建立一個名爲"Mikey"的新海龜,朝向爲0
注:
10. 客戶端程序
(1)聲明請求和響應類型:#include<turtlesim/Spawn.h> //包含頭文件,定義turtlesim::Spawn類(服務數據類型)
(2)建立客戶端對象:ros::ServiceClient client = node_handle.serviceClient<service_type>(service_name) //服務名稱通常應當爲相對名稱,如"spawn"
注:與話題發佈者不一樣,無需緩衝隊列,會阻塞等待直至服務調用完成
(3)建立請求和響應對象 //上述頭文件中定義了請求和響應的類,經過包名和服務類型引用,如turtlesim::Spawn::
注:服務類型的頭文件中還定義了一個單獨類package_name::service_type,同時擁有Request和Response做爲數據成員;能夠定義單獨對象package_name::service_type srv,而不使用獨立的Request和Response對象
(4)調用服務:bool success = service_client.call(request, response)
注:
11. 服務器程序
(1)編寫回調函數 bool function_name(package_name::service_type::Request &req, package_name::service_type::Response &resp)
注:本例中請求和響應的數據類型均爲std_srvs/Empty(空字符串),無需進行數據處理
(2)與話題訂閱者相似,須要建立服務器對象ros::ServiceServer server=node_handle.advertiseService(service_name, pointer_to_callback_function);
注:本例使用ros::spinOnce()而非ros::spin(),緣由在於沒有服務調用時還須要執行其餘工做,即發佈速度指令 //與第三章 表3.5 進行對比
(3)解決ros::spinOnce() + sleep()引發的延遲問題
9、消息錄製與回放
1. rosbag:將發佈在一個或多個話題上的消息錄製到一個包文件中,可用於過後回放
注:術語包文件bag files指用於存儲帶時間戳的ROS消息的特殊文件格式
2. 命令行工具
(1)錄製包文件:rosbag record -O filename.bag topic-names //不指定文件名時,rosbag基於當前的日期和時間自動生成文件名;會建立新節點 /record_...
(2)回放包文件:rosbag play filename.bag //保持與原始發佈相同的順序和時間間隔
注:儘可能避免系統中rosbag和「真實」節點向同一個話題發佈消息
(3)檢查文件包:rosbag info filename.bag //提供包文件的豐富信息
3. rosbag功能包
(1)rosrun rosbag record -O filename.bag topic-names;rosrun rosbag play filename.bag //利用record和play可執行文件
(2)在啓動文件中使用包文件
注:須要提供參數
第十章 總結
1. 在網絡環境中運行ROS:分佈式機器人控制模式
(1)網絡層配置:確保計算機之間可以互相通訊
(2)ROS層配置:確保全部節點都能與節點管理器通訊
2. 編寫更規範的程序,如使用ros::Timer的回調函數替代ros::Rate對象
3. 使用rviz是數據可視化:訂閱用戶話題以顯示消息
4. 建立消息和服務類型
5. 使用tf工具來管理多個座標系:幫助節點完成座標轉換
6. 使用Gazebo仿真:高保真的機器人仿真器