ROS之話題的發布與訂閱


消息:

msg文件就是一個描述ROS中所使用消息類型的簡單文本。它們會被用來生成不同語言的源代碼。
注意,在構建的時候,我們只需要"message_generation"。然而,在運行的時候,我們只需要"message_runtime"。
查看package.xml, 確保它包含以下兩條語句:
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
在 CMakeLists.txt文件中,利用find_packag函數,增加對message_generation的依賴:
catkin_package( … CATKIN_DEPENDS message_runtime … …)
add_message_files( FILES Num.msg)
generate_messages()

1、創建工作空間:

mkdir -p ~/ROS_Learning_ws/src
cd ~/ROS_Learning_ws/src
catkin_init_workspace	#初始化工作空間
cd ~/ROS_Learning_ws
catkin_make	#編譯工作空間
source devel/setup.bash	#將該工作空間加入環境變量

2創建功能包:

創建工作空間后,工作空間可以順利通過編譯,此時工作空間不存在功能包,即還沒有功能實現。需要使用catkin_create_pkg創建功能包。

cd ~/ROS_Leraning/src
catkin_create_pkg learning_communication  std_msgs  roscpp  rospy

catkin_create_pkg命令行格式:catkin_create_pkg [package_name] [depend1] [depend2] [depend3]。因此上述命令行中的std_msgs和roscpp分別為功能包ROS_Test1的依賴項。

std_msgs:包含了常見的消息類型,表示基本數據類型和其他基本的消息構造。

roscpp:表示該功能包通過c++實現ROS的各種功能。提供了一個客戶端庫,c++開發者可以調用接口迅速完成主題、服務等相關工作。

rospy:表示該功能包通過python實現ROS的各種功能。提供了一個客戶端庫,python開發者可以調用接口迅速完成主題、服務等相關工作。

此時執行以下命令可以查看功能包的依賴項。  

rospack depends learning_communication    #查看功能包依賴項

3、編譯功能包:

 返回到工作空間根目錄:

cd ~/ROS_Learning
catkin_make

4、創建發布和訂閱節點

在功能包下的src文件下,即learning_communication/src創建發布話題節點文件:talker.cpp   內容如下:

 //該例程將發布chatter話題,消息類型String
 
#include <sstream>
#include "ros/ros.h"
#include "std_msgs/String.h"

int main(int argc, char **argv)
{
    // ROS節點初始化
    ros::init(argc, argv, "talker");

    // 創建節點句柄
    ros::NodeHandle n;

    // 創建一個Publisher,發布名為chatter的topic,消息類型為std_msgs::String
    ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

    // 設置循環的頻率
    ros::Rate loop_rate(10);

    int count = 0;
    while (ros::ok())
    {
        // 初始化std_msgs::String類型的消息
        std_msgs::String msg;
        std::stringstream ss;
        ss << "hello world " << count;
        msg.data = ss.str();

        // 發布消息
        ROS_INFO("%s", msg.data.c_str());
        chatter_pub.publish(msg);

        // 循環等待回調函數
        ros::spinOnce();

        // 按照循環頻率延時
        loop_rate.sleep();
        ++count;
    }

    return 0;
}

在功能包下的src文件下,即learning_communication/src創建訂閱話題節點文件:listener.cpp   內容如下:  

//該例程將訂閱chatter話題,消息類型String

 
#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節點
    ros::init(argc, argv, "listener");

    // 創建節點句柄
    ros::NodeHandle n;

    // 創建一個Subscriber,訂閱名為chatter的topic,注冊回調函數chatterCallback
    ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

    // 循環等待回調函數
    ros::spin();

    return 0;
}

在一個功能包內可以同時發布可創建多個實例化節點句柄,創建多個發布函數,創建多個訂閱回調函數。  

5、創建CMake文件:

learning_communication包根目錄下找到CMakeLists.txt文件在文件結尾端添加如下:

add_executable(talker src/talker.cpp)    #將talker.cpp文件編譯成可執行文件talker
target_link_libraries(talker ${catkin_LIBRARIES})      #為可執行文件talker添加鏈接庫 
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp) #添加可執行文件的消息依賴

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)

以上內容編輯完成以后,進行節點編譯:

回到工作空間根目錄進行編譯:

cd ~/ROS_Learning
catkin_make

編譯完成后運行

roscore
rosrun learning_communication talker   #需開啟新終端
rosrun learning_communication listener  #需開啟新終端

運行結果如下圖:

補充:

ros::ok()返回false的條件:

 

1. SIGINT收到(Ctrl-C)信號
2. 另一個同名節點啟動,會先中止之前的同名節點
3. ros::shutdown()被調用
4. 所有的ros::NodeHandles被銷毀

spinOnce()與spin()區別:
spinOnce()與spin()是兄弟函數,學名叫做消息回調處理函數。區別如下:

spinOnce()函數調用后,會繼續執行后續的代碼段。例如talker中,執行該函數后會繼續執行loop_rate.sleep()。
spin()調用后,程序不會返回,不會執行后續的代碼段。例如listener中,執行該函數后,程序不會返回。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM