本文记录ROS通信中spinOnce和spin两个回调函数的区别与联系。首先两者相同点是,两者均为回旋函数,可用于处理回调函数。两者的不同点:ros::spin() 是进入了循环执行回调函数,而 ros::spinOnce() 只会执行一次回调函数(没有循环),在 ros::spin() 后的语句不会执行到,而 ros::spinOnce() 后的语句可以执行。
两者API
/**
* \brief 处理一轮回调
*
* 一般应用场景:
* 在循环体内,处理所有可用的回调函数
*
*/
ROSCPP_DECL void spinOnce();
/**
* \brief 进入循环处理回调
*/
ROSCPP_DECL void spin();
代码测试 C++
发布者,注意在spinOnce函数的下方还有个打印语句:
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc,char *argv[]){
/*
init 方法中,有几个参数
argc:参数个数(n+1,其中那1个是自身)
argv:接收传递的参数
options: 可选项
name:节点名称要唯一,否则重复启动,启动早的容易被覆盖
ros::init_options::AnonymousName:避免同一个名称的节点多次启动,会追加时间的编码
*/
setlocale(LC_ALL,"");
//1 初始化ros节点
ros::init(argc,argv,"publisher",ros::init_options::AnonymousName);
//2 创建句柄
ros::NodeHandle nh;
/**
* \brief 根据话题生成发布对象
*
* 在 ROS master 注册并返回一个发布者对象,该对象可以发布消息
*
* 使用示例如下:
*
* ros::Publisher pub = handle.advertise<std_msgs::Empty>("my_topic", 1);
*
* \param topic 发布消息使用的话题
*
* \param queue_size 等待发送给订阅者的最大消息数量
*
* \param latch (optional) 如果为 true,该话题发布的最后一条消息将被保存,并且后期当有订阅者连接时会将该消息发送给订阅者
一般在发送静态地图时,设置为 true,这时发送方仅需要发送一次,即可当接收方连接时,收到消息
*
* \return 调用成功时,会返回一个发布对象
*
*
*/
//3 创建发布者对象
//ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10,true);
//4 编写发布逻辑并发布数据
// 创建被发布的信息
std_msgs::String msg;
//定义频率
ros::Rate rate(10);
//设置编号
int count=0;
//可让发送数据前 休眠3秒 当作是注册到roscore的时间
//这样可保证订阅者 可 接收到前几个信息
ros::Duration(3).sleep();
//循环发布
while(ros::ok()){
count++;
std::stringstream ss;
ss << "hello ---> " << count;
msg.data = ss.str();
if(count <= 10){
pub.publish(msg);
//添加日志
ROS_INFO("发布的数据为: %s",ss.str().c_str());
}
rate.sleep();
//官方建议 主要用于调用回调函数
ros::spinOnce();
ROS_INFO("spinOnce run out ...");
}
return 0;
}
订阅方,注意在spin 函数的下方还有个打印语句:
#include "ros/ros.h"
#include "std_msgs/String.h"
void doMsg(const std_msgs::String::ConstPtr &msg){
ROS_INFO("subcribe msg: %s", msg->data.c_str());
}
int main(int argc, char *argv[]){
setlocale(LC_ALL,"");
//1 初始化ros节点
ros::init(argc,argv,"subcribe");
//2 创建句柄
ros::NodeHandle nh;
//3 创建发布者对象
ros::Subscriber sub = nh.subscribe("fang",10,doMsg);
//为了处理上面的回调函数
ros::spin();
ROS_INFO("spin run out ...");
return 0;
}
运行程序
发布者:
订阅者: