本教程介绍如何使用C ++编写发布者和订阅者节点

1、编写 Publisher Node

“节点”是连接到ROS网络的可执行文件的ROS术语。现在将创建一个发布者(publisher “talker”)节点,该节点将不断广播消息。将目录更改为在之前的教程中创建catkin工作区中的beginner_tutorials包:

roscd beginner_tutorials

1.1 代码

在beginner_tutorials包目录中创建一个src目录:

mkdir -p src

该目录将包含beginner_tutorials包的所有源文件。

在beginner_tutorials包中创建src / talker.cpp文件,内容如下:

#include "ros/ros.h"
#include "std_msgs/String.h"#include <sstream>/*** This tutorial demonstrates simple sending of messages over the ROS system.*/
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, "talker");/*** 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 advertise() function is how you tell ROS that you want to* publish on a given topic name. This invokes a call to the ROS* master node, which keeps a registry of who is publishing and who* is subscribing. After this advertise() call is made, the master* node will notify anyone who is trying to subscribe to this topic name,* and they will in turn negotiate a peer-to-peer connection with this* node.  advertise() returns a Publisher object which allows you to* publish messages on that topic through a call to publish().  Once* all copies of the returned Publisher object are destroyed, the topic* will be automatically unadvertised.** The second parameter to advertise() is the size of the message queue* used for publishing messages.  If messages are published more quickly* than we can send them, the number here specifies how many messages to* buffer up before throwing some away.*/ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);ros::Rate loop_rate(10);/*** A count of how many messages we have sent. This is used to create* a unique string for each message.*/int count = 0;while (ros::ok()){/*** This is a message object. You stuff it with data, and then publish it.*/std_msgs::String msg;std::stringstream ss;ss << "hello world " << count;msg.data = ss.str();ROS_INFO("%s", msg.data.c_str());/*** The publish() function is how you send messages. The parameter* is the message object. The type of this object must agree with the type* given as a template parameter to the advertise<>() call, as was done* in the constructor above.*/chatter_pub.publish(msg);ros::spinOnce();loop_rate.sleep();++count;}return 0;
}

1.2 代码解释

#include "ros/ros.h"#ros/ros.h是一个快捷的包括,包括使用ROS系统最常见的公共部分所需的所有头文件。
#include "std_msgs/String.h"#这包括std_msgs / String消息,该消息驻留在std_msgs包中。这是从该包中的String.msg文件自动生成的标头
 ros::init(argc, argv, "talker");

初始化ROS。允许ROS通过命令行进行名称重映射 - 现在不重要。这也是指定节点名称的地方。节点名称在运行的系统中必须是唯一的。这里使用的名称必须是基本名称,即不能包含路径。

  ros::NodeHandle n;

为此进程的节点创建句柄。首先创建的NodeHandle实际上将执行节点的初始化,其次退出时将清除节点使用的任何资源。

 ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

告诉主机将在主题 chatter 中发布类型为std_msgs / String的消息。主机告诉任何监听 chatter节点的节点,chatter节点将发布该主题的数据。第二个参数是发布队列的大小,在这种情况下,如果发布得太快,缓冲最多1000条消息,之后将开始丢弃旧消息。

NodeHandle :: advertise()返回一个ros :: Publisher对象,它有两个目:

1)它包含一个publish()方法,允许你将消息发布到它创建的主题上;

2)当它超出范围时,它会自动退出。

  ros::Rate loop_rate(10);

使用ros :: Rate对象指定要循环的频率。跟踪自上次调用Rate :: sleep()以来的持续时间。在这种情况下,告诉系统以10Hz运行。

  int count = 0;while (ros::ok()){

默认情况下roscpp将安装一个SIGINT处理程序,该处理程序提供Ctrl-C处理,将导致ros :: ok()返回false。

出现以下情况,ros :: ok()将返回false:

a SIGINT is received (Ctrl-C)

we have been kicked off the network by another node with the same name

ros::shutdown() has been called by another part of the application.

all ros::NodeHandles have been destroyed

一旦ros :: ok()返回false,所有ROS调用都将失败。

    std_msgs::String msg;std::stringstream ss;ss << "hello world " << count;msg.data = ss.str();

使用消息适配类在ROS上广播消息,通常消息从msg文件生成。更复杂的数据类型是可能的,但是现在我们将使用标准的String消息,它有一个成员:“data”。

   chatter_pub.publish(msg);

现在将消息广播给任何已连接的节点。

ROS_INFO("%s", msg.data.c_str());

ROS_INFO及其相关是printf / cout的替代品。相关文档查看 rosconsole documentation 。

   ros::spinOnce();

这个简单程序可以不需要调用ros :: spinOnce(),因为没有收到任何回调。但是,如果要在此应用程序中添加订阅,且此处没有ros :: spinOnce(),则永远不会调用您的回调。所以,它是作为一个衡量存在。

    loop_rate.sleep();

使用ros :: Rate对象达到10Hz的发布速度。

以上归结如下:

1、 初始化ROS系统;

2、将把chatter主题上的std_msgs / String消息发布给master

3、循环发布消息,每秒10次

2、 编写 the Subscriber Node

2.1 代码

在beginner_tutorials包中创建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;
}

2.2 代码解释

现在一点一点地分解它,忽略一些已经在上面解释过的部分。

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

这是一个回调函数,当一个新的消息到达chatter主题时将被调用。消息在boost shared_ptr中传递,这意味着您可以根据需要将其存储起来,而不必担心它会被删除,并且不会复制基础数据。

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

订阅聊天主题。每当有新消息到达时,ROS都会调用chatterCallback()函数。第二个参数是队列大小,以防我们无法足够快地处理消息。在这种情况下,如果队列达到1000条消息,将在新消息到达时开始丢弃旧消息。

NodeHandle :: subscribe()返回一个ros :: Subscriber对象,必须保留该对象,直到取消订阅。订阅对象被销毁后,将自动取消订阅chatter主题。

有一些版本的NodeHandle :: subscribe()函数允许您指定类成员函数,甚至可以指定Boost.Function对象可调用的任何函数。相关信息请查阅 roscpp overview。

ros::spin();

ros :: spin()进入一个循环,尽可能快地调用消息回调函数。如果没有什么可以做的话就不会占用太多的CPU。ros :: spin()将退出一次ros :: ok()返回false,这意味着已经调用了ros :: shutdown(),默认的Ctrl-C处理程序。

还有其他方法可以回调,但我们不会担心这些问题。roscpp_tutorials中有一些演示应用程序来演示这一点。更多roscpp信息请查阅 roscpp overview。

编写Subscribe总结如下:

1、初始化ROS系统;

2、订阅chatter主题;

3、spin,等待消息到达;

4、当消息到达时,将调用chatterCallback()函数

3、编译nodes

使用catkin_create_pkg创建了一个package.xml和一个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的底部:

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)

生成的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,默认情况下将进入devel空间的package目录,默认位于〜/ catkin_ws / devel / lib / <package name>。

注意,必须将可执行目标的依赖项添加到生成目标:

add_dependencies(talker beginner_tutorials_generate_messages_cpp)

这样可以确保在使用之前生成此包的​​头文件。如果使用catkin工作区内其他包的消息,则需要将依赖项添加到其各自的生成目标,因为catkin并行构建所有项目。从* Groovy *开始,可以使用以下变量来依赖所有必需的目标:

target_link_libraries(talker ${catkin_LIBRARIES})

可以直接调用可执行文件,也可以使用rosrun来调用它们。它们不会放在'<prefix> / bin'中,因为在将软件包安装到系统时会(污染)PATH。如果希望在安装时将可执行文件放在PATH上,则可以设置安装目标,查阅: catkin/CMakeLists.txt。

现在运行catkin_make:

# In your catkin workspace
$ cd ~/catkin_ws
$ catkin_make  

注意:或者如果您要添加新的pkg,您可能需要通过--force-cmake选项告诉catkin强制制作。请参阅catkin/Tutorials/using_a_workspace#With_catkin_make.

已经写了一个简单的发布者和订阅者,让我们来查看ROS教程五-运行简单的发布者和订阅者。

ROS教程四——编写Publisher和Subscriber节点(C++篇)相关推荐

  1. ROS教程四——编写Publisher和Subscriber节点(Python篇)

    本教程介绍如何在python中编写发布者和订阅者节点 1.编写Publisher节点 "节点"是连接到ROS网络的可执行文件的ROS术语.在这里,我们将创建广播消息的 publis ...

  2. ROS教程五——运行 Publisher和Subscriber

    本教程检查运行简单的发布者和订阅者. 1.运行Publisher 确保roscore已启动并运行: $ roscore catkin特别规定如果使用的是catkin,请确保在调用catkin_make ...

  3. 小白学习ROS(3)创建Publisher和Subscriber节点

    创建Publisher和Subscriber节点进行通讯 1.前言 在创建Publisher和Subscriber节点之前,先给介绍一个创建ROS包以及程序编写非常方便的一个ide,真的特别方便,尤其 ...

  4. ROS基础四之roscpp/rospy节点编写

    roscpp/rospy节点编写 subscriber/advertiser编写 roscpp实例 rospy实例 server/client编写 roscpp实例 rospy实例 actionlib ...

  5. ROS教程中Publisher和Subscriber (Python)的说明

    Publisher和Subscriber[Python]的说明 1.编写发布节点 2.编写订阅节点 3.编译现在的节点 1.编写发布节点 $ roscd beginner_tutorials #切换到 ...

  6. 【从零开始的ROS四轴机械臂控制】(四)- ros、gazebo与opencv,图像处理节点

    [从零开始的ROS四轴机械臂控制(四)] 七.图像处理节点 1.节点功能与实现方法 2.iamge_process 相关程序 部分程序解释 3.节点运行与测试 七.图像处理节点 1.节点功能与实现方法 ...

  7. 【ROS入门学习05|自定义话题消息,并且编程实现publisher和subscriber】

    这里是学习ROS第一次涉及到代码的部分.主要根据古月居视频教程整理出来的干货.本人是干货爱好者. 文章目录 前言 一.话题模型 二.自定义话题消息 1.定义msg文件 2.在功能包(learning_ ...

  8. ROS学习----Publisher与Subscriber

    1.Publisher(发布者)与subscriber(订阅者)关系. Publisher的主要作用是对于指定话题发布特定数据类型的消息. 下面是利用代码实现一个节点,节点创建一个Publisher并 ...

  9. ROS教程——1.6 如何使用TF变换

    转载自:ROS教程--1.6 如何使用TF变换 ROS教程--1.6 如何使用TF变换 原创 huicanlin Robot404 2019-07-03 15:10 1.6.1 ROS的变换系统(TF ...

最新文章

  1. linux蓝牙设备无法打开,linux 下 无线 wifi 蓝牙 无法启用
  2. Kubernetes存储之ConfigMap
  3. SDNU 1167.花生采摘(排序)
  4. 计算机三种引用方式,单元格的引用方式有哪几种
  5. 【37.68%】【hdu 5918】Sequence I
  6. VSCode REMOTE SSH
  7. HDU-2553N皇后问题(dfs)
  8. 在win10在使用cmder代替Linux是怎样的体验
  9. The _imagingft C module is not installed
  10. Good Bye 2016 //智商再次下线,边界爆炸.....
  11. 165体重_身高165的女性体重多少比较合适?过胖和过瘦都不太好
  12. 中国移动苏州研发中心前端笔试(2)
  13. mysql图文混排设计方案_平面设计图文混排技巧,看完再也不用担心排版了
  14. STM32涉及到的汇编基础知识
  15. MongoDB实验练习题
  16. java tld_Java Web自定义标签tld文件的简单使用
  17. HTML标签-排版标签、媒体标签、列表标签、表格标签、表单标签、语义化标签、字符实体
  18. VC6 限定鼠标移动范围
  19. vue大屏展示高度自适应
  20. 第四套人民币荧光冠号大全

热门文章

  1. Best_Cow_Line
  2. 关于VS2012使用make_pair编译提示“error C2664: “std::make_pair”: 不能将参数 1 从“int”转换为“int ””
  3. [单源最短路]逃离僵尸岛
  4. acadres.dll文件丢失怎么办?怎么去修复?
  5. 晚上看了轮子哥的知乎想法,我失眠了
  6. 获取大量合伙人并疯狂裂变的秘密,思路引导出路,布局聚焦格局!
  7. 快速克隆已有的WindowsToGo到另一个盘
  8. 卡尔福安卓智能导航,好用又方便
  9. 怎么快速将服务器上的文件取回本地,迅雷离线文件取回本地的图文步骤
  10. 用计算机画画的意义,尺子对于绘画的意义是什么,为什么绘画领域很少用尺子?...