【ROS實踐學習入門系列(五)自定義節點功能包使用與消息傳遞】
本內容經官網實例以及一些參考書總結而成,歡迎留言評論交流~
聯繫方式:ziyuanw#foxmail.com(#換成@)
一、回顧小海龜案例:
在小海龜的案例中我們知道有兩個節點的終端窗口,在一個終端窗口中輸入鍵盤消息,另外一個終端窗口接收消息,最後才使得小海龜的圖像按照鍵盤方向移動。
rostopic發佈器節點(紅色)正在與rostopic 輸出海龜動作節點(綠色),通過鍵盤/turtle1/cmd_vel控制方向的輸入消息,進行通信:
那麼問題來了我想自己定義兩個類似的節點然後讓他們完成類似的工作也是可行的,或者說,ROS系統的節點之間通信的基礎就是:一個節點發布數據,另外一個節點接收數據,同時操作數據並使用這些數據來完成一些任務和工作。
二、自定義功能包:
1.創建catkin工作空間:
我這裏就在用戶家目錄下直接創建名爲catkin_ws的catkin工作空間。(創建功能包的目錄可自行選擇)
$mkdir -p ~/catkin_ws/src
$cd ~/catkin_ws
$catkin_make
回顧之前博客中的catkin工作空間相關文件說明。ROS的任務都是在自己的工作空間完成的。因此爲了保證自己創建的兩個節點能夠順利完成任務,我需要自定義一個catkin工作空間來將這兩個節點放入。而這兩個節點所完成的任務即構成了第二篇博客中所說的功能包。如果在自己的工作空間有多個這種類似任務的功能包,即組成了元功能包。
具有元功能包集合的catkin工作空間目錄結構如下:
catkin_workspace_folder/ -- WORKSPACE
src/ -- SOURCE SPACE
CMakeLists.txt -- 'Toplevel' CMake file, provided by catkin
package_1/
CMakeLists.txt -- CMakeLists.txt file for package_1
package.xml -- Package manifest for package_1
...
package_n/
CMakeLists.txt -- CMakeLists.txt file for package_n
package.xml -- Package manifest for package_n
2.創建功能包
有了工作空間還只是第一步基礎,在之前博客中所說到的,一個功能包要想完成一個功能,一定要有功能包清單即package.xml文件進行管理,以及CMakeLists.txt文件對功能包中的實現節點功能的源程序進行編譯,進而建立其與工作空間的聯繫纔行。
一個catkin功能包必須包含:
- CMakeLists.txt
- package.xml
最簡單的程序包看起來就像這樣:
my_package/
CMakeLists.txt
package.xml
ROS創建功能包的命令:
catkin_create_pkg [packagename] [dependency1] .... [dependencyN]
第一個參數爲自定義功能名稱,後面爲建立功能包所需要的依賴包。
- (注意,功能包都是在catkin_ws的src目錄下創建。)
這裏我創建一個名爲test的功能包:
catkin_create_pkg test std_msgs roscpp
參數說明:
- catkin_create_pkg 命令創建了一個名爲test的功能包。
- std_msgs:包含了創建消息類型,表示基本數據類型和其他基本的消息構建,如多維數組。
- roscpp:使用C++實現ROS的功能,它提供了一個客戶端庫,能夠讓開發者使用這些接口快速完成與ROS主題,服務,參數相關開發工作。
最後完成創建可發現在~/catkin_ws/src下面多出了一個test文件夾,我的功能包節點源程序就需要放在其下src目錄中。其中文件結構如下:由於其爲一個功能包,因此可使用rospack命令對其進行查找路徑和查看依賴關係:
創建完功能包記得進入工作空間更新一下環境變量配置,不然會出現找不到功能包。
3.創建節點
本例我創建一個名爲example1_a的節點用於發送消息,一個名爲example1_b用於接收消息並將消息輸出在屏幕。兩個節點的源程序分別爲example1_a.cpp和example1_b.cpp放在~/catkin_ws/src/test/src目錄下:
example1_a.cpp源程序如下:
#include<ros/ros.h> //包含ROS節點所有必要的文件
#include<std_msgs/String.h> //包含要使用的消息類型
#include<sstream> //字符串流輸入輸出
int main(int argc,char **argv)
{ //初始化節點並設置名稱(該名稱唯一)
ros::init(argc,argv,"example1_a");
//進程的處理程序,允許我們與環境交互
ros::NodeHandle n;
//將節點實例化爲發佈者,將發佈主題和名稱告知節點管理器,名爲message,第二個參數爲緩衝區大小,若主題發佈數據速度較快,緩衝區至少設置爲存放1000條消息
ros::Publisher chatter_pub=n.advertise<std_msgs::String>("message",1000);
//發送數據的頻率爲10HZ
ros::Rate loop_rate(10);
//按下Crtl+C組合或ROS停止所有節點,ros::ok()停止
while(ros::ok())
{ //創建一個消息變量,變量類型必須符合發送數據要求
std_msgs::String msg;
//定義字符串流
std::stringstream ss;
ss<<"I am the example1_a node";
msg.data=ss.str();
//ROS_INFO("%s",msg.data.c_str());
//繼續發佈消息,使用之前發佈器的定義發佈消息
chatter_pub.publish(msg);
//spinOnce()函數負責處理所有ROS內部時間和操作,例如讀取訂閱的消息。
ros::spinOnce();
//按照10HZ頻率將程序掛起
loop_rate.sleep();
}
return 0;
}
example1_b.cpp源程序如下:
#include<ros/ros.h> //包含ROS節點所有必要的文件
#include<std_msgs/String.h> //包含要使用的消息類型
//設置回調函數messageCallback,每次該節點收到一條消息時都會調用此函數。該函數可以處理數據。
void messageCallback(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,"example1_b");
//進程的處理程序,允許我們與環境交互
ros::NodeHandle n;
//將節點實例化爲訂閱者,並將所發佈的主題類型的名稱告知節點管理器。名爲message。處理消息的函數爲messageCallback
ros::Subscriber sub = n.subscribe("message",1000,messageCallback);
//spin()函數負責處理節點開始讀取主題和在消息到達時,回調函數messageCallback被調用的主循環。Ctrl+C組合建,節點退出消息循環,於是結束循環
ros::spin();
return 0;
}
4.編譯節點
①修改CMakeLists.txt文件:
rosed工作空間內跳轉並以文本方式(默認編輯器爲:vim) 打開CMakeLists.txt文件,並添加可執行文件,依賴,目標鏈接庫:
在最後一行添加如下內容:
## Build the example1_a and example1_b
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_executable(example1_a src/example1_a.cpp)
add_dependencies(example1_a test_generate_messages_cpp)
target_link_libraries(example1_a ${catkin_LIBRARIES})
add_executable(example1_b src/example1_b.cpp)
add_dependencies(example1_b test_generate_messages_cpp)
target_link_libraries(example1_b ${catkin_LIBRARIES})
②catkin_make編譯節點:
$cd ~/catkin_ws
$catkin_make
- (PS:後面參數可選爲編譯指定功能包,若缺省則默認編譯全部功能包的全部節點。)
catkin_make --pkg [packagename]
編譯完成可看到輸出成功兩個可執行節點。
5.運行節點
還是之前博客中所提到的步驟:
在~/catkin_ws工作空間中:
1.打開第一個終端窗口輸入:roscore
2.打開第二個終端輸入:rosrun test example1_a
3.打開第三個終端輸入:rosrun test example1_b
- 此時不要先急於執行,一定要先在終端中更新一下環境配置,不然可能找不到該節點:
效果如下:
6.rqt_graph查看節點消息傳遞
在上面兩個節點傳遞消息同時,CTRL+Shift+T打開第四個終端:
可以看到節點example1_a發佈message主題,節點example1_b訂閱該主題。
至此,一個簡單的兩個節點功能包test已經完成,後面將會用到新的功能用於節點通信:消息和服務。
下一篇:【ROS實踐入門(六)消息msg和服務srv文件創建與使用】
參考資料:
【1】ROS官網:http://wiki.ros.org/cn
【2】ROS機器人高效編程