ROS编写第一个订阅器

在上一篇文章中,我们实现了第一个ROS程序—发布器(publisher),然而在上一篇文章的最后我们也注意到,尽管我们的程序非常小,但占据的CPU资源却非常多。

这是因为在发布器的while循环里没有执行必要的sleep操作,使得发布器一直以最高速率运行,长时间占用CPU。

本篇文章分为以下两部分:

  1. 在发布器中加入sleep调用使发布器的频率稳定在1Hz
  2. 实现一个订阅器(Subscriber)

1. 发布器加入sleep

事实上,我们所需要做的只有两行工作,首先创建一个ros::Rate对象,然后在while循环里调用该对象的.sleep()函数即可。

修改后完整的代码如下:

#include <ros/ros.h>
#include <std_msgs/Float64.h>

int main(int argc, char **argv) {
    ros::init(argc, argv, "minimal_publisher"); // 初始化节点名
    ros::NodeHandle n; //

    // ++++
    ros::Rate s_timer(1.0); // 参数1.0代表发布频率即1.0Hz
    // ++++

    ros::Publisher my_publisher_object = n.advertise<std_msgs::Float64>("topic1", 1); // 创建一个发布器,调用advertise通知ROS Master话题名称以及话题类型
    //"topic1" 是话题名
    // 参数 "1" 是queue_size,表示缓冲区大小

    std_msgs::Float64 input_float; // 创建一个发布器将要使用的消息变量
    // 该消息定义在: /opt/ros/indigo/share/std_msgs
    // 在ROS中发布的消息都应该提前定义,以便订阅者接收到消息后该如何解读
    // Float64消息的定义如下,其中包含一个数据字段data:
    // float64 data

    input_float.data = 0.0; // 设置数据字段

    // 程序所要做的工作将在下面的循环里完成
    while (ros::ok())
    {
        // 该循环没有sleep,因此将一直处于运行状态,不断消耗CPU资源
        input_float.data = input_float.data + 0.001; //每循环一次+0.01
        my_publisher_object.publish(input_float); // 发布消息到对应的话题
        // ++++
        s_timer.sleep(); // 在这里调用sleep函数可以让程序在这里
        // 停止一段时间以便达到要求的发布频率
        // ++++
    }
}

将修改后的发布器重新进行编译,然后按照和上篇文章一样依次运行:

roscore

再打开一个终端,运行

rosrun my_minimal_node my_minimal_publisher # 启动发布器

检查发布频率,运行

rostopic hz /topic1

可以看到此时发布器的发布频率已经基本稳定在1Hz了。然后检查系统监视器的状态:

也同样可以看到此时CPU的占用率已经降下来了。

2. 实现一个订阅器

首先将我们提前修改好的订阅器代码复制到src目录下,代码如下:

#include<ros/ros.h>
#include<std_msgs/Float64.h>
void myCallback(const std_msgs::Float64& message_holder)
{
  // 打印出我们接收到的值
  ROS_INFO("received value is: %f",message_holder.data);
} 

int main(int argc, char **argv)
{
  ros::init(argc,argv,"minimal_subscriber"); //初始化节点
  // 节点名定义为 minimal_subscriber
  ros::NodeHandle n; // 节点句柄,用来创建订阅器
  // 订阅话题'topic1'
  // subscribe中的mycallback是回调函数,每当有新数据到来时,该函数
  // 便会被调用
  // 实际的工作是在回调函数中完成的

  ros::Subscriber my_subscriber_object=
      n.subscribe("topic1",1,myCallback); 

  ros::spin(); // 类似于 `while(1)`语句,但是当有新消息到来时,会调用回调函数

  return 0;
} 

然后和上篇文章一样,为了编译我们刚写的订阅器,我们还需要修改CMakeLists.txt文件,以便让编译器知道应该编译我们新增的文件。类比上篇文章的发布器,我们在CMakeLists.txt文件中加入如下两行:

add_executable(my_minimal_subscriber src/minimal_subscriber .cpp) # 第一个参数是生成后的可执行文件名 第二个参数
# 是源文件路径名
target_link_libraries(my_minimal_subscriber  ${catkin_LIBRARIES}) # 链接库

打开终端,导航到工作区目录下~/catkin_ws,然后执行命令

catkin_make

等待编译完成后,依次执行命令(这些命令都是在不同的终端下输入)

roscore
rosrun my_minimal_node my_minimal_publisher
rosrun my_minimal_node my_minimal_subscriber

然后在订阅器的终端下就可以看出输出

运行命令rosnode list检查节点

最后,可以运行命令

rqt_graph

来显示一个图形化的节点-话题连接图:

由上面的直观展示可以看出,消息由发布器流出到话题topic1然后再流向订阅器。

视频

ROS编写第一个订阅器程序

以上所有过程我录制了一个视频,在浏览文章过程中如果遇到问题,您可以查看视频来看看我是怎么做的。

原文地址:https://www.cnblogs.com/cporoske/p/11621423.html

时间: 2024-12-26 21:27:33

ROS编写第一个订阅器的相关文章

ROS学习(十二)—— 编写简单的消息发布器和订阅器(C++)

一.创建发布器节点 1 节点功能: 不断的在ROS网络中广播消息 2 创建节点 (1)打开工作空间目录 cd ~/catkin_ws/src/beginner_tutorials p { margin-bottom: 0.25cm; line-height: 120% } a:link { } 创建一个发布器节点("talker"),它将不断的在ROS网络中广播消息. --> { } (2)创建src文件夹 mkdir -p ~/catkin_ws/src/beginner_tu

ROS 自定义消息发布器和订阅器测试 +代码详解(入门级)

既对ros tutorial 上的例子有了一定的了解之后,今天对发布器和订阅器代码(http://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29)进行了研究,同时稍作改动进行了验证, 发布器-------------------------------------------------------------------------------------------------------------

SLAM+语音机器人DIY系列:(二)ROS入门——4.如何编写ROS的第一个程序hello_world

摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人"miiboo"中的大部分程序也采用ROS进行开发,所以本文就重点对ROS基础知识进行详细的讲解,给不熟悉ROS的朋友起到一个抛砖引玉的作用.本章节主要内容: 1.ROS是什么 2.ROS系统整体架构 3.在ubuntu16.04中安装ROS kinetic 4.如何编写ROS的第一个程序hello_world 5.编写简单的消息发布器和订阅器 6.编写简单的s

6.Ray-消息订阅器编写

消息订阅器: Ray是基于Event Sourcing设计的ES/Actor框架,消息发布后需要订阅处理,订阅器主要有以下两类: CoreHandler消息订阅器=RabbitSub+SubHandler ToReadHandler消息订阅器=RabbitSub+SQLToReadHandler(ToReadHandler的子类) RabbitSub特性 RabbitSub特性是RabbitMQ消息队列订阅器. RabbitSub特性有两个构造函数,常用的是这个: public RabbitSu

django之创建第3个项目:编写第一个模板文件

1.django结构 2.在站点blog下创建templates文件夹,专门用于存放模板文件 3.在templates文件夹下创建index.html文件 #index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>第一个模板文件</title> </head> <body&

如何编写一个JSON解析器

编写一个JSON解析器实际上就是一个函数,它的输入是一个表示JSON的字符串,输出是结构化的对应到语言本身的数据结构. 和XML相比,JSON本身结构非常简单,并且仅有几种数据类型,以Java为例,对应的数据结构是: "string":Java的String: number:Java的Long或Double: true/false:Java的Boolean: null:Java的null: [array]:Java的List<Object>或Object[]: {"

渲染入门,使用C++编写基本的渲染器

序 一直以来,电影特效和那些炫目.逼真的三维场景令我惊奇且赞叹不已.在具体接触计算机科学以及C++编程语言之前,我并不知道3DMax或者Maya这类软件的背后究竟发生着什么--在一个可交互的窗口中编辑三维场景,然后进入一个叫做"渲染"的神奇过程,神秘而复杂精妙的事情再不为人知的计算机中发生着,然后就能产生处足以以假乱真的图像.尽管在计算机技术相当发达的今天,通过计算机和软件生成图像并不让人感到惊讶,但是作为一个软件工程的学生,这其中的奥秘依然让我深深着迷. 图1    使用本博客所实现

面试题思考:如何编写自己的类加载器

类加载器就是负责检索并加载其他Java类或者资源(如文件)的对象,它一般继承于java.lang.ClassLoader这个抽象类(除了BootstrapClassLoader). 实际上,程序中所有的类都是通过类加载器进行加载的,并且它们都持有各自类加载器对象的引用,可以通过java.lang.Class的getClassLoader方法得到. 一个程序中的各个类加载器构成了一棵树,位于根部的被称作BootstrapClassLoader,它作为Java虚拟机的一部分,它使用C++语言实现,在

HTML5&CSS3初学者指南(1) – 编写第一行代码

介绍 网络时代已经到来.现在对人们来说,每天上网冲浪已经成为一种最为常见的行为. 在网页浏览器中输入一段文本地址,就像http://www.codeproject.com,等待一下,网页就加载到浏览器窗口中.一个典型的网页是由文本.图像和链接组成的.除去内容上的差异,不同网站的网页也具有不同的外观和感受,以实现在网络上建立自己的身份品牌的目的. 如果你也曾想要了解你屏幕上的这些网页是如何被创建出并以各式各样的方式渲染的,那么这里正是你可以了解到这些知识的地方.让我们一起走进在浏览器中创建了这么多