zoukankan      html  css  js  c++  java
  • 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中,执行该函数后,程序不会返回。

  • 相关阅读:
    今天开始用 VSU 2010
    Visual Studio 2010 模型设计工具 基本应用
    Asp.Net访问Oracle 数据库 执行SQL语句和调用存储过程
    Enterprise Library 4.1 Security Block 快速使用图文笔记
    解决“System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本。”(图)
    一个Oracle存储过程示例
    Enterprise Library 4.1 Application Settings 快速使用图文笔记
    Oracle 10g for Windows 简体中文版的安装过程
    Oracle 11g for Windows 简体中文版的安装过程
    Oracle 9i 数据库 创建数据库 Net 配置 创建表 SQL查询 创建存储过程 (图)
  • 原文地址:https://www.cnblogs.com/qilai/p/13974458.html
Copyright © 2011-2022 走看看