ROS时间概念总结

ROS时间概念总结

——常用到的时间相关的一些类、定时器、概念

关于ROS Time和Wall Time

两者是有区别的。它们两个的接口完全一样,数据类型也一样,但是ROS Time表示的是网络中的时间(如果当时在非仿真环境里运行,那它就是当前的时间。但如果去回放当时的情况,那就需要把当时的时间录下来)

ROS Time可以被认为修改,你可以暂停它,可以加速,可以减速,但是Wall Time不可以

在开启一个Node之前,当把use_sim_time设置为true时,这个节点会从clock Topic获得时间。所以操作这个clock的发布者,可以实现一个让Node中得到ROS Time暂停、加速、减速的效果。同时下面这些方面都是跟Node透明的,所以非常适合离线的调试方式。当把ROSbag记下来以后重新play出来时,加两个横杠,–clock,它就会发布出这个消息

一、Time

roslib提供了ros::Time和ros::Duration两个类来描述时刻以及时间间隔(一般情况下,这里的时间都是跟平台即系统的时间相关联的,但ros提供了一种模拟时钟即ROS时钟时间)

  • Duration可以是负数
  • Time和Duration拥有一样的成员
    • int32 sec
    • int32 nsec

时间与时间间隔的基本使用

  • 获取当前时间
ros::Time begin = ros::Time::now()
  • 定义类对象
ros::Time::Time(uint32_t _sec, uint32_t _nsec)
ros::Time::Time(double t)

ros::Duration::Duration(uint32_t _sec, uint32_t _nsec)
ros::Duration::Duration(double t)

//_sec是秒,_nsec是纳秒
//故ros::Time a_little_after_the_beginning(0, 1000000);
//等价于ros::Time a_little_after_the_beginning(0.001);
  • 相互转换、比较
//Time继承自
template<class T, class D>
class ros::TimeBase< T, D >

//Duration继承自
template<class T>
class ros::DurationBase< T >

//两个基类都实现了>、<、!=等比较符。并且两者都实现了
uint64_t     toNSec () const
double     toSec () const
//我们可以通过这两个函数来进行Time和Duration的转化
  • 运算符
//两个基类都重载了+、-、+=、-=运算符:

/*1 hour + 1 hour = 2 hours (duration + duration = duration)
2 hours - 1 hour = 1 hour (duration - duration = duration)
Today + 1 day = tomorrow (time + duration = time)
Today - tomorrow = -1 day (time - time = duration)
Today + tomorrow = error (time + time is undefined)*/
  • 延时和循环
bool ros::Duration::sleep()
ros::Duration(0.5).sleep(); // sleep for half a second
  • 定时器

    • ros::Timer

ROS并不是实时系统,所以定时器并不能确保精确定时。精确的执行时间以及理论上应该执行的时间可以在回调函数的ros::TimerEvent结构中得到

ros::Timer ros::NodeHandle::createTimer(ros::Duration period, <callback>, bool oneshot = false);
ros::Timer timer = n.createTimer(ros::Duration(0.1), timerCallback);//定时0.1s
void timerCallback(const ros::TimerEvent& e);
//其中TimerEvent结构体定义如下:

struct TimerEvent
{
  Time last_expected;                     ///< In a perfect world, this is when the last callback should have happened
  Time last_real;                         ///< When the last callback actually happened
  Time current_expected;                  ///< In a perfect world, this is when the current callback should be happening
  Time current_real;                      ///< This is when the current callback was actually called (Time::now() as of the beginning of the callback)

  struct
  {
    WallDuration last_duration;           ///< How long the last callback ran for, always in wall-clock time
  } profile;
};
  • ros::Rate

它的功能就是先设定一个频率,然后通过睡眠度过一个循环中剩下的时间,来达到该设定频率。如果能够达到该设定频率则返回true,不能则返回false。计时的起点是上一次睡眠的时间、构造函数被调用、或者调用void ros::Rate::reset()函数重置时间。因为没有TimerEvent,所以相对于Timer而言,Rate的精确度会有所下降。

ros::Rate r(10); // 10 hz
while (ros::ok())
{
//... do some work ...
    bool met = r.sleep();
}
二、Wall Time

在模拟时,如果想要进入实际运行 wall-clock time ,可以用 ros::WallTime, ros::WallDuration, 和ros::WallRate,类似于 ros::Time, ros::Duration, 和 ros::Rate

  • 三种时间的定义
    • 时钟时间(wall clock time):从进程开始运行到结束,时钟走过的时间,其中包含了进程在阻塞和等待状态的时间
    • 用户CPU时间:就是用户的进程获得了CPU资源以后,在用户态执行的时间
    • 系统CPU时间:用户进程获得了CPU资源以后,在内核态的执行时间
  • 三者之间的关系 real time、user time、sys time
    • 进程的三种状态为阻塞、就绪、运行
    • 时钟时间 = 阻塞时间 + 就绪时间 + 运行时间
    • 用户CPU时间 = 运行状态下用户空间的时间
    • 系统CPU时间 = 运行状态下系统空间的时间
    • 用户CPU时间 + 系统CPU时间 = 运行时间

CPU总时间(user + sys)是CPU执行用户进程操作和内核(代表用户进程执行)系统调用所耗时间的总和,即该进程(包括线程和子进程)所使用的实际CPU时间。若程序循环遍历数组,则增加用户CPU时间;若程序执行exec或fork等系统调用,则增加系统CPU时间。

在多核处理器机器上,若进程含有多个线程或通过fork调用创建子进程,则实际时间可能小于CPU总时间,因为不同线程或进程可并行执行,但其时间会计入主进程的CPU总时间。若程序在某段时间处于等待状态而并未执行,则实际时间可能大于CPU总时间:

real < CPU 表明进程为计算密集型(CPU bound),利用多核处理器的并行执行优势
real ≈ CPU 表明进程为计算密集型,未并行执行
real > CPU 表明进程为I/O密集型 (I/O bound),多核并行执行优势并不明显

在实际使用情况中可用C++11提供的计时标准库chrono中的 steady_clock 和 system_clock来替代walltime,具体替换示例如下:

-    ros::WallTime end = ros::WallTime::now();
-    ros::WallDuration dur = end - start;
-    //ROS_INFO_STREAM(out_t);
-    logInform("lookupTransform at Time(0) took %f for an average of %.9f", dur.toSec(), dur.toSec() / (double)count);
+    steady_clock::time_point end = steady_clock::now();
+    double dur = std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count();
+    printf("lookupTransform at Time(0) took: %f (secs) for an average of: %.9f (secs)\n", dur, dur / (double)count);
---
-      out_t = bc.lookupTransform(v_frame1, v_frame0, ros::Time(0));
+      out_t = bc.lookupTransform(v_frame1, v_frame0, 0);

参考:

ROS时间概念总结

ROS::Time()vsROS::WallTime()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值