ros发布者节点以及订阅者节点的编写

本文围绕ROS展开,介绍了发布者与订阅者节点的编写方法。先创建发布者节点,初始化ROS系统并循环发布消息;接着创建订阅者节点,初始化系统、订阅主题并等待消息。最后说明了节点的构建过程,包括修改CMakeLists.txt文件、添加依赖项,最后运行catkin_make。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编写发布者节点:

“节点”是连接到ROS网络的可执行文件的ROS术语。在这里,我们将创建一个将继续广播消息的发布者(“talker”)节点。
将目录更改为您在catkin工作区之前的教程中创建的beginner_tutorials包:
首先使用指令更改一下roscd的绝对路径:

$ . ~/catkin_ws/devel/setup.bash

然后使用

$ roscd beginner_tutorials

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

$ mkdir -p src

该目录将包含beginner_tutorials包的任何源文件。
在beginner_tutorials包中创建src / talker.cpp文件并在其中粘贴以下内容:

#include "ros/ros.h"          		
/*ros/ros.h是一个方便的包括,包括使用ROS系统最常见的公共部分所需的所有标题。*/

#include "std_msgs/String.h"
#include <sstream>
/*这包括std_msgs / String消息,该消息驻留在std_msgs包中。
这是从该包中的String.msg文件自动生成的标头。*/

int main(int argc, char **argv)
{
 
  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节点的节点,我们将发布有关该主题的数据。
  	第二个参数是我们的发布队列的大小。在这种情况下,如果我们发布得太快,
  	它将在开始丢弃旧消息之前缓冲最多1000条消息。
  	NodeHandle::advertise()返回一个ros::Publisher对象,它有两个目的:
  	1)它包含一个publish()方法,它允许你将消息发布到它创建的主题上,以及
  	2)当它超出范围时,它会自动取消广告。*/
  
  ros::Rate loop_rate(10);
/*使用ros :: Rate对象可以指定要循环的频率。它将跟踪自上次调用
  Rate :: sleep()以来的持续时间,并在正确的时间内休眠。在这种情况下,
  我们告诉它我们想要以10Hz运行。*/
  
  int count = 0;
  
/*默认情况下,roscpp将安装一个SIGINT处理程序,该处理程序提供Ctrl-C处理,
如果发生这种情况,将导致ros :: ok()返回false。如果出现以下情况,
ros :: ok()将返回false:
收到SIGINT(Ctrl-C)
我们已被另一个具有相同名称的节点踢出网络
ros :: shutdown()已被应用程序的另一部分调用。
所有ros ::NodeHandles都被销毁了
一旦ros :: ok()返回false,所有ROS调用都将失败。
*/
  while (ros::ok())   
  {
/*我们使用消息适配类在ROS上广播消息,通常从msg文件生成。
更复杂的数据类型是可能的,但是现在我们将使用标准的String消息,
它有一个成员:“data”。*/
    std_msgs::String msg;
    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();

/*ROS_INFO和friend是printf/cout的替代品。*/
    ROS_INFO("%s", msg.data.c_str());

/*将消息广播给任何已连接的人。*/
    chatter_pub.publish(msg);

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

/*现在我们使用ros::Rate对象在剩余时间内休眠,让我们达到10Hz的发布速度。*/
    loop_rate.sleep();
    ++count;
  }    
  return 0;
}

这是正在发生的事情的浓缩版本:
初始化ROS系统
宣传我们将把聊天主题上的std_msgs / String消息发布给master
循环发布消息,每秒10次聊天
现在我们需要编写一个节点来接收这些消息。

编写订阅者节点

在beginner_tutorials包中创建src / listener.cpp文件并在其中粘贴以下内容:

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

/*这是一个回调函数,当一个新消息到达chatter主题时将被调用。消息在
boost shared_ptr中传递,这意味着您可以根据需要将其存储起来,而
不必担心它会被删除,并且不会复制基础数据。*/
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");

  ros::NodeHandle n;
/*与主人订阅chatter主题。每当有新消息到达时,ROS都会调用chatterCallback()
函数。第二个参数是队列大小,以防我们无法足够快地处理消息。在这种情况下,
如果队列达到1000条消息,我们将在新消息到达时开始丢弃旧消息。
NodeHandle :: subscribe()返回一个ros::Subscriber对象,您必须保留该对象,
直到您想取消订阅为止。订阅者对象被销毁后,它将自动取消订阅chatter主题。
NodeHandle::subscribe()函数有一些版本允许您指定类成员函数,甚至可以指定
Boost.Function对象可调用的任何函数。该roscpp概述包含更多的信息。*/
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

/*ros::spin()进入一个循环,尽可能快地调用消息回调。不过不用担心,如果没有什么
可以做的话就不会占用太多的CPU。只要ros::ok()返回false,ros::spin()将退出,
这意味着已经调用了ros::shutdown(),默认的Ctrl-C处理程序,master告诉我们关
闭,或者手动调用它。*/
  ros::spin();

  return 0;
}

再次,这是一个精简版的正在发生的事情:
初始化ROS系统
订阅聊天主题
旋转,等待消息到达
当消息到达时,将调用chatterCallback()函数

构建节点:

您在之前的教程中使用了catkin_create_pkg,它为您创建了一个package.xml和一个CMakeLists.txt文件。
生成的CMakeLists.txt应该如下所示(修改了创建Msgs和Srvs教程,删除了未使用的注释和示例):

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

add_message_files(DIRECTORY msg FILES Num.msg)
add_service_files(DIRECTORY srv FILES AddTwoInts.srv)

generate_messages(DEPENDENCIES std_msgs)

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_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

add_message_files(FILES Num.msg)
add_service_files(FILES AddTwoInts.srv)

generate_messages(DEPENDENCIES std_msgs)
catkin_package()

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/。
请注意,您必须将可执行目标的依赖项添加到(message generation targets)信息生成目标:(以下代码已经添加到CMakeLists.txt文件)

add_dependencies(talker beginner_tutorials_generate_messages_cpp)

这可以确保在使用之前生成此包的(message head)邮件头。如果您使用catkin工作区内其他包的消息,则还需要将依赖项添加到各自的生成目标,因为catkin并行构建所有项目。从* Groovy *开始,您可以使用以下变量来依赖所有必需的目标:
target_link_libraries(talker $ {catkin_LIBRARIES})
您可以直接调用可执行文件,也可以使用rosrun来调用它们。它们不会放在’ / bin’中,因为在将软件包安装到系统时会污染PATH。

之后就运行catkin_make啦!
进入catkin工作区:

$ cd ~/catkin_ws
$ catkin_make

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值