发布者Publisher、订阅者Subscriber的编程实现+自定义话题消息编程实现

news2024/10/25 17:10:10

1.发布者Publisher的编程实现

1.创建功能包

cd ~/catkin_ws/src
catkin_create_pkg learning_topic rospy roscpp std_msgs geometry_msgs turtlesim

2.创建发布者代码(C++) ——文件名为velocity_publisher.cp

/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/

/**
 * 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist
 */
 
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>

int main(int argc, char **argv)
{
  // ROS节点初始化
  ros::init(argc, argv, "velocity_publisher");  //velocity_publisher为节点

  // 创建节点句柄
  ros::NodeHandle n;   

  // 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
  ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);

  // 设置循环的频率
  ros::Rate loop_rate(10);

  int count = 0;
  while (ros::ok())
  {
      // 初始化geometry_msgs::Twist类型的消息
    geometry_msgs::Twist vel_msg;
    vel_msg.linear.x = 0.5;
    vel_msg.angular.z = 0.2;

      // 发布消息
    turtle_vel_pub.publish(vel_msg);
    ROS_INFO("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
        vel_msg.linear.x, vel_msg.angular.z);

      // 按照循环频率延时
      loop_rate.sleep();
  }

  return 0;
}

总结上面的代码,实现一个发布者的步骤为:

  • 初始化ROS节点
  • 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型
  • 创建消息数据
  • 按照一定的频率循环发布消息

这里也给出python的代码实现,实现步骤与C++一致 

#!/usr/bin/env python
# -*- coding: utf-8 -*-

########################################################################
####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
########################################################################

# 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist

import rospy
from geometry_msgs.msg import Twist

def velocity_publisher():
  # ROS节点初始化
    rospy.init_node('velocity_publisher', anonymous=True)

  # 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
    turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)

  #设置循环的频率
    rate = rospy.Rate(10) 

    while not rospy.is_shutdown():
    # 初始化geometry_msgs::Twist类型的消息
        vel_msg = Twist()
        vel_msg.linear.x = 0.5
        vel_msg.angular.z = 0.2

    # 发布消息
        turtle_vel_pub.publish(vel_msg)
      rospy.loginfo("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
        vel_msg.linear.x, vel_msg.angular.z)

    # 按照循环频率延时
        rate.sleep()

if __name__ == '__main__':
    try:
        velocity_publisher()
    except rospy.ROSInterruptException:
        pass

3

  1. 配置发布者代码编译规则

    配置编译规则主要进行两个设置:

    1. 第一个是设置需要的编译的代码和生成的可执行文件

 

add_executable(velocity_publisher src/velocity_publisher.cpp)

这句代码的含义是编译src路径下的velocity_publisher.cpp文件,并生成可执行文件velocity_publisher。

    1. 第二个是设置链接库
      target_link_libraries(velocity_publisher ${catkin_LIBRARIES})

      将上述两行代码放置到功能包learning_topic下的CMakeLists.txt中,放置具体位置如下图所示:

4.编译并运行发布者

cd ~/catkin_ws
catkin_make
source devel/setup.bash
roscore
rosrun turtlesim turtlesim_node 
rosrun learning_topic velocity_publisher

可以从下图看出,小海龟正以0.5m/s,0.2rad/s的速度运动,此时做圆周运动。5、订阅者Subscriber的编程实现

1.创建订阅者代码(c++) ——文件名为pose_subscriber.cpp

/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/

/**
 * 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
 */
 
#include <ros/ros.h>
#include "turtlesim/Pose.h"

// 接收到订阅的消息后,会进入消息回调函数
void poseCallback(const turtlesim::Pose::ConstPtr& msg)
{
    // 将接收到的消息打印出来
    ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f", msg->x, msg->y);
}

int main(int argc, char **argv)
{
    // 初始化ROS节点
    ros::init(argc, argv, "pose_subscriber");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
    ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);

    // 循环等待回调函数
    ros::spin();

    return 0;
}

总结上面的代码,实现一个订阅者的步骤为:

  • 初始化ROS节点
  • 订阅需要的话题
  • 循环等待话题消息,接收到消息后进入回调函数
  • 在回调函数中完成消息处理

这里同样给出python的代码实现,实现步骤与C++一致

#!/usr/bin/env python
# -*- coding: utf-8 -*-

########################################################################
####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
########################################################################

# 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose

import rospy
from turtlesim.msg import Pose

def poseCallback(msg):
    rospy.loginfo("Turtle pose: x:%0.6f, y:%0.6f", msg.x, msg.y)

def pose_subscriber():
  # ROS节点初始化
    rospy.init_node('pose_subscriber', anonymous=True)

  # 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
    rospy.Subscriber("/turtle1/pose", Pose, poseCallback)

  # 循环等待回调函数
    rospy.spin()

if __name__ == '__main__':
    pose_subscriber()
  1.   配置订阅者代码编译规则

配置编译规则主要进行两个设置:

    • 第一个是设置需要的编译的代码和生成的可执行文件
      add_executable(pose_subscriber src/pose_subscriber.cpp)

      这句代码的含义是编译src路径下的pose_subscriber.cpp文件,并生成可执行文件pose_subscriber。

      • 第二个是设置链接库
        target_link_libraries(pose_subscriber ${catkin_LIBRARIES})

        是不是发现和配置发布者代码编译规则基本一致,是的,可以说没什么区别,那么这两句代码就可以放在配置发布者代码的下面。如图:

      • 编译并运行订阅者

        cd ~/catkin_ws
        catkin_make
        source devel/setup.bash
        roscore
        rosrun turtlesim turtlesim_node 
        rosrun learning_topic velocity_publisher

自定义话题消息

6、自定义话题消息

上文介绍了话题的订阅和发布,但这些话题都是系统提供的,我们自然会想到,我们可不可以自己定义话题来使用呢?…好吧…我这么说肯定是有的了,下面就来介绍自定义话题消息的定义和使用 。

  1. 定义话题消息
  • 定义msg文件
    //在learning_topic目录下创建msg文件夹
    cd ~/catkin_ws/src/learning_topic
    mkdir msg
    //创建Penson.msg文件
    touch Person.msg

    创建好Person.msg文件后,在文件中写入以下内容:

    string name
    uint8 sex
    uint8 age
    
    uint8 unknown = 0
    uint8 male = 1
    uint8 female = 2

    在package.xml中添加功能包依赖

    <build_depend>message_generation</build_depend>
    <exec_depend>message_runtime</exec_depend>

    在CMakeLists.txt中添加编译选项

    find_package( …… message_generation)
    catkin_package(…… message_runtime)
    add_message_files(FILES Person.msg)
    generate_messages(DEPENDENCIES std_msgs)

    catkin_package(…… message_runtime)

    编译生成语言相关文件
    cd ~/catkin_ws
    catkin_make

    实现一个发布者(C++) ——文件名为person_publisher.cpp

    /***********************************************************************
    Copyright 2020 GuYueHome (www.guyuehome.com).
    ***********************************************************************/
    
    /**
     * 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
     */
     
    #include <ros/ros.h>
    #include "learning_topic/Person.h"
    
    int main(int argc, char **argv)
    {
        // ROS节点初始化
        ros::init(argc, argv, "person_publisher");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
        ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);
    
        // 设置循环的频率
        ros::Rate loop_rate(10);
    
        int count = 0;
        while (ros::ok())
        {
            // 初始化learning_topic::Person类型的消息
          learning_topic::Person person_msg;
        person_msg.name = "wsj";
        person_msg.age  = 18;
        person_msg.sex  = learning_topic::Person::male;
    
            // 发布消息
        person_info_pub.publish(person_msg);
    
            ROS_INFO("Publish Person Info: name:%s  age:%d  sex:%d", 
              person_msg.name.c_str(), person_msg.age, person_msg.sex);
    
            // 按照循环频率延时
            loop_rate.sleep();
        }
    
        return 0;
    }

    该部分和之前的步骤基本一致,这里不再进行总结。

    同样,这里给出python的代码供参考:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    ########################################################################
    ####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
    ########################################################################
    
    # 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
    
    import rospy
    from learning_topic.msg import Person
    
    def velocity_publisher():
      # ROS节点初始化
        rospy.init_node('person_publisher', anonymous=True)
    
      # 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
        person_info_pub = rospy.Publisher('/person_info', Person, queue_size=10)
    
      #设置循环的频率
        rate = rospy.Rate(10) 
    
        while not rospy.is_shutdown():
        # 初始化learning_topic::Person类型的消息
          person_msg = Person()
          person_msg.name = "wsj";
          person_msg.age  = 18;
          person_msg.sex  = Person.male;
    
        # 发布消息
            person_info_pub.publish(person_msg)
          rospy.loginfo("Publsh person message[%s, %d, %d]", 
            person_msg.name, person_msg.age, person_msg.sex)
    
        # 按照循环频率延时
            rate.sleep()
    
    if __name__ == '__main__':
        try:
            velocity_publisher()
        except rospy.ROSInterruptException:
            pass

    实现一个订阅者(C++) ——文件名为person_subscriber.cpp

    /***********************************************************************
    Copyright 2020 GuYueHome (www.guyuehome.com).
    ***********************************************************************/
    
    /**
     * 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
     */
     
    #include <ros/ros.h>
    #include "learning_topic/Person.h"
    
    // 接收到订阅的消息后,会进入消息回调函数
    void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
    {
        // 将接收到的消息打印出来
        ROS_INFO("Subcribe Person Info: name:%s  age:%d  sex:%d", 
           msg->name.c_str(), msg->age, msg->sex);
    }
    
    int main(int argc, char **argv)
    {
        // 初始化ROS节点
        ros::init(argc, argv, "person_subscriber");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
        ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
    
        // 循环等待回调函数
        ros::spin();
    
        return 0;
    }

    python代码如下:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    ########################################################################
    ####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
    ########################################################################
    
    # 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
    
    import rospy
    from learning_topic.msg import Person
    
    def personInfoCallback(msg):
        rospy.loginfo("Subcribe Person Info: name:%s  age:%d  sex:%d", 
           msg.name, msg.age, msg.sex)
    
    def person_subscriber():
      # ROS节点初始化
        rospy.init_node('person_subscriber', anonymous=True)
    
      # 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
        rospy.Subscriber("/person_info", Person, personInfoCallback)
    
      # 循环等待回调函数
        rospy.spin()
    
    if __name__ == '__main__':
        person_subscriber()

  • 配置编译规则
  • 设置需要编译的代码和可执行文件
  • 设置链接库
  • 添加依赖项
    add_executable(person_publisher src/person_publisher.cpp)
    target_link_libraries(person_publisher ${catkin_LIBRARIES})
    add_dependencies(person_publisher ${PROJECT_NAME}_generate_messages_cpp)
    
    add_executable(person_subscriber src/person_subscriber.cpp)
    target_link_libraries(person_subscriber ${catkin_LIBRARIES})
    add_dependencies(person_subscriber ${PROJECT_NAME}_generate_messages_cpp)

    放置的具体位置如下:编译并运行发布者和订阅者

    cd ~/catkin_ws
    catkin_make
    roscore
    rosrun learning_topic person_subscriber
    rosrun learning_topic person_publisher

    运行结果如下:发布消息后成功订阅

    **注:**这里我们可以尝试程序运行过程中把roscore关掉,看看是否能继续发布和订阅消息?

    (答案是能,roscore启动是Rosmaster, Rosmaster这里的作用是帮助建立连接,一旦连接建立好,关掉roscore也无影响)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2223426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Vue】word / excel / ppt / pdf / 视频(mp4,mov) 预览

文件预览 Vue3一. word二. excel三. ppt四. pdf4.1 vue-pdf-embed4.2 iframe 五. 视频六&#xff1a;扩展——kkFileView Vue3 一. word 安装&#xff1a;npm install docx-preview父页面 <template><div><DocPreviewv-if"filePath.includes(docx)"…

E. Sakurako, Kosuke, and the Permutation (置换环) Codeforces Round 981 (Div. 3)

哈哈哈, 之前做过一道置换环的题目, 但是当时不知道这是置换环 昨天写这道题目时老眼昏花, 读错题目, 如今一朝有悟,甄至化境 原题 E. Sakurako, Kosuke, and the Permutation 思路 这道题目与排序的不同在于, 如果第 i 个数不等于 i, 但是第 i 个数指向的数等于 i, 那么也…

基于RabbitMQ,Redis,Redisson,RocketMQ四种技术实现订单延时关闭功能及其相关优缺点介绍(以12306为主题)

目录 1. 延迟关闭订单 1.1 订单延时关闭功能技术选型 1.1.1 定时任务 1.1.2 RabbitMQ 1.1.3 Redis 过期监听 1.1.4 Redisson 1.1.5 RocketMQ 1.2 RocketMQ订单延时关闭发送方实现 1.3 RocketMQ订单延时关闭的消费方实现 1. 延迟关闭订单 用户发起订单后&#xff0c;如…

基于SSM的BBS社区论坛系统源码

运行环境&#xff1a;ideamysql5.7jdk8maven 使用技术&#xff1a;ssmmysqlshirolayui 功能模块&#xff1a;用户管理、模板管理、帖子管理、公告管理、权限管理等

使用 v-html 指令渲染的标签, 标签内绑定的 click 事件不生效

背景 在项目开发中&#xff0c;实现用户友好的输入交互是提升用户体验的关键之一。例如&#xff0c;在客服对话框中&#xff0c;其中有包含多个快捷选项用于快速问答&#xff0c;每个快捷选项都是一个可点击的按钮&#xff0c;并需要绑定点击事件来执行相应操作。然而&#xf…

Android Junit 单元测试 | 依赖配置和编译报错解决

问题 为什么在依赖中添加了testImplement在build APK的时候还是会报错&#xff1f;是因为没有识别到test文件夹是test源代码路径吗&#xff1f; 最常见的配置有: implementation - 所有源代码集(包括test源代码集)中都有该依赖库.testImplementation - 依赖关系仅在test源代码…

【CSS in Depth 2 精译_054】8.2 CSS 层叠图层(cascade layer)的推荐组织方案

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 【第三部分 现代 CSS 代码组织】 ✔️【第八章 层叠图层及其嵌套】 ✔️ 8.1 用 layer 图层来操控层叠规则&#xff08;上篇&#xff09; 8.1.1 图层的定义&#xff08;上篇&#xff09;8.1.2 图层的…

华为云实战杂记

配置nginx服务器 首先我们拿到一台服务器时&#xff0c;并不知道系统是否存在Nginx我们可以在Linux命令行执行如下命令查看 find / -name nginx* find / -name nginx* 查找所有名字以nginx开头的文件或者目录&#xff0c;我们看看系统里面都有哪些文件先&#xff0c;这样可以快…

Linux系统安装Redis详细操作步骤(二进制发布包安装方式)

安装方式介绍 在Linux系统中&#xff0c;安装软件的方式主要有四种&#xff0c;这四种安装方式的特点如下&#xff1a; 安装方式特点二进制发布包安装软件已经针对具体平台编译打包发布&#xff0c;只要解压&#xff0c;修改配置即可rpm安装软件已经按照redhat的包管理规范进…

雷池社区版有多个防护站点监听在同一个端口上,匹配顺序是怎么样的

如果域名处填写的分别为 IP 与域名&#xff0c;那么当使用进行 IP 请求时&#xff0c;则将会命中第一个配置的站点 以上图为例&#xff0c;如果用户使用 IP 访问&#xff0c;命中 example.com。 如果域名处填写的分别为域名与泛域名&#xff0c;除非准确命中域名&#xff0c;否…

NGINX 保护 Web 应用安全之基于 IP 地址的访问

根据客户端的 IP 地址控制访问 使用 HTTP 或 stream 访问模块控制对受保护资源的访问&#xff1a; location /admin/ { deny 10.0.0.1; allow 10.0.0.0/20; allow 2001:0db8::/32; deny all; } } 给定的 location 代码块允许来自 10.0.0.0/20 中的任何 IPv4 地址访问&#xf…

UE4_Niagara基础实例—9、使用条带渲染器来制作闪电

效果图&#xff1a; 一、通过模板Static Beam来熟悉条带渲染器 从Static Beam发射器新建niagara系统&#xff0c;更名为NS_StaticBeam。 打开粒子系统&#xff0c;界面如下&#xff1a; Beam Emitter Setup模块可以设置条带的开始点、结束点和切线。 我们就可以通过这个Beam E…

自动化测试:等待方式

在自动化测试中&#xff0c;等待是一个重要的技术&#xff0c;用于处理页面加载、元素定位、元素状态改变等延迟问题。 等待能够确保在条件满足后再进行后续操作&#xff0c;提高自动化测试的稳定性以及可靠性。 等待方式&#xff1a;显示等待、隐式等待、线程睡眠 1. 显式等…

【python】OpenCV—WaterShed Algorithm(1)

文章目录 1、功能描述2、代码实现3、完整代码4、效果展示5、涉及到的库函数5.1、cv2.pyrMeanShiftFiltering5.2、cv2.morphologyEx5.3、cv2.distanceTransform5.4、cv2.normalize5.5、cv2.watershed 6、参考 1、功能描述 基于分水岭算法对图片进行分割 分水岭分割算法&#x…

什么是域名?什么是泛域名?

域名 定义 域名是互联网上用于识别和定位网站或网络服务的名称。它是由一串用点分隔的字符组成&#xff0c;例如 “baidu.com”。就像是现实生活中建筑物的地址&#xff0c;方便用户在互联网的海量信息中找到特定的网站。 结构 域名从右到左依次为顶级域名&#xff08;TLD&…

go语言中的Scan()和Scanln()输入函数

Scan()输入函数 package mainimport "fmt"func main() {var a intvar b stringfor {fmt.Println("请输入一个整数和一个字符串&#xff08;用空格分隔&#xff09;&#xff1a;")fmt.Scan(&a, &b) // 直接读取输入到变量中fmt.Println("整数…

图书管理系统的简单实现

文章目录 图书系统逻辑分析各种操作功能的实现完整代码 个人主页 JavaSE专栏 图书系统逻辑分析 该程序设置有三个包&#xff0c;user 包&#xff0c;book 包&#xff0c;operation包。 book包中包含对于书的一些信息和操作;operation包中包含有对 书 的所有操作功能;user包中包…

‘perl‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

‘perl’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。 明明已经根据教程安装了perl环境,但是在cmd中依赖报该错误,本章教程提供解决办法。 一、激活perl环境 state shell ActiveState-Perl-5.36.0此时输入perl -v 是可以直接输出perl版本号的。 二、找到perl的执…

想进体制内?到底有哪些路可走?原来有这么多方法

在如今的就业大环境下&#xff0c;体制内工作越来越受到大家的青睐。那么&#xff0c;体制内为何如此受欢迎呢&#xff1f; 一、体制内为何备受青睐 体制内工作首先给人一种强烈的稳定感和安全感。一旦进入体制&#xff0c;你不用时刻担心失业的风险&#xff0c;能够拥有一份长…

安康旅游网站:SpringBoot设计与实现详解

目 录 目 录 I 摘 要 III Abstract IV 第一章 绪论 1 1.1 研究现状 1 1.2 设计原则 1 1.3 研究内容 2 第二章 相关技术简介 1 2.1 JSP技术 1 2.2 Java技术 2 2.3 MYSQL数据库 2 2.4 B/S结构 3 2.5 Spring Boot框架 4 第三章 系统分析 5 3.1可行性分析 5 3.1.1技术可行性 5 3.1.…