ROS学习笔记(五)——编写ROS消息发布器于订阅器(C++)

ROS学习笔记系列是对 ROS中文教程 的记录总结。
笔记五包括:

  • 5.1 实现目标
  • 5.2 编写ROS发布器与订阅器
  • 5.3 编译与运行

5.1 实现目标

学了ROS 一段时间里,我们get 了什么呢?首先是安装软件环境配置,然后会创建catkin空间,添加与编译程序包。学习了ROS 节点与话题,实际控制小海龟运动。还学了服务与参数,会一些保存文件这些操作。

然而,我们学习ROS 的初心是什么呢?肯定不止于此。我们要在工程中使用ROS,我们要有自己的东西。比如本人学习ROS,是因为想要使用树莓派外部控制pixhawk 无人机。一种方案就是使用树莓派使用 MAVROS 来与无人机交互,而ROS 就是基础之一。

先不谈那么远,我们抽象出“初心” 与 “现在” 的共同点——编写自己的程序。现在,我们就开始编写两个节点,一个不停发送 “hello world 1”, “hello world 2”…,一个不停监听,并且打印听到的内容。


5.2 编写ROS发布器与订阅器

5.2.1 ROS发布器

假设您已经学过前面的四节内容,创建的 catkin 空间还在,beginner_tutorials 程序包还在,有目录~/catkin_ws/src/beginner_tutorials/。都不在的话先补好再往下看~

进入程序包,创建新的目录与文件并打开

$ cd ~/catkin_ws/src/beginner_tutorials/
$ mkdir -p ~/catkin_ws/src/beginner_tutorials/src
$ touch src/talker.cpp
$ gedit src/talker.cpp

打开文件,复制粘贴以下内容

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

int main(int argc, char **argv)
{
  ros::init(argc, argv, "talker");    //ros::init() 函数需要 argc 和 argv 参数才能运行,第三个参数是节点的名称
  ros::NodeHandle n;                  //节点句柄(NodeHandle)是和ROS 系统通信的关键点
  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);      
  //第一个参数就是话题的名字,第二个参数是消息队列的长度,用于缓冲
  ros::Rate loop_rate(10);            //消息发布速率10Hz

  int count = 0;  			
  while (ros::ok())
  {
    std_msgs::String msg;  		         //创建一个消息对象,用来存放要发布的消息
    std::stringstream ss;
    ss << "hello world " << count;   	
    msg.data = ss.str();

    ROS_INFO("%s", msg.data.c_str());	//打印发布了的消息

    chatter_pub.publish(msg);       	//发布消息,一个Publiser 对象调用 publish() 方法,参数是要发布的消息

    ros::spinOnce();                    //不接受回调的意思,此处其实可无
    loop_rate.sleep();                  //保证是10Hz循环,而不是一直跑着
    ++count;
  }
  return 0;
}

代码的更详细的解释可以看官方教程 ,然后保存退出即可。

5.2.2 编写 ROS订阅器

和 talker.cpp 在同一目录下,编写 listener.cpp。首先还是新建并打开文件。

$ touch src/listener.cpp
$ gedit src/listener.cpp

然后复制粘贴以下内容:

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

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");      //节点名称 listener
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
  // 第一个参数是订阅的话题名称,第二个参数是消息队列长度,第三个是回调函数
  ros::spin();

  return 0;
}

这个程序也很简单,仔细读读就明白。


5.3 编译与运行

5.3.1 编译

C++编译的最重要文件就是 CMakelist.txt 了,接下来我们修改它。
在当前目录 ~/catkin_ws/src/beginner_tutorials/下运行

$ ls
    # 可得CMakeLists.txt  include  package.xml  src
gedit CMakeLists.txt

修改文件使其如下(删除注释):

project(beginner_tutorials)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)
catkin_package()

#---------- 以下部分为修改和添加的内容 -----------#
include_directories(include ${catkin_INCLUDE_DIRS})               #包含 catkin空间

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)#添加依赖

然后回到catkin 空间下,执行编译

$ cd ~/catkin_ws
$ catkin_make

正常结果后半部分如下:
ROS正常编译5.3.2 运行测试

见证奇迹的时刻到了!
在三个终端分别运行

$ roscore    #启动ROS服务器
$ cd ~/catkin_ws
$ source ./devel/setup.bash
$ rosrun beginner_tutorials talker
$ cd ~/catkin_ws
$ source ./devel/setup.bash
$ rosrun beginner_tutorials listener

一切正常的话,可以得到如下结果:
ROS节点运行woow!恭喜完成第一个自己的节点,准备实现最初的目标吧~
------------------ 路曼曼其修远兮,吾将上下而求索---------------------


5.4 后期补充

后面自己再次运行程序,作此补充。我们编写的两个程序—— talker.cpp 和 listener.cpp 是怎样通信的?

首先,编译之后是产生可执行文件 talkerlistener,它们是相互独立的。

然后,运行了roscore 指令,开启服务器。值得注意的是,这个服务器并不是联网的服务器(因为不连接网络以上依然能正常运行),而是自己电脑里面一段处理程序。

最后,两个可执行文件之间一个发布消息到话题,另一个从话题订阅消息。这个话题可以使用rostopic list指令查看,叫做 chatter ,其实就是在上面的 .cpp 文件里我们自己定义的。

总结,ROS 的这个机制实现的是进程通信。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大强强小强强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值