ROS定时器

roscpp的定时器会计划在某一频率下执行一次回调操作,在订阅或服务中的回调函数队列机制中使用。

创建定时器

通过ros::NodeHandle::createTimer()创建: ros::Timer timer = nh.createTimer(ros::Duration(0.1), timerCallback); 其实有多个重载,这是用的比较多的一种。

回调函数只能是这种形式: void callback(const ros::TimerEvent&);
ros::TimerEvent结构体作为参数传入,它提供时间的相关信息,对于调试和配置非常有用。ros::TimerEvent结构体说明:

1
2
3
4
5
6
7
8
9
10
// 上次回调期望发生的时间
ros::Time last_expected
// 上次回调实际发生的时间
ros::Time last_real
// 本次回调期待发生的时间
ros::Time current_expected
// 本次回调实际发生的时间
ros::Time current_real
// 上次回调的时间间隔(结束时间-开始时间),是wall-clock时间。
ros::WallTime profile.last_duration

常用代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void odomTimerCb(const ros::TimerEvent& e);
void odomSubCb(const nav_msgs::OdometryConstPtr& m);
ros::Timer odomTimer ;
riki_msgs::HealthStatus msg;

int main(int argc, char** argv)
{
ros::init(argc,argv,"healthStatus");
ros::NodeHandle nh;
odomTimer = nh.createTimer(ros::Duration(5), odomTimerCb);
ros::Subscriber odomSub = nh.subscribe("odom", 1000, odomSubCb);

ros::Publisher pub = nh.advertise<riki_msgs::HealthStatus>("healthStatus", 1000);
ros::Rate loop_rate(1);
while(ros::ok())
{
pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
}
}

void odomTimerCb(const ros::TimerEvent& e)
{
msg.odomData = false;
}
void odomSubCb(const nav_msgs::OdometryConstPtr& m)
{
msg.odomData = true;
odomTimer.stop();
odomTimer.start();
}

未发布odom主题时,不会进入订阅者的回调函数odomSubCb,只进入定时器的回调odomTimerCb,此时消息成员odomData一直是false。
发布odom后,进入订阅者回调,此时odomData成为true,此时需要先停止计时器再打开。如果不停止,还会进入计时器回调,让消息成员赋值为false,实际造成赋值混乱。但是还得打开,因为一旦odom话题关闭了,就不会再进入订阅者回调,需要设法调用计时器回调,赋值false。订阅odom话题成功再打开计时器后,不会进入计时器回调。

参考: ROS与C++入门教程-Timers