【ROS读书笔记】---4. 日志消息


本章将学习如何生成和查看日志消息。
接上回,这两天断更学习笔记,本人电脑以及很多资料放在实验室了,因为疫情突然封校,全体隔离,后借了电脑还原资料续更,读书是 不能停止的。突破寒冬的唯一捷径就是不断学习与其 抱怨身处黑暗,不如提灯前行。

介绍

在之前的章节中,我们经常看到“ROS_INFO_STREAM”的字样,ROS日志的核心思想是使程序生成一些简短的文本字符流,分为五个不同的严重级别/严重性/级别等。这些级别有:

  • DEBUG
    频繁出现,只要程序正常工作便不必在意。
  • INFO
    较轻
  • WARN
    中等
  • ERROR
    较严重
  • FATAL
    很少出现,很重要,表示程序中存在的一些问题导致无法继续运行。

划分等级的意图是提供一种区分和管理日志消息的全局
方法。生成一个fatal程序并不会终止你的程序,生成一个debug并不会调试你的程序。

示例程序

一个简单的例子如下:

#include <ros/ros.h>

 int main (int argc,char **argv) 
 {
		 ros::init(argc, argv, "count_and_log");
		 ros::NodeHandle nh;
		
		 ros::Rate rate (10);
		 for(inti=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_WARN_STREAM(i<<"?is?divisible?by?5.");
		 }
		 if((i%10)==0)
		 {
		 		ROS_ERROR_STREAM(i<<"?is?divisible?by?10.");
		 }
		 if((i%20)==0)
		 {
		 		ROS_FATAL_STREAM(i<<"?is?divisible?by?20.");
		 }
		 rate.sleep();
	}
 }

将会生成如下所示的代码:

[INFO] [1375889196.165921375]: 3 is divisible by 3.
[WARN] [1375889196.365852904]: 5 is divisible by 5.
[INFO] [1375889196.465844839]: 6 is divisible by 3.
[INFO] [1375889196.765849224]: 9 is divisible by 3.
[WARN] [1375889196.865985094]: 10 is divisible by 5.
[ERROR] [1375889196.866608041]: 10 is divisible by 10.
[INFO] [1375889197.065870949]: 12 is divisible by 3.
[INFO] [1375889197.365847834]: 15 is divisible by 3
  • 可以明显地看到:这个输出不包含任何debug
    级别的消息,因为最小的级别是info。

生成日志消息

一般生成日志消息:

ROS_DEBUG_STREAM(message);
ROS_INFO_STREAM(message);
ROS_WARN_STREAM(message);
ROS_ERROR_STREAM(message);
ROS_FATAL_STREAM(message);
  • message是C++中的输出流,比如std::cout等,可以使用插入运算符(<<)。

生成print风格的代码的日志消息:

ROS_INFO(“Position=(%0.2f, %0.2f) direction=%0.2f, msg.x, msg.y, msg.theta);
  • 由于是以行为单位的,因此没必要使用endl这种终止符。

生成一次性的日志消息:

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);
  • 使用静态变量来使消息只生成一次(无视循环)。

生成频率受控的日志消息:

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类型的,以秒为单位,这是相邻日志消息出现的最小时间间隔。
  • 如果用这种方式实现之前代码(第一个代码)的功能的话,它们的差距如下:
  • 生成频率可控的日志消息,采用的是轮询机制而不是休眠机制。而这种轮询机制在实际程序中通常是一个糟糕的思路。

查看日志消息

实际上日志消息可以有三个不同的目的地:

  • 控制台输出
  • rosout话题的消息
  • 也可以写入日志消息中
控制台

默认,DEBUG和INFO消息被打印至标准输出(standard output),而WARN、ERROR和FATAL消息将被送至标准错误(standard output)。

而实际上它们的区别是无关紧要的。可以通过文件重定向技术进行重定向。以下是三种重定向技术:
command > file
command &> file
stdbuf -oL command &> file


  • 格式化控制台消息
[${severity}] [${time}]: ${message}

roslaunch工具默认不会将日志消息导入输出流,为了查看,必须显式地使用output="screen"属性。


rosout

每一个日志消息都被发布到/rosout上,消息类型是rosgraph_msgs/Log。下图是消息的各个域:

1 byte DEBUG=1
2 byte INFO=2
3 byte WARN=4
4 byte ERROR=8
5 byte FATAL=16
6 std_msgs/Header header
7 uint32 seq
8 time stamp
9 string frame_id
10 byte level
11 string name
12 string msg
13 string file
14 string function
15 uint32 line
16 string [] topics

可以通过以下消息查看:

rostopic echo /rosout

也可以通过图形化界面查看(每条消息独占一行):

rqt_console

实际上rqt_console的描述并不完全正确,实际上它订阅的是/rosout_agg,而不是/rosout。后缀_agg表示实际上是被rosout节点输出到/rosout_agg话题上。

日志文件

日志消息还有一个去处就是rosout节点生成的日志文件。文件名类似:

~/.ros/log/run_id/rosout.log

是纯文本文件。
运行标识码(run_id)是一个通用的唯一识别码(UUID),基于计算机的MAC地址和当前时间生成,下边是一个run_id的例子:

57aa1860-d765-11e2-a830-f0def1e189cc

查找运行标识码有如下两种方法:

  • 通过检查 roscore 生成的输出,在靠近输出末端的位置,可以看到与下面内容类似的一行setting /run_id to run_i
  • 通过以下命令向节点管理器询问当前的 run_id rosparam get /run_id由于 run_id 存放在参数服务器上,因此该命令是有效的。

检查日志文件:

rosclean check
  • 日志文件将随着时间累积,ROS并不会采取任何的措施来减小日志文件大小。

删除所有的日志文件:

rosclean purge

启用或停用日志消息

日志级别是提供每个节点日志细节程度的能力。设置日志级别类似于rqt_console中的图纸级别过滤,不同的是,改变日志级别将会组织在源头生成。

通过命令行

伪代码:rosservice call /node-name/set_logger_level ros.package-name leve调用 set_logger_level 服务,该服务由各个节点自动提供。
例:

rosservice call /count_and_log/set_logger_level ros.agitr DEBUG
  • node-name是你期望设置日志级别的节点名称
  • pkg-name是拥有这个节点的功能包的名称
  • level参数是DEBUG、INFO、WARN、ERROR、FATAL中的一个字符串。
通过图形界面
rqt_logger_level
通过C++代码设置日志级别

节点改变自身的日志级别也是可能的。最直接的方式是调用 ROS 来实现日志功能的 log4cxx 提供的接口,代码如下

#include <log4cxx/logger.h>
. . .
log4cxx::Logger::getLogger(ROSCONSOLE_DEFAULT_NAME)->setLevel(
ros::console::g_level_lookup[ros::console::levels::Debug]
);
ros::console::notifyLoggerLevelsChanged();
  • 除了必要的语法理解,这些代码应该很容易识别是将日志级别设置为 DEBUG。Debug 这个标识当然可以替换为 Info、Warn、Error 或者 Fatal

总结

消息对于跟踪和调试复杂ROS 系统的行为是很有用的,特是这些系统拥有大量不同节点时。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值