(一):c++代码
#include<ros/ros.h>
#include<turtlesim/Pose.h>
#include<iomanip>
void poseMessageReceived(const turtlesim::Pose & msg)
{
ROS_INFO_STREAM(std::setprecision(2) << std::fixed
<< " position =(" << msg.x << " , " << msg.y << " ) "
<< " *direction=" << msg.theta);
}
int main(int argc, char** argv)
{
ros::init(argc, atgv, "subscribe_to_pose");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("turtle1/pose", 1000,
&poseMessageReceived);
ros::spin();
}
(二):代码解释
#include<ros/ros.h>
#include<turtlesim/Pose.h>
#include<iomanip>
第一个头文件是所有ros程序都必须有的
第二个头文件是这次用到的消息的主题
第三个头文件是用于控制输入输出
void poseMessageReceived(const turtlesim::Pose & msg)
{
ROS_INFO_STREAM(std::setprecision(2) << std::fixed
<< " position =(" << msg.x << " , " << msg.y << " ) "
<< " *direction=" << msg.theta);
}
这个是回调函数。订阅者程序无法知道消息什么时候会到达,因此需要一个回调函数作为响应,ROS每接收到一个新消息都将调用一次回调函数。需要注意的细节包括:(1)回调函数没有返回值,这是因为,调用此函数是ROS的工作,数据返回也是返回到ROS中而不是返回到程序中(节点?),因此程序中的回调函数不需要返回值。(2)回调函数参数的形式为“const package_name::type_name &msg”,package_name::type_name在这个程序中就是我们定义的第二个头文件名
主函数
ros::init(argc, atgv, "subscribe_to_pose");
ros::NodeHandle nh;
这两句就是很套路的初始化语句,前两个ros程序中都讲过了
ros::Subscriber sub = nh.subscribe("turtle1/pose", 1000,
&poseMessageReceived);
声明了一个ros::Subscriber类的对象sub,调用了nh.subscribe作为构造函数,这个构造函数有三个形参,第一个形参表示要订阅的主题名,第二个形参表示队列的容量,第三个形参是指向回调函数的指针,代表着发生事件后的响应函数,注意不要在函数名后面加括号()。
ros::spin();
这个东西不是很明白,书上的解释是,只有当我们明确给ROS控制权时,ROS才能调用回调函数,有两种方式可以做到这点,本程序使用的ros::spin()就是一种方法。这个方法要求ROS等待并执行回调函数直到该节点关机。
另外一种方法是ros::spinOnce(),这种方法要求ROS去执行所有挂起的回调函数,然后将控制权限返回给我们
ros::spin()大概等于
while(ros::ok( ))
{ros::spinOnce();
}
(三):声明依赖库
这个程序的依赖库比较简单,只需在Hello ROS程序的基础上加上turtlesim库就可以,具体可见《ROS:Hello ROS程序》
(四):其他设置及编译
前面几篇博客写的很清楚了,略
(五):执行
打开节点管理器
然后用三个命令窗分别执行pubvel,subpose,turtlesim_node三个程序,在subpose的命令窗内可以看见不断跳动的位姿数据。
版权声明:本文为buaazyp原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。