ROS中的日志(log)消息


學會使用日志(log)系統,做ROS大型項目的主治醫生
0

通過顯示進程的運行狀態是好的習慣,但需要確定這樣做不會影響到軟件的運行效率和輸出的清晰度。ROS 日志 (log) 系統的功能就是讓進程生成一些日志消息,顯示在屏幕上、發送到特定 topic 或者儲存在特定 log 文檔中,以方便調試、記錄、報警等。下面簡單介紹如何生成和查看日志消息。

日志消息

在ROS中,有一個特殊的話題叫作/rosout,它承載着所有節點的所有日志消息。/rosout消息的類型是rosgraph_msgs/Log:

1

rosgraph_msgs/Log消息用來讓各個節點發布日志消息,這樣一來就能讓網絡上的任何一個人都看到。可以認為/rosout是一個加強版的print():他不是向終端輸出字符串,可以將字符串和元數據放到一個消息中,發送到網絡上的任何一個人。ROS節點應該向/rosout發布日志消息,這樣一來這些消息就能被所有人看到。rospy客戶端提供了多個函數來發布rosgraph_msgs/Log消息:

1
2
if battery_voltage < 11.0:
rospy.logwarn('Battery voltage low: %f'%(battery_voltage))

rospy.logwarn()函數實現了三件事請:

  1. 輸出一個格式化的字符串到終端
  2. 輸出更詳細的警告到日志文檔中,這個文檔一般在~/.ros/log中
  3. 構建並發布一條消息到/rosout話題,其中包括警告以及節點元數據

日志等級

ROS有5個日志記錄標准級別,這些名稱是輸出信息的函數的一部分,他們遵循以下語法:
ROS_<LEVEL>[_<OTHER>]
每個消息級別用於不同的目的:

  • DEBUG(調試):只在調試時用,此消息不出現在部署的應用中,僅用於測試。
  • INFO(信息):標准消息,說明重要步驟或節點所正在執行的操作。
  • WARN(警告):提醒一些錯誤,缺失或者不正常,但進程仍能運行。
  • ERROR(錯誤):提示錯誤,盡管節點仍可在這里恢復,但對節點的行為設置了一定期望。
  • FATAR(致命):這些消息通常表示阻止節點繼續運行的錯誤。

2

生成基本的日志消息

由五個 C++ 宏來產生日志消息,每個宏對應一個級別:

1
2
3
4
5
ROS_DEBUG_STREAM(message);  
ROS_INFO_STREAM(message);
ROS_WARN_STREAM(message);
ROS_ERROR_STREAM(message);
ROS_FATAL_STREAM(message);

編寫如下 C++ 進程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

int (int argc,char **argv)
{
ros::init(argc,argv,"count_and_log");
ros::NodeHandle nh;
ros::Rate.rate(10);
for(int i=1;ros::ok();i++){
ROS_DEBUG_STREAM("Counted?to?"<<i);
if((i%3)==0){
ROS_INFO_STREAM(I<<"?is?divisible?by?3.");
}
if((i%5)==0){
ROS_INFO_STREAM(I<<大專欄  ROS中的日志(log)消息"string">"?is?divisible?by?5.");
}
if((i%10)==0){
ROS_INFO_STREAM(I<<"?is?divisible?by?10.");
}
if((i%20)==0){
ROS_INFO_STREAM(I<<"?is?divisible?by?20.");
}
rate.sleep();
}
}

編譯、執行之后結果如下:

3

生成一次性日志消息

ROS 提供了可以僅僅生成一次日志消息的宏:

1
2
3
4
5
ROS_DEBUG_STREAM_ONCE(message);  
ROS_INFO_STREAM_ONCE (message);
ROS_WARN_STREAM_ONCE (message);
ROS_ERROR_STREAM_ONCE (message);
ROS_FATAL_STREAM_ONCE (message);

將上述 C++ 進程中的 log 命令替換一下,得到如下的執行結果:

4

可以看到每個日志只生成了一次。

生成頻率受控的日志消息

1
2
3
4
5
ROS_DEBUG_STREAM_THROTTLE(interval, message);  
ROS_INFO_STREAM_THROTTLE(interval, message);
ROS_WARN_STREAM_THROTTLE(interval, message);
ROS_ERROR_STREAM_THROTTLE(interval, messge);
ROS_FATAL_STREAM_THROTTLE(interval, message);

參數 interval 是 double 型,表示相鄰日志消息出現的最小時間間隔,以秒為單位。得到如下的執行結果:

5

查看日志消息

日志消息有三個不同的輸出目的地,包括屏幕、rosout topic、log 文檔。其中發布到 rosout topic 的 msg 類型是 rosgraph_msgs/Log。除了 topic echo,還可以通過 rqt_console 查看日志消息:

2

啟用和禁用日志消息

ROS 默認只處理 INFO 或者更高級別消息,DEBUG 級別的消息會被忽略。可以通過命令行設置顯示的日志級別:
rosservice call /node-name/set_logger_level package-name level

其中:

  • set_logger_level服務由各個節點自動提供;
  • node-name 期望設置日志級別的節點名稱;
  • package-name 擁有這個節點的 package 名稱;
  • level 是五個級別中的一個。

另外也可以通過圖形接口設置日志級別:
rqt_logger_level

6

圖中列出了節點列表、日志記錄器列表、日志級別列表。在圖中操作與 rosservice 命令的效果一致。
另外,也可以在 C++ 進程中設置日志級別。ROS node 改變自身日志級別最直接的方式是使用 log4cxx 提供的接口:

1
2
3
4
#include <log4cxx/logger.h>
log4cxx::Logger::getLogger(ROSCONSOLE_DEFAULT_NAME)->setLevel(
ros::console::g_level_lookup[ros::console::levels::Debug]);
ros::console::notifyLoggerLevelsChanged();

其中 Debug 可以替換為 Info、Warn、Error、Fatal。

后記

對於大型ROS項目的調試必須要利用到日志系統,所有成熟的框架都為開發者提供了代碼進程的調試工具,學會這些工具能夠很大程度上幫助我們少走彎路節省時間,所以我們要能夠利用這些輔助工具來作為開發過程中的左膀右臂,達到事半功倍的效果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM