这里简单的记录一下在ros系统中如何实现一个发布者,仅对新手,老司机可以以直接忽略啦!
首先我个人认为发布有两种情况 :一种是发布已有功能包中的数据类型,比如我们可以发布turtlesim功能包中已经存在的数据类型。另一种是发布自己创建的消息数据类型。后者需要自己在自己所建的功能包下面建立一个msg文件夹,并且在这个文件夹下建立一个.msg文件,这个msg文件中用来存放我们个人所想要发布的数据类型。今天我重点来讲述总结前者。
先说一下创建一个已有消息类型发布者的完整步骤
1:创建一个工作空间 并进行编译
2:在这个工作空间的src目录下 创建一个功能包 这点要注意 加上依赖项 roscpp rospy std_msgs geometry_msgs turtlesim 后面两个我不太清楚为什么加进来 可能是因为 我们使用turtlesim功能包中的数据类型才加进来吧,不过这不是重点。
3:创建一个publisher.cpp文件 开始书写程序即可。 下面是程序书写步骤
第一步:初始化节点 给节点起一个名字 告诉节点管理器 我来了 并创建节点句柄 这基本是所有话题通讯会做的事,这个节点名字可以随便取 ,但是最好比较有明显的含义吧
ros::init(argc,argv,"节点名字");
ros::NodeHandle n;
第二部:创建一个发布者 这里发布者的名字可以随便取 好记有意思即可 这里包括了消息类型和话题名字 请想一下我们怎么确定消息类型和话题名字呢?下面这句话是固定套路 记住就行 Publisher是大写 后面 advertise也记住 这都是发布消息的基本语句内容。
ros::Publisher 发布者 = n.advertise<消息类型>("话题名字",队列长度);
第三部:设置循环的频率 括号中是多少 就是每秒多少次
ros::Rate loop_rate(10);
第四部:进入while(ros::ok())循环 创建消息实例 发布消息即可 后面加上循环等待
这里的程序要根据消息的数据类型来写 ,这里不做介绍 在下面的代码中会有体现
loop_rate.sleep();
看似到这里已经很完美了 ,网上的多数教程也是这样做的,但是请原谅我是个菜鸡,我在编写程序的时候依然是云里雾里,直到现在我也不太明白 。我把我知道这些东西记录下来 防止忘记。
重点来了:从最开始说起 ,刚开始说话 我们发布的是turtlesim这个功能包中已有的消息类型 那么这个包里有哪些数据类型?每个数据类型又是依赖那个话题进行通讯的呢?每个数据类型内部结构又究竟是怎么定义的呢?带着这些东西我们去寻找答案 啦啦啦啦啦啦
首先打开一个新的终端 运行rosrun turtlesim turtlesim_node 这个节点 这时候我们便可以使用相应的命令来查看上面的问题了。
首先我们要知道我们在哪个话题上进行发布 使用rostopic list即可 可以看到
关于海龟的三个话题 /turtle1/cmd_vel /turtle1/color_sensor /turtle1/pose
那么这三个话题所对应的消息类型又是什么呢 我们可以通过 rostopic type +话题名字进行查看 得到如下结果
rostopic type /turtle1/cmd_vel --->geometry_msgs/Twist
rostopic type /turtle1/color_sensor --->turtlesim/Color
rostopic type /turtle1/pose --->turtlesim/Pose
假设我们选择 /turtle1/cmd_vel 进行发布消息 那么请问还记得吗 ?这个话题进行发布包含了两个头文件
#include "ros/ros.h" #include "geometry_msgs/Twist.h"
我刚学的时候 一直好奇后面那个头文件是怎么找出来的,原来就是用 rostopic type /turtle1/cmd_vel 这个东西找出来的 也就是这个消息类型是geometry_msgs::Twist
这里我们二货一下 为什么网上的教程在写发布程序的时候 都选择 这个话题 而不是其他两个呢?我就傻逼的遇到了这个问题,我选择了那个颜色的话题,程序通过编译 没有问题 然后运行海龟节点 和这个发布的节点 发现海龟的背景颜色根本没有改变,原因是
后来 运行了 rqt_graph这个命令 发现两个节点 根本没有建立通讯联系
使用 rosnode info turtlesim 之后 发现 turtlesim这个节点的详细信息中 后面那两个话题是海归节点发布的话题 海归节点订阅的是第一个话题 所以绝对不会有反应的!!!!
下面说在while中创建发布实例的问题 我们知道了消息类型 但是并不知道消息的具体内部定义,这时候我们可以使用
rosmsg show geometry_msgs/Twist
geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z
rosmsg show turtlesim/Color
uint8 r
uint8 g
uint8 b
rosmsg show turtlesim/Pose
float32 x
float32 y
float32 theta
float32 linear_velocity
float32 angular_velocity
最后一点 写完程序之后 要添加编译连接语句。
这样我们就可以创建实例了,差不多就是这些内容 下面我把源码放上 ,刚学没两天 说的术语都不太对 大家见谅 欢迎拍砖
#include "ros/ros.h"
#include "geometry_msgs/Twist.h"
int main(int argc,char **argv)
{
//初始化节点 创建节点句柄 告诉节点管理器 老娘来了
ros::init(argc,argv,"publish_color");
ros::NodeHandle n;
ros::Publisher pub_color = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",10);
//设定循环频率
ros::Rate loop_rate(10);
unsigned char count=0;
while(ros::ok())
{
geometry_msgs::Twist v_msg;
v_msg.linear.x=0.2;
v_msg.linear.y=0.6;
v_msg.linear.z=0.4;
v_msg.angular.x=0.2;
v_msg.angular.y=0.6;
v_msg.angular.z=0.3;
pub_color.publish(v_msg);
ROS_INFO("v_msg.linear.x:%lf v_msg.linear.y:%lf v_msg.linear.z:%lf", v_msg.linear.x, v_msg.linear.y, v_msg.linear.z);
loop_rate.sleep();
}
return 0;
}
#include "ros/ros.h"
#include "learing_topic_server/Person.h"
int main(int argc,char ** argv)
{
//初始化节点
ros::init(argc,argv,"person_publish");
ros::NodeHandle n;
//创建发布函数
ros::Publisher person_pub=n.advertise<learing_topic_server::Person>("person_info",10);
//设置循环频率
ros::Rate loop_rate(10);
while(ros::ok())
{
learing_topic_server::Person people;
people.name = "GUO";
people.sex =1;
people.age =24;
person_pub.publish(people);
loop_rate.sleep();
}
return 0;
}
#include "ros/ros.h"
#include "learing_topic_server/Person.h"
void personCallback(const learing_topic_server::Person::ConstPtr& person_msg)
{
std::cout <<"subscriber is succeddfully"<<std::endl;
ROS_INFO("name:%s age:%d sex:%d",person_msg->name.c_str(),person_msg->age,person_msg->sex);
}
int main(int argc,char** argv)
{
ros::init(argc,argv,"person_subscriber");
ros::NodeHandle n;
ros::Subscriber person_sub = n.subscribe("person_info",10,personCallback);
ros::spin();
return 0;
}