一、ROS基本数据类型的发布和订阅
ros中的std_msgs包含了许多基本的数据类型,基本数据类型的发布订阅通过std_msgs中的数据类型实现(后续会有自定义数据类型)。
std_msgs中包含的数据类型,可以通过在终端中键入“rosmsg list ”查看,下面给出std_msgs包含的一些基本的数据类型:
std_msgs/Bool
std_msgs/Byte
std_msgs/ByteMultiArray
std_msgs/Char
std_msgs/ColorRGBA
std_msgs/Duration
std_msgs/Empty
std_msgs/Float32
std_msgs/Float32MultiArray
std_msgs/Float64
std_msgs/Float64MultiArray
std_msgs/Header
std_msgs/Int16
std_msgs/Int16MultiArray
std_msgs/Int32
std_msgs/Int32MultiArray
std_msgs/Int64
std_msgs/Int64MultiArray
std_msgs/Int8
std_msgs/Int8MultiArray
std_msgs/MultiArrayDimension
std_msgs/MultiArrayLayout
std_msgs/String
std_msgs/Time
std_msgs/UInt16
std_msgs/UInt16MultiArray
std_msgs/UInt32
std_msgs/UInt32MultiArray
std_msgs/UInt64
std_msgs/UInt64MultiArray
std_msgs/UInt8
std_msgs/UInt8MultiArray
1、ROS字符串数据类型的发布和订阅
1.1 发布方实现
#include "ros/ros.h"
#include "std_msgs/String.h"
int main(int argc, char *argv[])
{
//乱码问题的解决
setlocale(LC_ALL,"");
//初始化ROS节点
ros::init(argc,argv,"pubNode");
//句柄
ros::NodeHandle nh;
//发布对象的创建
ros::Publisher pub;
pub = nh.advertise<std_msgs::String>("string",100);
//发布频率的设置
ros::Rate rate(1); //一秒一次
//创建待发布消息对象
std_msgs::String pubString;
std::string str1 = "第";
std::string str2 = "次发送!";
int8_t number = 1;
while(ros::ok())
{
//组织消息
std::stringstream ss;
ss<< str1 << std::to_string(number) <<str2;
pubString.data = ss.str();
//发布
pub.publish(pubString);
rate.sleep();
number++;
}
return 0;
}
1.2 订阅方实现
#include "ros/ros.h"
#include "std_msgs/String.h"
void doMsg(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("订阅到的消息为:%s",msg->data.c_str());
}
int main(int argc, char *argv[])
{
//乱码问题的解决
setlocale(LC_ALL,"");
//初始化ROS节点
ros::init(argc,argv,"subNode");
//句柄
ros::NodeHandle nh;
//发布对象的创建
ros::Subscriber sub;
sub = nh.subscribe<std_msgs::String>("string",100,doMsg);
//回旋函数
ros::spin();
return 0;
}
1.3 launch文件
<launch>
<node pkg="string_pub_sub" type="demo_pub" name="pub" output="screen"/>
<node pkg="string_pub_sub" type="demo_sub" name="sub" output="screen"/>
</launch>
2、ROS整形数据类型的发布和订阅
整形数据分int8、uint8、int16、uint16等多种,不同的长度在实现发布订阅时只是使用std_msgs中的数据类型不同,在此以int8为例
2.1 发布方实现
#include "ros/ros.h"
#include "std_msgs/Int8.h"
int main(int argc, char *argv[])
{
/* code */
//解决乱码
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc, argv, "pub");
//句柄
ros::NodeHandle nh;
//初始化发布者对象
ros::Publisher pub;
pub = nh.advertise<std_msgs::Int8>("intPub",100);
//组织数据
int8_t number = 1;
//设置发布频率
ros::Rate rate(1); //一秒一次
while(ros::ok())
{
//组织发布数据
std_msgs::Int8 dataPub;
dataPub.data = number;
//发布
pub.publish(dataPub);
//休眠
rate.sleep();
//自增
number++;
}
return 0;
}
2.2 订阅方实现
#include "ros/ros.h"
#include "std_msgs/Int8.h"
void doMsg(const std_msgs::Int8::ConstPtr& msg)
{
ROS_INFO("接受到的消息为:%d",msg->data);
}
int main(int argc, char *argv[])
{
/* code */
//解决乱码
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"sub");
//句柄
ros::NodeHandle nh;
//订阅方对象
ros::Subscriber sub;
sub = nh.subscribe<std_msgs::Int8>("intPub",100,doMsg);
//回旋
ros::spin();
return 0;
}
launch文件
<launch>
<node pkg="int_pub_sub" type="demo_pub_int" name="pub" output="screen"/>
<node pkg="int_pub_sub" type="demo_sub_int" name="sub" output="screen"/>
</launch>
3、ROS浮点型数据类型的发布和订阅
3.1 发布方实现
#include "ros/ros.h"
#include "std_msgs/Float32.h"
int main(int argc, char *argv[])
{
/* code */
//解决乱码
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"pub");
//句柄
ros::NodeHandle nh;
//创建发布者对象
ros::Publisher pub;
pub = nh.advertise<std_msgs::Float32>("floatPub",100);
//发布频率设置
ros::Rate rate(1);
double number = 1.0;
while(ros::ok())
{
//组织发布消息
std_msgs::Float32 pubData;
pubData.data = number;
//发布
pub.publish(pubData);
//自增
number = number +0.1;
rate.sleep();
}
return 0;
}
3.2订阅方实现
#include "ros/ros.h"
#include "std_msgs/Float32.h"
void domsg(const std_msgs::Float32::ConstPtr& msg)
{
ROS_INFO("接收到的消息为%.2f",msg->data);
}
int main(int argc, char *argv[])
{
/* code */
//解决乱码
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"pub");
//句柄
ros::NodeHandle nh;
//创建订阅者对象
ros::Subscriber sub;
sub = nh.subscribe<std_msgs::Float32>("floatPub",100,domsg);
ros::spin();
return 0;
}
launch文件
<launch>
<node pkg="flaoat_pub_sub" type="demo_pub_float" name="pub" output="screen"/>
<node pkg="flaoat_pub_sub" type="demo_sub_float" name="sub" output="screen"/>
</launch>
4、ROS布尔型数据类型的发布和订阅
4.1发布方实现
#include "ros/ros.h"
#include "std_msgs/Bool.h"
int main(int argc, char *argv[])
{
/* code */
//解决乱码问题
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"pub");
//句柄
ros::NodeHandle nh;
//发布者对象
ros::Publisher pub;
pub = nh.advertise<std_msgs::Bool>("boolPub",100);
//发布频率
ros::Rate rate(1);
//组织数据
bool boolData =0;
while(ros::ok())
{
//组织被发布数据
std_msgs::Bool boolPub;
boolPub.data = boolData;
//发布数据
pub.publish(boolPub);
//反转
if (boolData==1)
{
boolData = 0;
}
else
{
boolData = 1;
}
//休眠
rate.sleep();
}
return 0;
}
4.2订阅方实现
#include "ros/ros.h"
#include "std_msgs/Bool.h"
void doMsg(const std_msgs::Bool::ConstPtr& msg)
{
if(msg->data == 1)
{
ROS_INFO("接收到的消息为真");
}
else
{
ROS_INFO("接收到的消息为假");
}
}
int main(int argc, char *argv[])
{
/* code */
//解决乱码问题
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"pub");
//句柄
ros::NodeHandle nh;
//订阅者对象
ros::Subscriber sub;
sub = nh.subscribe<std_msgs::Bool>("boolPub",100,doMsg);
ros::spin();
return 0;
}
launch文件
<launch>
<node pkg="bool_pub_sub" type="demo_pub_bool" name="pub" output="screen"/>
<node pkg="bool_pub_sub" type="demo_sub_bool" name="sub" output="screen"/>
</launch>
二、ROS自定义数据类型的发布和订阅
std_msgs中封装了一些常用的数据类型,但是在实际应用中可能会根据项目的需求自定义一些消息类型,因此需要能够创建自定义消息。
1、相关配置
1.1定义msg文件
在功能包下创建msg文件夹,在该文件夹中添加.msg文件
例:
发布一个联系人的消息,该消息包括姓名、性别、电话号码、地址(前四个为字符串类型)、年龄(int类型)和身高(float类型)
string name
string gender
string phoneNumber
string addres
int8 age
float32 height
1.2 编辑配置文件
在package.xml文件中添加编译依赖和执行依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
<!--
exce_depend 以前对应的是 run_depend 现在非法
-->
1.3 CMakeList.txt编辑msg相关配置
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
# 需要加入 message_generation,必须有 std_msgs
## 配置 msg 源文件
add_message_files(
FILES
Person.msg #自定义的文件名称
)
# 生成消息时依赖于 std_msgs
generate_messages(
DEPENDENCIES
std_msgs
)
#执行时依赖
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES demo02_talker_listener
CATKIN_DEPENDS roscpp rospy std_msgs message_runtime # 新加message_runtime
# DEPENDS system_lib
)
1.4编译
编译后的中间文件查看
1.5 vscode配置
为了方便代码提示以及避免误抛异常,需要先配置vscode,为了方便代码提示以及避免误抛异常,需要先配置 vscode,将前面生成的 head 文件路径配置进 c_cpp_properties.json 的 includepath属性:
注:路径的查看可以右击生成的中间文件的include文件夹,选择“在集成终端中打开”,然后再终端输入“pwd”命令,然后复制路径,注意include后面的“/**”不要忘了
{
"configurations": [
{
"browse": {
"databaseFilename": "",
"limitSymbolsToIncludedHeaders": true
},
"includePath": [
"/opt/ros/noetic/include/**",
"/usr/include/**",
"/xxx/yyy工作空间/devel/include/**", //配置 head 文件的路径
"/home/wang/demo03_ws/devel/include/**",//例子
],
"name": "ROS",
"intelliSenseMode": "gcc-x64",
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++17"
}
],
"version": 4
}
2、发布方实现
#include "ros/ros.h"
#include "msg_pub_sub/Person.h"
int main(int argc, char *argv[])
{
/* code */
//解决乱码
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"pub");
//句柄
ros::NodeHandle nh;
//创建发布者对象
ros::Publisher pub;
pub = nh.advertise<msg_pub_sub::Person>("msgPub",100);
//组织发布消息
msg_pub_sub::Person person;
person.age = 18;
person.addres = "ubuntu路ros小区msg号";
person.gender = "男";
person.height = 1.88;
person.name = "msgPubSub";
person.phoneNumber = "12345678910";
//发布频率
ros::Rate rate(1);
while(ros::ok())
{
pub.publish(person);
rate.sleep();
}
return 0;
}
3、订阅方实现
#include "ros/ros.h"
#include "msg_pub_sub/Person.h"
void doMsg(const msg_pub_sub::Person::ConstPtr& msg)
{
ROS_INFO("联系人的姓名:%s",msg->name.c_str());
ROS_INFO("联系人的地址:%s",msg->addres.c_str());
ROS_INFO("联系人的性别:%s",msg->gender.c_str());
ROS_INFO("联系人的电话:%s",msg->phoneNumber.c_str());
ROS_INFO("联系人的年龄:%d",msg->age);
ROS_INFO("联系人的身高:%.2f",msg->height);
}
int main(int argc, char *argv[])
{
/* code */
//解决乱码
setlocale(LC_ALL,"");
//初始化ros节点
ros::init(argc,argv,"sub");
//句柄
ros::NodeHandle nh;
//创建发布者对象
ros::Subscriber sub;
sub = nh.subscribe<msg_pub_sub::Person>("msgPub",100,doMsg);
ros::spin();
}
4、launch文件
<launch>
<node pkg="msg_pub_sub" type="demo_pub_msg" name="pub" output="screen"/>
<node pkg="msg_pub_sub" type="demo_sub_msg" name="sub" output="screen"/>
</launch>