ROS多线程消息发布
在ROS
消息接收再转发的程序设计中,会遇到如下需求:
- 现有一
A
话题 - 节点
B
订阅A
话题 - 节点
B
接收到A
话题msg
消息的特定值时如msg={"你可以停止接收了"}
,停止订阅A
话题 - 节点
B
发布话题C
在对该需求进行程序设计时,一开始想以这样的框架完成需求
// 仅为框架,不阐述细节
#include "..."
// 订阅消息A的回调函数
void callback(Date_type& msg)
{
if(msg=="你可以停止接收了")
{
// 取消订阅A
sub_A.shutdown();
return;
}
}
int main(...)
{
...;
sub_A = n.subscribe(A,n,callback);
pub_C = n.advertise(C,1000,true);
ros::Rate loop_rate(10);
while(ros::ok())
{
// 发布C的消息
pub(C_msg);
ros::spinOnce();
// 补足发布频率
loop_rate.sleep();
}
ros::spin();
}
但是发现订阅消息A
的回调函数callback
不执行,猜测可能是由于ros
消息订阅的回调函数是在 ros::spin()
中触发的,我们在ros::spin()
前加了while
循环导致订阅A
的回调不能正常触发。
如果将该问题拆分为两个节点或者三个节点来处理,应该也可以解决该需求,但显然有些繁琐。
参考VINS-MONO
中的多线程操作,尝试创建一个线程来解决问题。
程序设计框架如下
// 仅为框架,不阐述细节
#include "..."
bool flag = false;
// 订阅消息A的回调函数
void callback(Date_type& msg)
{
if(msg=="你可以停止接收了")
{
// 取消订阅A
sub_A.shutdown();
flag = true;
return;
}
}
void pub_process()
{
ros::Rate loop_rate(10);
while(ros::ok())
{
// 消息发布标志
if(flag == false)continue;
pub_C(C_msg);
ros::spinOnce();
loop_rate.sleep();
}
}
int main(...)
{
...;
sub_A = n.subscribe(A,n,callback);
pub_C = n.advertise(C,1000,true);
// 创建一个发布线程,并链接函数
std::thread measurement_process{pub_porcess};
ros::Rate(20);
ros::spin();
}
该框架可以完成本文的问题的需求,但就程序设计而言,线程间的变量传递应该完成加锁与解锁的操作,后续如果有时间会补上这一部分(挖个坑先)。