roscpp的定时器会计划在某一频率下执行一次回调操作,在订阅或服务中的回调函数队列机制中使用。
创建定时器
通过ros::NodeHandle::createTimer()创建: ros::Timer timer = nh.createTimer(ros::Duration(0.1), timerCallback);
其实有多个重载,这是用的比较多的一种。
回调函数只能是这种形式: void callback(const ros::TimerEvent&);
ros::TimerEvent结构体作为参数传入,它提供时间的相关信息,对于调试和配置非常有用。ros::TimerEvent结构体说明:
1 | // 上次回调期望发生的时间 |
常用代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17void callback(const ros::TimerEvent&)
{
ROS_INFO("Callback triggered");
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "test_timer_node");
signal(SIGINT, SigintHandler);
ros::NodeHandle nh;
ros::Timer timer = nh.createTimer(ros::Duration(0.5), callback);
ros::spin();
return(0);
}
实战
比如某些情况下,我们需要一直监视机器人的里程计数据状态,并在某个界面上显示出来。这种情况下可以用到定时器,
1 | void odomTimerCb(const ros::TimerEvent& e); |
未发布odom主题时,不会进入订阅者的回调函数odomSubCb
,只进入定时器的回调odomTimerCb
,此时消息成员odomData
一直是false。
发布odom后,进入订阅者回调,此时odomData
成为true,此时需要先停止计时器再打开。如果不停止,还会进入计时器回调,让消息成员赋值为false,实际造成赋值混乱。但是还得打开,因为一旦odom
话题关闭了,就不会再进入订阅者回调,需要设法调用计时器回调,赋值false。订阅odom
话题成功再打开计时器后,不会进入计时器回调。