// linear线性的 angular角度的
//%0.2f打印geometry_msgs::Twist类型
// %s打印std_msgs::String类型
// linear线性的 angular角度的
%0.2f打印geometry_msgs::Twist类型
启动小海龟及其键盘控制
$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun turtlesim turtle_teleop_key
第二步查看rosnode节点直接的关系
查看rosnode节点直接的关系
$ rqt_graph
由于箭头是单向的,所以消息传播是单向的,由图像可知,/teleop_turtle为发布者Publisher,用于键盘发布指令,/turtlesim为订阅者Subscriber,用于定义指令,两节点的通信管道为/turtle/cmd_vel,只要实现一个发布者在通信管道/turtle/cmd_vel发送相应信息都会被订阅者订阅,下面将介绍如何查看发布消息的类型
查看发布消息的列表
$ rosnode list
我们可以看到发布者/teleop_turtle
然后输入下列指令
$ rosnode info /teleop_turtle
我们可以看到
Publications:
* /rosout [rosgraph_msgs/Log]
* /turtle1/cmd_vel [geometry_msgs/Twist]
其中 /turtle1/cmd_vel [geometry_msgs/Twist]是我们要的信息
以 /turtle1/cmd_vel消息管道,以geometry_msgs::Twist传递消息
Services:
* /teleop_turtle/get_loggers
* /teleop_turtle/set_logger_level
这里面可以看到/teleop_turtle,该为发布者的节点名
第四步创建发布者Publishser创建发布者Publishser
//以 /turtle1/cmd_vel消息管道,以geometry_msgs::Twist传递消息
// /teleop_turtle,该为发布者的节点名
// linear线性的 angular角度的
//%0.2f打印geometry_msgs::Twist类型
#include "ros/ros.h"
#include "geometry_msgs/Twist.h"
int main(int argc, char **argv){
//初始化ros节点
ros::init(argc, argv, "Publisher");//也可以将Publisher改为/teleop_turtle
//创建节点句柄
ros::NodeHandle node;
//创建一个发布者Publisher,消息管道/turtle1/cmd_vel,消息类型geometry_msgs::Twist
ros::Publisher pub = node.advertise("/turtle1/cmd_vel",1000);
//设置一个循环频率每秒5次
ros::Rate loop_rate(5);
//计数发布次数
int count = 0;
while (ros::ok()){
//初始化消息类型geometry_msgs::Twist
geometry_msgs::Twist msg;
msg.linear.x = 5;
msg.angular.z = 1;
//发布消息
pub.publish(msg);
//发布成功在该节点终端显示
//已成功发布第%d条消息,发布的内容为%0.2f打印geometry_msgs::Twist类型
ROS_INFO("Successfully published message %d with:[msg.linear.x = %0.2f m/s , msg.angular.z = %.2f rad/s]"
,count , msg.linear.x, msg.angular.z);
loop_rate.sleep();
++count;
}
return 0;
}
发布者运行结果:
第五步创建订阅者Sbuscriber
创建订阅者Sbuscriber
由图像可知,消息管道为/turtle1/cmd_vel
消息类型为geometry_msgs::Twist
* /turtlesim/get_loggers
* /turtlesim/set_logger_level
节点名为/turtlesim
/*
* 消息管道为/turtle1/cmd_vel 消息类型为geometry_msgs::Twist
* 节点名为 /turtlesim
*/
#include "ros/ros.h"
#include "geometry_msgs/Twist.h"
void cmdCallBack(const geometry_msgs::Twist& msg){
//将收到的消息打印出来
ROS_INFO("The message I received was:[x=%0.2f m/s, z=%0.2f rad/s]"
, msg.linear.x, msg.angular.z);
}
int main(int argc, char **argv){
//初始化ros节点
ros::init(argc, argv, "Subscriber");//节点名也可以写成/turtlesim
//创建节点句柄
ros::NodeHandle node;
//创建一个Subscriber,消息管道为/turtle1/cmd_vel,注册回调函数为cmdCallBack
ros::Subscriber sub = node.subscribe("/turtle1/cmd_vel", 1000, cmdCallBack);
ros::spin();
return 0;
}
订阅者运行结果:
扩展:发布hello_n_word并订阅
通过上面的内容实现,不通过小海龟信息管道,自己定义一个,来实现发布者发布hello_n_word ,n为数字并打印在自己终端,订阅者接收并打印出该消息。
第一步:模拟发布者//以 /talker消息管道,以std_msgs::String传递消息
// /Publisher,该为发布者的节点名
// %s打印std_msgs::String类型
#include "sstream"
#include "ros/ros.h"
#include "std_msgs/String.h"
int main(int argc, char **argv){
//初始化ros节点
ros::init(argc, argv, "Publisher");
//创建节点句柄
ros::NodeHandle node;
//创建一个发布者Publisher,消息管道/turtle1/cmd_vel,消息类型std_msgs::String
ros::Publisher pub = node.advertise("/talker",1000);
//设置一个循环频率每秒5次
ros::Rate loop_rate(5);
//计数发布次数
int count = 0;
while (ros::ok()){
++count;
//初始化消息类型std_msgs::String
std_msgs::String msg;
std::stringstream ss;
ss<< "hello_"<< ++count<<"_world";
msg.data = ss.str();
//发布消息
pub.publish(msg);
//发布成功在该节点终端显示
//已成功发布第%d条消息,发布的内容为%s打印std_msgs::String类型
ROS_INFO("Successfully published message with:[%s]",msg.data.c_str());
loop_rate.sleep();
}
return 0;
}
第二步:模拟订阅者
/*
* 消息管道为/talker 消息类型为std_msgs::String
* 节点名为 /Subscriber
*/
#include "sstream"
#include "ros/ros.h"
#include "std_msgs/String.h"
void cmdCallBack(const std_msgs::String::ConstPtr& msg){
//将收到的消息打印出来
ROS_INFO("The message I received was:[%s]",msg->data.c_str());
}
int main(int argc, char **argv){
//初始化ros节点
ros::init(argc, argv, "Subscriber");
//创建节点句柄
ros::NodeHandle node;
//创建一个Subscriber,消息管道为/turtle1/cmd_vel,注册回调函数为cmdCallBack
ros::Subscriber sub = node.subscribe("/talker", 1000, cmdCallBack);
ros::spin();
return 0;
}
运行结果: