zoukankan      html  css  js  c++  java
  • ROS话题通信案例(三)——自定义消息msg(c++和python)

    参考视频:【奥特学园】ROS机器人入门课程《ROS理论与实践》零基础教程_哔哩哔哩_bilibili

    参考文档:http://www.autolabor.com.cn/book/ROSTutorials/

    需求:

      创建自定义消息,该消息包含人的信息:姓名、身高、年龄等。

    流程:

    1. 按照固定格式创建 msg 文件
    2. 编辑配置文件
    3. 编译生成可以被 Python 或 C++ 调用的中间文件

    1.定义msg文件

    功能包下新建 msg 目录,添加文件 Person.msg

    string name
    uint16 age
    float64 height

    2.编辑配置文件

    package.xml中添加编译依赖与执行依赖

      <build_depend>message_generation</build_depend>
      <exec_depend>message_runtime</exec_depend>
      <!-- 
      exce_depend 以前对应的是 run_depend 现在非法
      -->

    CMakeLists.txt编辑 msg 相关配置

    find_package(catkin REQUIRED COMPONENTS
      roscpp
      rospy
      std_msgs
      message_generation
    )
    # 需要加入 message_generation,必须有 std_msgs
    
    ## 配置 msg 源文件
    add_message_files(
      FILES
      Person.msg
    )
    
    # 生成消息时依赖于 std_msgs
    generate_messages(
      DEPENDENCIES
      std_msgs
    )
    
    #执行时依赖
    catkin_package(
    #  INCLUDE_DIRS include
    #  LIBRARIES demo02_talker_listener
      CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
    #  DEPENDS system_lib
    )

     

     

    3.编译

    编译后的中间文件查看:

    C++ 需要调用的中间文件(.../工作空间/devel/include/包名/xxx.h)

    Python 需要调用的中间文件(.../工作空间/devel/lib/python3/dist-packages/包名/msg)


    C++实现

    需求:

    编写发布订阅实现,要求发布方以10HZ(每秒10次)的频率发布自定义消息,订阅方订阅自定义消息并将消息内容打印输出。

    分析:

    在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:

    1. 发布方
    2. 接收方
    3. 数据(此处为自定义消息)

    流程:

    1. 编写发布方实现;
    2. 编写订阅方实现;
    3. 编辑配置文件;
    4. 编译并执行

    0.vscode 配置

    为了方便代码提示以及避免误抛异常,需要先配置 vscode,将前面生成的 head 文件路径配置进 c_cpp_properties.json 的 includepath属性

    "/xxx/yyy工作空间/devel/include/**" //配置 head 文件的路径 

    1.发布方

    #include "ros/ros.h"
    #include "plumbing_pub_sub/Person.h"
    /*
        发布者:发布人的消息
            1.包含头文件;
            2.初始化ROS节点
            3.创建节点句柄
            4.创建发布者对象
            5.编写发布者逻辑,发布数据。
    */
    int main(int argc, char *argv[])
    {
        setlocale(LC_ALL,"");
        ROS_INFO("这是消息发布方");
        // 2.初始化ROS节点
        ros::init(argc,argv,"banZhuanRen");
        // 3.创建节点句柄
        ros::NodeHandle nh;
        // 4.创建发布者对象
        ros::Publisher pub = nh.advertise<plumbing_pub_sub::Person>("Chat",10);
        // 5.编写发布者逻辑,发布数据。
        //5.1.被发布的数据
        plumbing_pub_sub::Person person;
        person.name = "张三";
        person.age = 1;
        person.height = 1.73;
        //5.2.设置发布的频率
        ros::Rate rate(1);
        //5.3.循环发布数据
        while (ros::ok())
        {
            //修改数据
            person.age += 1;
            //核心:数据发布
            pub.publish(person);
            ROS_INFO("发布的消息:%s,%d,%.2f",person.name.c_str(),person.age,person.height);
            //休眠
            rate.sleep();
            //建议
            ros::spinOnce();
    
        }
        return 0;
    }
        

    配置

    执行

    2.订阅方

    #include "ros/ros.h"
    #include "plumbing_pub_sub/Person.h"
    
    /*
        订阅方:订阅消息
            1.包含头文件;
                #include "plumbing_pub_sub/Person.h"
            2.初始化ROS节点
            3.创建节点句柄
            4.创建订阅者对象
            5.处理订阅的数据
            6.调用spin()函数
    */
    void doPerson (const plumbing_pub_sub::Person::ConstPtr& person){
        ROS_INFO("订阅人的信息:%s,%d,%.2f",person->name.c_str(),person->age,person->height);
    }
    int main(int argc, char *argv[])
    {
        setlocale(LC_ALL,"");
        ROS_INFO("订阅方实现");
        // 2.初始化ROS节点
        ros::init(argc,argv,"jiaZhang");
        // 3.创建节点句柄
        ros::NodeHandle nh;
        // 4.创建订阅者对象
        ros::Subscriber sub = nh.subscribe("Chat",10,doPerson);
        // 5.处理订阅的数据
        // 6.调用spin()函数
        ros::spin();
        return 0;
    }

    配置

    执行


    python 实现

    0.vscode配置

    将自定义 msg 所在的文件夹配置进 settings.json

    1.发布方

    在 scripts 下新建 demo03_pub_person_p.py

    #! /usr/bin/env python
    
    import rospy
    from plumbing_pub_sub.msg import Person
    '''
        发布方:发布人的消息
            1.导包;
            2.初始化ROS节点;
            3.创建发布者对象;
            4.组织发布逻辑并发布数据。
    
    '''
    
    if __name__ == "__main__":
        # 2.初始化ROS节点;
        rospy.init_node("daMa")
        # 3.创建发布者对象;
        pub = rospy.Publisher("jiaoSheTou",Person,queue_size=10)
        # 4.组织发布逻辑并发布数据。
        # 4.1.创建 Person 数据
        p = Person()
        p.name = "奥特曼"
        p.age = 8
        p.height = 1.85
        # 4.2.创建 Rate 对象
        rate = rospy.Rate(1)
        # 4.3.循环发布数据
        while not rospy.is_shutdown():
            pub.publish(p)
            rospy.loginfo("发布的消息:%s,%d,%.2f",p.name,p.age,p.height)
            rate.sleep()

    2.权限设置

    给 py 文件增加可执行权限

    cys@ubuntu:~/demo03_ws/src/plumbing_pub_sub/scripts$ chmod +x *.py

    3.配置 CMakeLists.txt

    更改 CMakeLists.txt 中的配置

     4.命令行测试

    cys@ubuntu:~/demo03_ws$ source ./devel/setup.bash
    cys@ubuntu:~/demo03_ws$ rosrun plumbing_pub_sub demo03_pub_person_p.py

    cys@ubuntu:~/demo03_ws$ source ./devel/setup.bash
    cys@ubuntu:~/demo03_ws$ rostopic echo jiaoSheTou

    5.订阅方

     在 scripts 下新建 demo04_sub_person_p.py

    #! /usr/bin/env python
    
    import rospy
    from plumbing_pub_sub.msg import Person
    '''
        订阅方:订阅人的消息
            1.导包;
            2.初始化ROS节点;
            3.创建订阅者对象;
            4.处理订阅的数据;
            5.spin()。
    
    '''
    def doPerson(p):
        rospy.loginfo("小伙子的数据:%s,%d,%.2f",p.name,p.age,p.height)
    
    if __name__ == "__main__":
        # 2.初始化ROS节点;
        rospy.init_node("daYe")
        # 3.创建订阅者对象;
        sub = rospy.Subscriber("jiaoSheTou",Person,doPerson)
        # 4.处理订阅的数据;
        # 5.spin()。
        rospy.spin()

    修改权限和配置

     6.运行

    启动发布方

    启动订阅方

    cys@ubuntu:~/demo03_ws$ source ./devel/setup.bash
    cys@ubuntu:~/demo03_ws$ rosrun plumbing_pub_sub demo04_sub_person_p.py 

     7.绘制计算图

    cys@ubuntu:~$ rqt_graph 

  • 相关阅读:
    apache phoenix查询缓慢问题
    hbase replication原理分析
    ServerSocketChannel实现多Selector高并发server
    hbase hmaster故障分析及解决方案:Timedout 300000ms waiting for namespace table to be assigned
    mapreduce出现类似死锁情况
    【转】How-to: Enable User Authentication and Authorization in Apache HBase
    最近的一些杂念思考
    我究竟该成为什么样的一个人
    解决linux下 使用netcore生成图片报错的问题:The type initializer for 'Gdip' threw an exception
    linux 编译安装nginx
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/15008101.html
Copyright © 2011-2022 走看看