ROS之初見Hello World

sherlock_lin發表於2021-05-21

前言

最近在玩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

這時候,工作區下面會出現 builddevel 兩個資料夾以及 .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、功能包編譯

前面說過,一個工作空間可以有多個功能包,因此編譯功能包有兩種方式:

  1. 編譯工作空間內的所有功能包;
  2. 編譯工作空間內的指定功能包;

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++,並深入框架層面,研究其原理。