用C++写一个简单的订阅者

打开一个终端,进入到beginner_tutorials包下面:

cd ~/catkin_ws/src/beginner_tutorials

建立文件src/listener.cpp

vim src/listener.cpp

将下面的代码复制到文件中:

#include "ros/ros.h"
#include "std_msgs/String.h"

/**
 * This tutorial demonstrates simple receipt of messages over the ROS system.
 */
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv)
{
  /**
   * The ros::init() function needs to see argc and argv so that it can perform
   * any ROS arguments and name remapping that were provided at the command line. For programmatic
   * remappings you can use a different version of init() which takes remappings
   * directly, but for most command-line programs, passing argc and argv is the easiest
   * way to do it.  The third argument to init() is the name of the node.
   *
   * You must call one of the versions of ros::init() before using any other
   * part of the ROS system.
   */
  ros::init(argc, argv, "listener");

  /**
   * NodeHandle is the main access point to communications with the ROS system.
   * The first NodeHandle constructed will fully initialize this node, and the last
   * NodeHandle destructed will close down the node.
   */
  ros::NodeHandle n;

  /**
   * The subscribe() call is how you tell ROS that you want to receive messages
   * on a given topic.  This invokes a call to the ROS
   * master node, which keeps a registry of who is publishing and who
   * is subscribing.  Messages are passed to a callback function, here
   * called chatterCallback.  subscribe() returns a Subscriber object that you
   * must hold on to until you want to unsubscribe.  When all copies of the Subscriber
   * object go out of scope, this callback will automatically be unsubscribed from
   * this topic.
   *
   * The second parameter to the subscribe() function is the size of the message
   * queue.  If messages are arriving faster than they are being processed, this
   * is the number of messages that will be buffered up before beginning to throw
   * away the oldest ones.
   */
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

  /**
   * ros::spin() will enter a loop, pumping callbacks.  With this version, all
   * callbacks will be called from within this thread (the main one).  ros::spin()
   * will exit when Ctrl-C is pressed, or the node is shutdown by the master.
   */
  ros::spin();

  return 0;
}

保存退出。

下面看一下代码的解释:

void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

当一个消息到达chatter话题时,这个回调函数将会被调用。

ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

订阅chatter话题,当一个新的消息到达时,ROS将会调用chatterCallback()函数。第二个参数是对列的长度,会将收到的消息缓冲下来,一共可以缓冲1000条消息,满1000之后,后面的到达的消息将会覆盖前面的消息。

NodeHandle::subscribe()将会返回一个ros::Subscriber类型的对象,当订阅对象被销毁以后,它将会自动从chatter话题上撤销。

ros::spin();

ros::spin()进入了一个循环,非常快的调用消息的回调函数。不要担心,如果它没有什么事情可做时,它也不会浪费太多的CPU。

ros::ok()返回false时,ros::spin()将会退出。

这就意味着,当ros::shutdown()被调用,或按下CTRL+C等情况,都可以退出。

下面总结一下写一个订阅者的步骤:(1)初始化ROS系统(2)订阅chatter话题(3)Spin,等待消息的到来(4)当一个消息到达时,chatterCallback()函数被调用。




下面看一下如何构建节点。我们之前用过catkin_create_pkg创建过package.xml和CMakeLists.txt(目录:catkin_ws/src/beginner_tutorials/CMakeLists.txt),这时候你的CMakeLists.txt看起来应该是下面这个样子,包括前面所做的修改,注释部分可以除去:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
add_message_files(DIRECTORY msg FILES Num.msg)
add_service_files(DIRECTORY srv FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

将下面几行代码添加到CMakeLists.txt的最后。最终你的CMakeLists.txt文件看起来样该是下面这个样子:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
add_message_files(FILES Num.msg)
add_service_files(FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

## Build talker and listener
include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)

构建完之后,这将会创建两个可执行文件,talker和listener。它们将会产生在~/catkin_ws/devel/lib/share/<package name>目录下,这也就是说构建好的东西,会放在devel的目录中,原本的东西会留在src文件中。

下面开始构建,在你的工作空间根目录下输入:

catkin_make

这样我们就完成了,在某个话题上的消息的发布者和订阅者的可执行模块的创建。

时间: 2024-08-06 12:20:21

用C++写一个简单的订阅者的相关文章

写一个简单vue 中间件,$emit、$on

前言 使用过vue的同学大多数都知道$emit 与$on的使用.我们仅仅知道使用,有时候是完全不够的.现在我就带领大家写一个简单类似于vue空实例的中间件. 非父子组件的通信 非父子组件的通信vue官网给出这样的解决方案. 有时候,非父子关系的两个组件之间也需要通信.在简单的场景下,可以使用一个空的 Vue 实例作为事件总线: var bus = new Vue() // 触发组件 A 中的事件 bus.$emit('id-selected', 1) // 在组件 B 创建的钩子中监听事件 bu

linux设备驱动第三篇:写一个简单的字符设备驱动

在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存. 下面就开始学习如何写一个简单的字符设备驱动.首先我们来分解一下字符设备驱动都有那些结构或者方法组成,也就是说实现一个可以使用的字符设备驱动我们必须做些什么工作. 1.主设备号和次设备号 对于字符设备的访问是通过文件系统中的设备名称进行的.他们通常位于/dev目录下.如下: [plain] vie

(2)自己写一个简单的servle容器

自己写一个简单的servlet,能够跑一个简单的servlet,说明一下逻辑. 首先是写一个简单的servlet,这就关联到javax.servlet和javax.servlet.http这两个包的类,其中一个比较重要的接口就是:javax.servlet.Servlet,所有的servlet必须实现实现或者继承实现该接口的类. Servlet接口有五个方法: public void init(ServletConfig config) throws ServletException publi

分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业不是百度来的,我只是百度了一些示例代码的意思,怎么用!算了,越解释万一越黑呢!哈哈O(∩_∩)O哈哈~) ----------------------------------------------------------------分界线------------------------------

Java写一个简单学生管理系统

其实作为一名Java的程序猿,无论你是初学也好,大神也罢,学生管理系统一直都是一个非常好的例子,初学者主要是用数组.List等等来写出一个简易的学生管理系统,二.牛逼一点的大神则用数据库+swing来做一个有界面的学生管理系统.其实都并不会太难. 今天我就先写一个简单的用List来实现学生管理系统: 首先,管理系统是针对学生对象的,所以我们先把学生对象就写出来: package bean; public class Student { String name; String studentId;

DuiVision开发教程(2)-如何写一个简单的界面程序

基于DuiVision界面库开发的界面程序主要包括如下几部分内容: 1.资源定义,包括图片资源.各个窗口界面的xml定义文件 2.事件处理类代码,用于处理界面响应消息 3.其他业务逻辑代码 下面举例说明如何写一个简单的界面程序. 第一步:使用VC向导创建一个有两个tab页面的DuiVision工程 向导生成的解决方案文件如下: 默认有两个工程,分别是DuiVision库和应用程序工程.自动生成的代码目录中bin目录下的内容那个如下,bkimg目录存放窗口背景图片,skins目录存放图片资源,xm

linux设备驱动第三篇:如何写一个简单的字符设备驱动?

在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存. 下面就开始学习如何写一个简单的字符设备驱动.首先我们来分解一下字符设备驱动都有那些结构或者方法组成,也就是说实现一个可以使用的字符设备驱动我们必须做些什么工作. 1.主设备号和次设备号 对于字符设备的访问是通过文件系统中的设备名称进行的.他们通常位于/dev目录下.如下: [email prot

利用servlet和html写一个简单的登录

写一个简单的html登录页面,然后利用servlet来进行验证账号密码. html代码: <!DOCTYPE html> <html> <title>登陆页面</title> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <form action = &

如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1

原文:http://www.raywenderlich.com/2941/how-to-write-a-simple-phpmysql-web-service-for-an-ios-app 作为一个iPhone/iPad开发者,能够自己写一个简单的web服务器将是很有用的. 例如,你可能希望在软件启动时显示一些来自服务器的更新,或者在服务器端保存一些用户数据.除了你的想象力,没有什么能限制你了. 在第一篇中,我们将会一步一步的建立一个web服务器,基于promo code system(促销码系