ROS学习(5)——话题消息与服务

news/2024/10/18 0:21:30/

节点之间的消息通信分为几种形式:

  • 话题(topic):单向消息发送/接收方式
  • 服务(service):双向消息请求/响应方式
  • 动作(action):双向消息目标(goal)/结果(result)/反馈(feedback)方式
  • 参数服务器(参数共享模式)

种类区别
话题异步单向连续单向的发送/接收数据的情况
服务同步双向        `需要对请求给出即时相应的情况
动作异步双向   

请求与响应之间需要太长的时间,所以难以使用服务的情况,

或需要中途返回值的情况

节点通信的过程

一、运行主节点

节点之间的消息通信当中,管理连接信息的主节点是使用 ROS 必须首先运行的必需元
素。ROS 主节点使用 roscore 命令来运行,并使用 XMLRPC 运行服务器。

主节点为了节点与节点的连接,会注册节点的名称、话题、消息类型、 URI 地址和端口,
并在有请求时将此信息通知给其他节点。

 二、运行发布者节点

发布者节点使用 rosrun 或 roslaunch 命令来运行。发布者节点向主节点注册发布者节
点名称、话题名称、消息类型、URI 地址和端口。主节点和节点使用 XMLRPC 进行通
信。

  三、运行订阅者节点

订阅者节点使用 rosrun 或 roslaunch 命令来运行。订阅者节点在运行时向主节点注册其订阅者节点名称、话题名称、消息类型、 URI 地址和端口。主节点和节点使用 XMLRPC
进行通信。

四、通知发布者信息

主节点向订阅者节点发送此订阅者希望访问的发布者的名称、话题名称、消息类型、
URI 地址和端口等信息。主节点和节点使用 XMLRPC 进行通信。

 五、订阅者节点的连接请求

订阅者节点根据从主节点接收的发布者信息,向发布者节点请求直接连接。在这种情况下,要发送的信息包括订阅者节点名称、话题名称和消息类型。发布者节点和订阅
者节点使用 XMLRPC 进行通信。

六、发布者节点的连接响应

发布者节点将 TCP 服务器的 URI 地址和端口作为连接响应发送给订阅者节点。发布者
节点和订阅者节点使用 XMLRPC 进行通信。

 七、TCPROS 连接

订阅者节点使用 TCPROS 创建一个与发布者节点对应的客户端,并直接与发布者节点
连接。节点间通信使用一种称为 TCPROS 的 TCP/IP 方式。

  八、发送消息

发布者节点向订阅者节点发送消息。节点间通信使用一种称为 TCPROS 的 TCP/IP
方式。

下面是实现者(Publisher)发布话题和接收者(Subcriber)接收话题的例子

一、发布者

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>int main(int argc, char *argv[])
{// 1.设置编码setlocale(LC_ALL,"");//2.初始化 ROS 节点:命名(唯一)// 参数 1 和参数 2 后期为节点传值会使用// 参数 3 是节点名称,是一个标识符,需要保证运行后,在 ROS 网络拓扑中唯一ros::init(argc, argv, "publisher");//3.实例化 ROS 句柄ros::NodeHandle nh;  //该类封装了 ROS 中的一些常用功能//4.实例化 发布者 对象//泛型: 发布的消息类型//参数 1: 要发布到的话题//参数 2: 队列中最大保存的消息数,超出此阈值时,先进的先销毁(时间早的先销毁)ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10);//5.组织被发布的数据,并编写逻辑发布数据//数据(动态组织)std_msgs::String msg;std::string msg_front = "Hello,你好啊!";  // 消息前缀int count = 0;  //消息计数器//逻辑(一秒 10 次)ros::Rate r(1);//节点不死;while(ros::ok()){//使用 stringstream 拼接字符串与编号std::stringstream ss;ss<<msg_front<<count;msg.data = ss.str();//发布消息pub.publish(msg);//加入调试,打印发送的消息ROS_INFO("发送的消息:%s",msg.data.c_str());//根据前面制定的发送贫频率自动休眠 休眠时间 = 1/频率;r.sleep();count++;//循环结束前,让 count 自增ros::spinOnce();}return 0;
}

二、接收者

// 1.包含头文件
#include "ros/ros.h"
#include "std_msgs/String.h"void doMsg(const std_msgs::String::ConstPtr& msg_p){ROS_INFO("我订阅:%s",msg_p->data.c_str());// ROS_INFO("我听见:%s",(*msg_p).data.c_str());
}int main(int argc, char *argv[])
{setlocale(LC_ALL,"");//2.初始化 ROS 节点:命名(唯一)ros::init(argc,argv,"subscriber");//3.实例化 ROS 句柄ros::NodeHandle nh;//4.实例化 订阅者 对象ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg);//5.处理订阅的消息(回调函数)//6.设置循环调用回调函数ros::spin(); //循环读取接收的数据,并调用回调函数处理return 0;
}

三、CMakeLists文件编写(不会的小伙伴可以参考ROS学习(3)——CMakeLists文件的编写)

cmake_minimum_required(VERSION 3.0.2)
project(hello)## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTSroscpprospystd_msgs
)catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES hello
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
)## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(publish_man src/publish_man.cpp)
add_executable(subscrib_man src/subscrib_man.cpp)## Specify libraries to link a library or executable target against
target_link_libraries(publish_man${catkin_LIBRARIES}
)
target_link_libraries(subscrib_man${catkin_LIBRARIES}
)

四、编写launch文件(不会的小伙伴可以参考ROS学习(4)——launch文件的编写)

<launch><node pkg="hello" type="publish_man" name="pub" output="screen" /><node pkg = "hello" type = "subscrib_man" name = "sub" output = "screen" />
</launch>

 五、在终端运行launch文件:

source ./devel/setup.bash
roslaunch <功能包名> <launch文件名.launch>

得到运行结果如下:

 实现了发布消息和接收消息的过程。

需要注意的几点:

1.main函数自动补齐的格式是

int main(int argc, char const *argv[]){}

我们需要把里面的const给删掉。

2.第一条数据丢失

原因是发送第一条数据时,publisher还没有在roscore注册完毕。

解决方法是,注册后,加入休眠 ros::Duration(3.0).sleep(); 延迟第一条数据的发送。

3.出现错误ros/ros.h No such file or directory

检查CMakeLists里面是否有重复的部分,将其删除。


http://www.ppmy.cn/news/80330.html

相关文章

安装编译PostgreSql15.3.0

一、下载源码 方式一 官网手动下载 https://www.postgresql.org/download/. 解压 tar -zxvf postgresql-14.2.tar.gz方式二 git clone git clone https://github.com/postgres/postgres.git解压或下载后计入postgres目录 cd postgres-15.3二、创建目录 用root账户创建 创建…

Vue电商项目--平台售卖属性和的排序操作制作

平台售卖属性的操作 就是点击平台的售卖属性&#xff0c;下面显示对应的内容 这里我们要借助这个props属性 这里块是平台的售卖属性&#xff0c;我们在这里绑定回调&#xff0c;一点击就把id传给父组件 我们需要把这俩个参数传进入 商品属性的数组: ["属性ID:属性值:…

js中setinterval怎么用?怎么才能让setinterval停下来?

setinterval()是定时调用的函数&#xff0c;可按照指定的周期&#xff08;以毫秒计&#xff09;来调用函数或计算表达式。 setinterval()的作用是在播放动画的时&#xff0c;每隔一定时间就调用函数&#xff0c;方法或对象。 setInterval() 方法会不停地调用函数&#xff0c;…

多态的原理、单继承和多继承的虚函数表、以及虚函数表的打印。

一、多态原理 1、下面这个结果是多少&#xff1f; class A { public:virtual void func(){cout << "func()" << endl;}private:int _a 1; };int main() {printf("%d\n", sizeof(A));return 0; } 是 4&#xff1f;8&#xff1f;还是多少&am…

CSS3多列布局:达到无与伦比的网站排版

随着互联网技术的日益发展&#xff0c;网站排版也变得越来越重要。对于网站设计师而言&#xff0c;如何用 CSS3 实现美观、简洁、灵活的多列布局是一项必修的技能。在本篇文章中&#xff0c;我们将会一步步介绍 CSS3 多列布局的使用方法&#xff0c;带你完成一个完整的布局&…

npm i 常见问题

需要注意的是&#xff0c;如果你在使用 NPM 安装包的过程中遇到了任何问题&#xff0c;可以尝试使用 --verbose 参数打印更详细的错误信息&#xff0c;以便更好地诊断问题。例如&#xff1a; npm install --verbose 1、vue老项目缺少编译环境安装依赖报错的问题 待下载的项目…

Splunk安装配置

前言 Splunk 社区 &#xff0c;包括白皮书&#xff0c;各类手册&#xff0c;资源下载&#xff0c;社区问答等 入门&#xff1a;Splunk 入门指南 | Splunk 手册&#xff1a;Splunk Enterprise - Splunk Documentation 资源下载:数据可视化工具Splunk Enterprise免费下载 | S…

python绘制密度图

本期目录 1、绘图参数2、使用 matplotlib 库绘制密度图时常用的参数3、案例4、 运行结果python绘图往期系列文章目录 1、绘图参数 可以使用多种库来绘制密度图&#xff0c;其中最常用的是 seaborn 和 matplotlib。以下是使用 seaborn 库绘制密度图时常用的参数&#xff1a; i…