ros学习笔记_服务通讯
学习地址
0、话题通讯理论模型
前言:
话题通信基本操作(C++)
注:启动roscore的时候rosmaster已经启动了,因此ROS master 不需要实现,而连接的建立也已经被封装了(因此连接也不需要被关注了),话题是在发布方和订阅方内部实现的时候设置的,因此需要关注的关键点有三个:
发布方
接收方
数据(此处为普通文本)
案例一
1、发布方实现(p42 p43)
1.1 建立工作空间
步骤参照之前的笔记贴
1.2创建功能包
右击工作空间下的src,选择Create Catkin Package。
输入功能包名字 plumbing_pub_sub 按enter
导入ros功能包 roscpp rospy std_msgs 按enter
1.3发布者代码编写
功能包创建完毕,开始进行发布者实现
在功能包下的src目录下建立一个c++源文件:右击src,新建文件,名为demo01_pub.cpp
代码如下,这次为发布方实现的代码
/*需求: 实现基本的话题通信,一方发布数据,一方接收数据,实现的关键点:1.发送方2.接收方3.数据(此处为普通文本)PS: 二者需要设置相同的话题消息发布方:循环发布信息:HelloWorld 后缀数字编号实现流程:1.包含头文件 2.初始化 ROS 节点:命名(唯一)3.实例化 ROS 句柄4.实例化 发布者 对象5.组织被发布的数据,并编写逻辑发布数据*/
// 1.包含头文件
#include "ros/ros.h"
#include "std_msgs/String.h" //普通文本类型的消息
#include <sstream>int main(int argc, char *argv[])
{ //设置编码 防止中文的日志输出乱码setlocale(LC_ALL,"");//2.初始化 ROS 节点:命名(唯一)// 参数1和参数2 后期为节点传值会使用// 参数3 是节点名称,是一个标识符,需要保证运行后,在 ROS 网络拓扑中唯一ros::init(argc,argv,"talker");//3.实例化 ROS 句柄ros::NodeHandle nh;//该类封装了 ROS 中的一些常用功能//4.实例化 发布者 对象//泛型: 发布的消息类型//参数1: 要发布到的话题//参数2: 队列中最大保存的消息数,超出此阀值时,先进的先销毁(时间早的先销毁)ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10);//5.组织被发布的数据,并编写逻辑发布数据//数据(动态组织)std_msgs::String msg;// msg.data = "你好啊!!!";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(); //类始于单片机的delaycount++;//循环结束前,让 count 自增//暂无应用ros::spinOnce(); //这里的发布方没有回调函数,所以这个函数不起作用}return 0;
}
1.4配置CMakeLists.txt文件
CMakeLists.txt在与demo01_pub.cpp同级目录,一般在137行与150行
137行映射格式:add_executable(自定义映射名称 src/cpp的文件名称),配置后如下
add_executable(xixixi src/demo01_pub.cpp)
150行:将${PROJECT_NAME}换为自定的映射名称 即为xixixi
1.5命令行操作
在编写并且配置完发布方实现后,通过终端对所以发布方代码进行查看
第一步:启动roscore
命令行:roscore
第二步:启动功能包
命令行:cd demo04_ws/ 切换到工作空间
source ./devel/setup.bash
rosrun plumbing_pub_sub xixixi (plumbing_pub_sub是功能包名 xixixi是自定义的映射名)
到这里就开始输出日志了
另外可以通过第三步
rostopic echo fang(fang是设置的主题)
2、订阅方实现(p44)
在上有的基础上创建demo01_sub.cpp,下面为订阅者实现的代码
/*需求: 实现基本的话题通信,一方发布数据,一方接收数据,实现的关键点:1.发送方2.接收方3.数据(此处为普通文本)消息订阅方:订阅话题并打印接收到的消息实现流程:1.包含头文件 2.初始化 ROS 节点:命名(唯一) **也就是订阅放的ROS节点的命名不能与发布方相同**3.实例化 ROS 句柄4.实例化 订阅者 对象5.处理订阅的消息(回调函数)6.设置循环调用回调函数*/
// 1.包含头文件
#include "ros/ros.h"
#include "std_msgs/String.h"
/*这里是回调函数,函数参数是 订阅的发布消息的常量指针的引用,获取msg_p中的data*/
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,"listener");//3.实例化 ROS 句柄ros::NodeHandle nh;//4.实例化 订阅者 对象ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg);//std_msgs::String代表std_msgs库中的string类型//5.处理订阅的消息(回调函数)// 6.设置循环调用回调函数ros::spin();//循环读取接收的数据,并调用回调函数处理,否则main函数只执行一次return 0;
}
代码写完后ctrl+shift+B编译一下看看有没有问题
同样同发布方一样配置的配置方法。
配置终端后
就可以正常接受订阅方的消息了
如果想让终端一直发送和接受的消息停下来,按ctrl+c,关闭节点(也就是ros::ok()函数判定为不ok了)
这就是案例一的实现了
3.注意事项:P45
3.1一个常见问题描述
问题:先打开订阅方 ,再打开发布方,依然会有前面几条数据没有收到。
原因:为发布方还未在roscore完成注册。
解决方法:解决方法是给发布方一个延时的发送函数。在发送内容的函数前,加一个延时函数,如 ros::Duration(3.0).sleep(); 延时3s即可
3.2ros经常用到的回调函数,什么是回调函数
老师的描述:普通函数是子弹,看见鬼子来了就打一枪
回调函数是地雷,不由自己控制,由外界来触发
比较像单片机的中断触发
4.计算图 P45
计算图并没有扩展ros的功能,但是可以直观地让我们看到不同节点之前的关系
在发布订阅都实现后,新开一个终端,输入rqt_graph ,可以查看计算图。
命令行输入:
计算图:节点talker把主题chatter发送给订阅方节点listener
案例二
1 基础配置
1.1新建文件夹及写好固定格式
在plumbing_pub_sub功能包下右击新建文件夹,创建名为msg的文件夹,msg文件夹下建立名为Person的文件。
/**msg的格式类始于结构体**/
string name
int32 age
float32 height
2.1配置package.xml
加入这两行
2.2配置CMakeLists.txt
在find_package添加message_generation find_package:编译时依赖
取消add_message_files的注释并修改
删除掉原有的 Message1.msg和Message2.msg的示例,添如自建的msg,Person.msg
将generate_messages取消注释
添加message_runtime功能包 catkin_package编译时依赖
2.3.编译
Ctrl+Shift+B后编译报错 错误如下:
– Configuring incomplete, errors occurred!
See also “/home/zhaojianqiao/demo04_ws/build/CMakeFiles/CMakeOutput.log”.
See also “/home/zhaojianqiao/demo04_ws/build/CMakeFiles/CMakeError.log”.
make: *** [Makefile:558: cmake_check_build_system] Error 1
Invoking “make cmake_check_build_system” failed
编译问题解决方法地址
然后可以在得到C++ 需要调用的中间文件(…/工作空间/devel/include/包名/xxx.h)
2.4.vscode配置
目的:为了让vscode能够找到上一步生成的.h文件
操作步骤:右击Person.h,选择在集成终端中打开,输入命令行pwd,终端则会显示.h文件所在位置
打开c_cpp_properties.json 文件来配置 includepath属性:
相同的格式将.h文件进行配置, “/home/zhaojianqiao/demo04_ws/devel/include/**”
**表示包含include文件夹下的所有内容
3.发布方实现
/*需求: 循环发布人的信息*/#include "ros/ros.h"
#include "plumbing_pub_sub/Person.h"int main(int argc, char *argv[])
{setlocale(LC_ALL,"");//1.初始化 ROS 节点ros::init(argc,argv,"talker_person");//2.创建 ROS 句柄ros::NodeHandle nh;//3.创建发布者对象ros::Publisher pub = nh.advertise<plumbing_pub_sub::Person>("chatter_person",1000); //话题名称+队列长度 发布方要写一个泛型类型,泛型类型根据消息类型指定//4.组织被发布的消息,编写发布逻辑并发布消息plumbing_pub_sub::Person p;p.name = "sunwukong";p.age = 2000;p.height = 1.45;ros::Rate r(1);while (ros::ok()){pub.publish(p);p.age += 1;ROS_INFO("我叫:%s,今年%d岁,高%.2f米", p.name.c_str(), p.age, p.height);r.sleep();ros::spinOnce();}return 0;
}
在配置CMakeLists.txt时需多添加一个
add_dependencies(demo03_pub_person ${PROJECT_NAME}_generate_messages_cpp)
目的是为了防止在源文件已经编译,但msg还未被编译的情况发生。
4.订阅方实现
订阅方代码
/*需求: 订阅人的信息*/#include "ros/ros.h"
#include "plumbing_pub_sub/Person.h"void doPerson(const plumbing_pub_sub::Person::ConstPtr& person_p){ROS_INFO("订阅的人信息:%s, %d, %.2f", person_p->name.c_str(), person_p->age, person_p->height); //这里是回调函数
}int main(int argc, char *argv[])
{ setlocale(LC_ALL,"");//1.初始化 ROS 节点ros::init(argc,argv,"listener_person");//2.创建 ROS 句柄ros::NodeHandle nh;//3.创建订阅对象ros::Subscriber sub = nh.subscribe<plumbing_pub_sub::Person>("chatter_person",10,doPerson);//主题名称+队列长度+回调函数//4.回调函数中处理 person//5.ros::spin();ros::spin(); return 0;
}
一样需要在CMakeLists.txt时需多添加一个
ros学习笔记_服务通讯相关推荐
- ROS学习笔记_创建工作空间(一)
创建工作空间 mkdir -p ~/catkin_ws_2/src -p参数是将路径上的父子目录同时创建. $ cd ~/catkin_ws_2/ $ catkin_make 在工作空间的根目录下运行 ...
- ROS 学习笔记(三):自定义服务数据srv+server+client 示例运行
ROS 学习笔记(三):自定义服务数据srv+Server+Client 示例运行 一.自定义服务数据: 1.向功能包添加自定义服务文件(AddTwoInts.srv) cd ~/catkin_ws/ ...
- ROS学习笔记十:用C++编写一个简单的服务和客户端
ROS学习笔记十:用C++编写一个简单的服务和客户端 这一节主要介绍如何使用C++编写一个简单的服务和客户端节点. 编写服务节点 由于在前面的练习中,已经向beginner_tutorials软件包中 ...
- ROS学习笔记六:理解ROS服务和参数
ROS学习笔记六:理解ROS服务和参数 主要介绍ROS服务和参数,同时使用命令行工具rosservice和rosparam. ROS service service是节点之间互相通信的另一种方式,se ...
- ROS学习笔记基础2(基础知识和ROS架构)
ROS学习笔记1(基础知识和ROS架构) 文章目录 ROS学习笔记1(基础知识和ROS架构) 1. 什么是ROS 2. ROS和其他机器人平台有什么不同 3. ROS架构组成 3.1 文件系统级别 3 ...
- ROS学习笔记(八): ROS通信架构
ROS学习笔记(八): ROS通信架构 文章目录 01 Node & Master 1.1 Node 1.2 Master 1.3 启动master和node 1.4 rosrun和rosno ...
- ROS学习笔记八:创建ROS msg和srv
ROS学习笔记八:创建ROS msg和srv 本节主要讲述了如何创建和建立ROS msg和srv,同时使用命令行工具rosmsg.rossrv和roscp. msg和srv简介 msg:描述ROS m ...
- ROS学习笔记五:理解ROS topics
ROS学习笔记五:理解ROS topics 本节主要介绍ROS topics并且使用rostopic和rqt_plot命令行工具. 例子展示 roscore 首先运行roscore系列服务,这是使用R ...
- ROS学习笔记四:理解ROS节点
ROS学习笔记四:理解ROS节点 本节主要介绍ROS图形概念,讨论ROS命令行工具roscore.rosnode和rosrun. 要求 要求已经在Linux系统中安装一个学习用的ros软件包例子: s ...
最新文章
- docker安装问题:E: Package 'docker-ce' has no installation candidate
- NetTier模板生成的代码框架用法 (转)
- linux编辑文档windows,1.9vim编辑器linux内核的底层文本编辑器,跟windows系统上的文本文档类似,大部分用这个工具进行文本的编辑,这个工具的操作方式基本上用不到鼠标,多是...
- Java常见面试知识点:继承、接口、多态、代码块
- 一款JS+CSS实现的无缝平滑图片滚动代码
- Emmet插件比较实用常用的写法
- paper 134:结构张量structure tensor(二)
- 一体机or复合机?企业文印设备该怎么选
- 铺铜规则在哪设定_干货丨PCB layout结合生产设计必须遵循这六大规则!
- 小说Symbian的签名
- 自举电容充电回路分析
- android 拍照水印日期,胶片日期水印app安卓版-胶片日期水印手机版预约v1.0-发卡屋...
- 微型计算机的指令集,窥视灵魂深处 AMD新一代SIMD指令集剖析
- Unity实现动态修改模型材质球
- 遇见你,是最美的意外
- mysql保留小数位数函数
- neogeo模拟器 linux,neogeo模拟器
- golang 格式化占位符相关
- 服务搭建篇(七) Elasticsearch单节点部署以及多节点集群部署
- 高德WMTS图层 调用天地图瓦片地图