zoukankan      html  css  js  c++  java
  • ROS节点通信(一)消息发布和订阅

    1、说明

    编写完ROS的hello world程序后,基本可以了解ROS的功能包开发的流程,现在再编写一个节点通信的测试代码,使用 topic 模式,即发布-订阅者模式,且传递的消息是自定义类型

    上代码

    2、创建工作空间

    该例不再创建新的工作空间,和hello world示例共用一个

    3、创建功能包

    cd src
    catkin_create_pkg test_topic message_generation std_msgs roscpp
    

    这里在创建功能包的时候,顺带把需要依赖的库也加进去了,好处就是,会默认把依赖库添加到 CMakeLists.txt 和 package.xml 中,而在 hello world 例子中,是手动添加的

    message_generation 会根据自定义类型的描述文件生成代码

    std_msgs 是ROS的字符串类

    这个功能包的名称就是 test_topic

    4、编写自定义传输类型文件

    cd test_topic
    mkdir msg && cd msg
    touch MessageDefine.msg
    

    编辑 MessageDefine.msg 文件,内容如下:

    time stamp
    int32 data
    string speak
    

    这里有三种类型,time 会生成ROS的Time类,这里不做详细说明

    5、编写源代码

    cd ../src
    

    依照惯例,代码还是放在src目录下

    5.1、编写发布者代码

    新增文件 test_publisher.cpp,代码如下:

    #include <ros/ros.h>
    #include <test_topic/MessageDefine.h>
    
    int main(int argc, char **argv)
    {
        //初始化发布者节点名称
        ros::init(argc, argv, "topic_publisher");
        //声明节点句柄与ROS系统进行通讯
        ros::NodeHandle nh;               
        //声明发布者,创建一个使用test_topic功能包MessageDefine消息文件的发布者
        //ros_tutorial_pub,话题名称是ros_message,消息发布者队列设置为100,如果消息发送太快,缓冲区的消息大于100,则会丢弃队列头
        ros::Publisher ros_tutorial_pub = nh.advertise<test_topic::MessageDefine>("ros_message", 100);
        //设定循环周期0.25HZ,4秒,需要配合sleep方法使用
        ros::Rate loop_rate(0.25);
        test_topic::MessageDefine msg; //声明一个消息
        int count = 0;
        std::stringstream talk;
        while (ros::ok())
        {
            //给MessageDefine.msg文件中的消息变量赋值
            msg.stamp = ros::Time::now();
            msg.data = count;
            msg.speak = "hello world, number: " + std::to_string(count);
            ROS_INFO("send stamp second = %d", msg.stamp.sec); //显示消息
            ROS_INFO("send data = %d", msg.data);
            ROS_INFO("%s", msg.speak.c_str());
            ros_tutorial_pub.publish(msg); //发布显示的消息
            ros::spinOnce();               //循环等待订阅节点的所有回调函数
            loop_rate.sleep();             //按设定值循环
            ++count;
        }
        return 0;
    }
    

    这里的 ros_message 是topic名称

    5.2、编写订阅者代码

    ros_message新增 test_subscriber.cpp,代码如下:

    #include <ros/ros.h>
    #include <test_topic/MessageDefine.h>
    
    //回调函数
    void messageCallback(const test_topic::MessageDefine::ConstPtr &msg)
    {
        ROS_INFO("recieve stamp second = %d", msg->stamp.sec);
        ROS_INFO("recieve data = %d", msg->data);
        ROS_INFO("receive str:[%s]", msg->speak.c_str());
    }
    int main(int argc, char **argv)
    {
        ros::init(argc, argv, "topic_subscriber"); //初始化订阅者节点
        ros::NodeHandle nh;
        //声明订阅者,创建一个使用test_topic功能包MessageDefine消息文件的订阅者
        //ros_tutorial_sub,订阅的话题名称是ros_message,消息接收者队列设置为100,如果消息处理太慢,缓冲区的消息数量大于100,则丢弃队列头部的消息
        ros::Subscriber ros_tutorial_sub = nh.subscribe<test_topic::MessageDefine>("ros_message", 100, messageCallback);
        ros::spin(); //调用后台,等待接收消息
        return 0;
    }
    

    ros::spin() 让程序进入自循环的挂起状态,让程序以最好的效率接收并执行回调

    当有消息达到 ros_message 时,执行一次回调函数

    6、编译

    修改编译配置

    因为创建功能包的时候,显示地指定了依赖,这些依赖会自动写进 CMakeLists.txt 和 package.xml 文件中,CMakeLists.txt 需要简单修改,package.xml文件无需改动

    CMakeLists.txt 文件如下

    cmake_minimum_required(VERSION 3.0.2)
    project(test_topic)
    
    add_compile_options(-std=c++11)
    
    #依赖库,创建包的时候添加了依赖,这里自动生成
    find_package(catkin REQUIRED COMPONENTS
      message_generation
      roscpp
      std_msgs
    )
    
    #添加自定义类型文件,这里自动生成的代码中注释说在msg文件夹下
    ## Generate messages in the 'msg' folder
    add_message_files(
      FILES
      MessageDefine.msg
    )
    generate_messages(
      DEPENDENCIES
      std_msgs
    )
    catkin_package(
     LIBRARIES test_topic
     CATKIN_DEPENDS roscpp std_msgs
    )
    
    include_directories(
      ${catkin_INCLUDE_DIRS}
    )
    
    #以下内容需要手动添加修改
    add_executable(${PROJECT_NAME}_publisher_node src/test_publisher.cpp)
    target_link_libraries(${PROJECT_NAME}_publisher_node  ${catkin_LIBRARIES})
    
    add_executable(${PROJECT_NAME}_subscriber_node src/test_subscriber.cpp)
    target_link_libraries(${PROJECT_NAME}_subscriber_node  ${catkin_LIBRARIES})
    

    编译指定包

    catkin_make -DCATKIN_WHITELIST_PACKAGES="test_topic"
    

    7、启动运行

    该例的包名为 test_topic,连个节点名是 test_topic_publisher_nodetest_topic_subscriber_node

    先启动节点管理器

    roscore
    

    启动发布者节点

    cd ~/project/catkin_ws
    source devel/setup.bash
    rosrun test_topic test_topic_publisher_node
    

    启动订阅者节点

    cd ~/project/catkin_ws
    source devel/setup.bash
    rosrun test_topic test_topic_subscriber_node
    

    查看效果,发布者每隔一段时间发送数据,订阅者接收到数据,打印出来

    8、查看ROS网络结构图

    rqt_graph
    

    结构图如下:

    img

  • 相关阅读:
    元素模式
    完美C++(第5版)(双色)
    ASP.NET Web API 2框架揭秘
    跨终端 Web
    WebKit技术内幕
    云计算时代——本质、技术、创新、战略
    互联网创业密码
    Netty权威指南
    Robot Framework 学习笔记(二)-------第一个脚本
    Robot Framework学习笔记(一)------环境搭建
  • 原文地址:https://www.cnblogs.com/sherlock-lin/p/14883526.html
Copyright © 2011-2022 走看看