前言
最近在玩ROS,筆記中斷了一段時間。
ROS即Robot Operating System,機器人作業系統,是一個開源框架,主力語言是C++和python,提供了硬體抽象、裝置驅動、庫函式、視覺化、訊息傳遞和軟體包管理等諸多功能。
我們先拋開機器人不談,ROS的設計思路還是值得學習的,它內部的最小執行單位是節點(node),執行時,啟動很多節點,每個節點完成一種特定的功能,且每個節點直接可以通訊。相似功能的節點組成一個包(package)。從原理上講,一個節點就是一個程式,多個節點的通訊就是程式間的通訊,而ROS中的程式間通訊不是傳統伺服器中的管道、訊息佇列這些,而是基於TCP/IP協議的通訊。
ROS框架中的程式間通訊的方式有多種,像釋出-訂閱者模式和流行的開源中介軟體是一樣的,其底層協議也是TCP和RPC,這個在後面文章中會詳細說明。
先來熟悉一下ROS,就先從Hello World開始吧!!!
1、建立工作空間
在需要防止程式碼的地方開啟命令列
#新建工作空間資料夾
mkdir catkin_ws && cd catkin_ws
#新建src資料夾
mkdir src
#初始化src目錄,生成CMakeLists.txt,為功能包編譯配置
cd src
catkin_init_workspace
這時候src目錄下會出現CMakeLists.txt,指令提示如下:
Creating symlink "/home/eco/project/MyCode/test_ws/src/CMakeLists.txt" pointing to "/opt/ros/kinetic/share/catkin/cmake/toplevel.cmake"
可知,這個CMakeLists.txt只是一個ROS庫中的連結,後面不要更改它
#回到工作空間,並對工作空間進行一次編譯
cd ..
catkin_make
這時候,工作區下面會出現 build 和 devel 兩個資料夾以及 .catkin_workspace 檔案
#配置環境變數,使新建的工作空間可用
source devel/setup.bash
#檢視配置的變數
echo $ROS_PACKAGE_PATH
到此,一個新的ROS工作空間已經建立完成
一個工作空間可以包含多個功能包,所有的功能包都在工作空間的src目錄下
2、建立功能包
現在,我們想建立一個功能包,名稱是 hello_world
#到工作空間的src目錄下建立功能包
cd src
catkin_create_pkg hello_world
這時,工作空間的 src 目錄下出現 hello_world 資料夾,這個名稱就是功能包的名稱及其唯一標誌符,功能包建立完成
3、編寫功能包原始碼
本次,我們編寫一個能列印 hello world 的程式
我們在功能包的目錄新建一個 src 資料夾,用於存放C++的原始碼,這個不是必須的,但是出於規範考慮,最好這樣做,便於組織程式碼結構
cd hello_world
mkdir src && cd src
#建立程式碼檔案
touch my_hello_world_node.cpp
在 my_hello_world_node.cpp 中編寫程式碼
#include "ros/ros.h"
//ros.h是ROS提供的C++客戶端庫,後面需要在編譯配置中新增依賴庫roscpp
int main(int argc,char **argv)
{
//初始化ros節點並知名節點名稱
//程式執行後,ros的計算圖中被註冊為hello_node名稱標識的節點
ros::init(argc,argv,"hello_node");
//宣告一個ros節點控制程式碼,初始化ros節點必須的
ros::NodeHandle nh;
//ROS_INFO_STREAM是roscpp庫中的列印資訊方法,這裡列印一個字串
ROS_INFO_STREAM("hello world!!!");
}
4、功能包編譯配置
這時候的工作空間是有兩個 CMakeLists.txt 的,工作空間下的是連結,不要更改,修改功能包中的CMakeLists.txt,本次修改的內容有下面幾種
4.1、新增依賴項
因為程式碼中用到了 ros/ros.h ,因此需要 roscpp 庫
find_package(catkin REQUIRED COMPONENTS roscpp)
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
修改功能包目錄下的 package.xml 檔案,找到 <buildtool_depend>catkin</buildtool_depend>,並在下面新增內容:
<build_depend>roscpp</build_depend>
<build_export_depend>roscpp</build_export_depend>
<exec_depend>roscpp</exec_depend>
4.2、宣告可執行檔案
add_executable(my_hello_world_node src/my_hello_world_node.cpp)
#連結時需要連結哪些庫,在find_package中定義
target_link_libraries(my_hello_world_node ${catkin_LIBRARIES})
至此,功能包的編譯配置完成
5、功能包編譯
前面說過,一個工作空間可以有多個功能包,因此編譯功能包有兩種方式:
- 編譯工作空間內的所有功能包;
- 編譯工作空間內的指定功能包;
5.1、編譯所有功能包
cd ~/project/catkin_ws/
catkin_make
5.2、編譯指定功能包
使用 DCATKIN_WHITELIST_PACKAGES 引數指定
cd ~/project/catkin_ws
catkin_make -DCATKIN_WHITELIST_PACKAGES="hello_world"
6、功能包啟動執行
先啟動ROS節點管理器,這個是所有節點執行的基礎
roscore
然後啟用工作空間
cd ~/project/catkin_ws
source devel/setup.bash
最後啟動功能包中的節點
rosrun hello_world my_hello_world_node
rosrun 指令的第一個引數是功能包名,第二個引數是需要啟動的節點名
輸出
[ INFO] [1620370500.474021642]: hello world!!!
到此,第一個程式完成,後面會繼續學習ROS和C++,並深入框架層面,研究其原理。