** TimeBase基類**
首先看time.h文件,它定義了一個叫TimeBase的類。注釋中說,TimeBase是個基類,定義了兩個成員變量uint32_t sec, nsec,還重載了+ ++、? -?、< <<、> >>、= ==等運算符。
成員變量uint32_t sec, nsec其實就是時間的秒和納秒兩部分,它們合起來構成一個完整的時刻。
至于為啥要分成兩部分而不是用一個來定義,可能是考慮到整數表示精度的問題。
因為32位整數最大表示的數字是2147483647。如果我們要用納秒這個范圍估計是不夠的。
你可能會問,機器人系統怎么會使用到納秒這么高精度的時間分辨率,畢竟控制器的定時器最高精度可能也只能到微秒?
如果你做過自動駕駛項目,有使用過GPS和激光雷達傳感器的經驗,就會發現GPS的時鐘精度就是納秒級的,它可以同步激光雷達每個激光點的時間戳。
還有,為什么定義TimeBase這個基類,原因大家很容易就能猜到。
因為在程序里,時間本質上就是一個數字而已,數字系統的序關系(能比較大小)和運算(加減乘除)也同樣適用于時間這個東西。
當然,這里只有加減沒有乘除,因為時間的乘除沒有意義。
Time類
緊接著TimeBase類的是Time類,它是TimeBase的子類。我們做機器人應用程序開發時用不到TimeBase基類,但是Time類會經常使用。
now()函數
Time類比TimeBase類多了now()函數,它是我們的老熟人了。在開發應用的時候,我們直接用下面的代碼就能得到當前的時間戳:
ros::Time begin = ros::Time::now(); //獲取當前時間
now()函數的定義在rostimesrctime.cpp里,因為它很常用很重要,筆者就把代碼粘貼在這里,如下。
函數很簡單,可以看到,如果定義了使用仿真時間(g_use_sim_time為true),那就使用仿真時間,否則就使用墻上時間。
Time Time::now()
{
if (!g_initialized)
throw TimeNotInitializedException();
if (g_use_sim_time)
{
boost::mutex::scoped_lock lock(g_sim_time_mutex);
Time t = g_sim_time;
return t;
}
Time t;
ros_walltime(t.sec, t.nsec);
return t;
}
在ROS里,時間分成兩類,一種叫仿真時間,一種叫墻上時間。
顧名思義,墻上時間就是實際的客觀世界的時間,它一秒一秒地流逝,誰都不能改變它,讓它快一點慢一點都不可能,除非你有超能力。
仿真時間則是可以由你控制的,讓它快它就快。之所以多了一個仿真時間,是因為有時我們在仿真機器人希望可以自己控制時間,例如為了提高驗證算法的效率,讓它按我們的期望速度推進。
在使用墻上時間的情況下,now()函數調用了ros_walltime函數,這個函數也在rostimesrctime.cpp里。
剝開層層洋蔥皮,最后發現,這個ros_walltime函數才是真正調用操作系統時間函數的地方,而且它還是個跨平臺的實現(Windows和Linux)。
如果操作系統是Linux,那它會使用clock_gettime函數,在筆者使用的Ubuntu 18.04系統中這個函數在usrinclude路徑下。
但是萬一缺少這個函數,那么ROS會使用gettimeofday函數,但是gettimeofday沒有clock_gettime精確,clock_gettime能提供納秒的精確度。
如果操作系統是Windows,那它會使用標準庫STL的chrono庫獲取當前的時刻,要用這個庫只需要引用它的頭文件,所以在time.cpp中引用了#include。
具體使用的函數就是
std::chrono::system_clock::now().time_since_epoch()。
當然,時間得是秒和納秒的形式,所以用了count方法:
uint64_t now_ns = std::chrono::duration_cast< std::chrono::nanoseconds >
(std::chrono::system_clock::now().time_since_epoch()).count();
WallTime類
后面又接著聲明了WallTime類和SteadyTime類。
-
控制器
+關注
關注
112文章
16398瀏覽量
178544 -
定時器
+關注
關注
23文章
3251瀏覽量
115013 -
文件
+關注
關注
1文章
569瀏覽量
24769 -
ROS
+關注
關注
1文章
278瀏覽量
17035
發布評論請先 登錄
相關推薦
評論