ROS 【log】的使用

转载链接

https://blog.csdn.net/lemonxiaoxiao/article/details/122101380

参考:

  1. ROS学习之日志消息
  2. ROS中的日志(log)消息
  3. ROS日志级别控制
ROS日志(log)系统:

在这里插入图片描述
通过显示进程的运行状态是好的习惯,但需要确定这样做不会影响到软件的运行效率和输出的清晰度。

ROS 日志 (log) 系统的功能是让程序生成一些日志消息,显示在屏幕上、发送到特定 topic 或者储存在特定 log 文件中,以方便调试、记录、报警等。

下面简单介绍如何生成和查看日志消息。

1. 日志消息

ROS中,有一个特殊的话题叫作/rosout,它承载着所有节点的所有日志消息/rosout消息的类型是rosgraph_msgs/Log
在这里插入图片描述
rosgraph_msgs/Log消息用来让各个节点发布日志消息,这样一来就能让网络上的任何一个人都看到。

可以认为/rosout是一个加强版的print():它不是向终端输出字符串,而是可以将字符串和元数据放到一个消息中,发送给网络上的任何一个人。

ROS节点应该向/rosout发布日志消息,这样一来这些消息就能被所有人看到。

rospy客户端提供了多个函数来发布rosgraph_msgs/Log消息:

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

 
 
  • 1
  • 2

rospy.logwarn()函数实现了三件事情:

  • 输出一个格式化的字符串到终端;
  • 输出更详细的警告到日志文档中,这个文档一般在~/.ros/log中;
  • 构建并发布一条消息到/rosout话题,其中包括警告以及节点元数据;
2. 日志等级

ROS有5个日志记录标准级别,这些名称是输出信息的函数的一部分,他们遵循以下语法:

ROS_<LEVEL>[_<OTHER>]

 
 
  • 1

日志消息按照严重性由低到高可以分为 5 级:

  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL

每个消息级别用于不同的目的:

  • DEBUG(调试):只在调试时用,此消息不出现在部署的应用中,仅用于测试;
  • INFO(信息):标准消息,说明重要步骤或节点所正在执行的操作;
  • WARN(警告):提醒一些错误、缺失或者不正常,但进程仍能运行;
  • ERROR(错误):提示错误,尽管节点仍可在这里恢复,但对节点的行为设置了一定期望;
  • FATAR(致命):这些消息通常表示阻止节点继续运行的错误。
    在这里插入图片描述

在这里插入图片描述

3. 生成基本的日志消息

由五个 C++ 宏来产生日志消息,每个宏对应一个级别:

ROS_DEBUG_STREAM(message);  
ROS_INFO_STREAM(message);  
ROS_WARN_STREAM(message);  
ROS_ERROR_STREAM(message);  
ROS_FATAL_STREAM(message);

 
 
  • 1
  • 2
  • 3
  • 4
  • 5

其实这个宏的定义就把格式输出包含到里面,其中各个宏的参数message可以处理C++中标准输出流(ostream)中的各种表达式,比如:std::cout。这包括在 int 或者 double 这种基本数据类型上使用插入操作符(<<),以及已经重载这个操作符的复合数据类型。

我们经常也能看到不带_STREAM的消息,它们的区别如下:

ROS_INFO(“INFO message %d”,k);  // 相当于c中的printf;
ROS_INFO_STREAM ( "INFO message." << k);  // 相当于c++中的cout;

 
 
  • 1
  • 2

编写如下 C++ 进程:

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<<"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();
   }
}

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

编译、执行之后结果如下:
在这里插入图片描述

4. 生成一次性日志消息

生成单次消息,其实就是在程序中加入了一个静态局部变量来检测,进入一次后就把变量改为false则下次检测到后则不输出该信息。

// Don't do this directly. Use ROS_..._STREAM_ONCE instead.
{
	static bool first_time = true ;
	if (first_time) {
		ROS_INFO_STREAM( "Here's some important information"
		<<" that will only appear once.");
		first_time = false;
	}
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

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);

 
 
  • 1
  • 2
  • 3
  • 4
  • 5

将上述 C++ 进程中的 log 命令替换一下,得到如下的执行结果:
在这里插入图片描述
可以看到每个日志只生成了一次。

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);

 
 
  • 1
  • 2
  • 3
  • 4
  • 5

参数 intervaldouble 型,表示相邻日志消息出现的最小时间间隔,以秒为单位ROS_..._STREAM_THROTTLE宏的每一个实例在第一次执行时都会生成日志消息(与不带_THROTTLE 后缀版本宏的日志消息相同),随后的执行都会被忽略,直到经过了指定的时间间隔。每个宏的实例的时间被单独跟踪,方法是使用一个局部静态变量来存储上一次生成日志的时间。

得到如下的执行结果:
在这里插入图片描述

6. 查看日志消息

日志消息有三个不同的输出目的地,包括屏幕、rosout topiclog 文档。其中发布到 rosout topicmsg 类型是 rosgraph_msgs/Log

我们可以通过rostopic echo /rosout 来查看消息,也可以通过一个节点来订阅日志话题,还可以通过指令rqt_console来通过图形界面来显示日志消息:
在这里插入图片描述

7. 日志文件

作为/rosout话题回调函数的一部分,rosout节点可以将日志消息作为一行写入到一个日志文件,文件名类似于:~/.ros/log/run_id/rosout.log

有时日志过多时需要我们清除系统日志,利用指令:

rosclean check

 
 
  • 1

如果日志正在消耗过多的硬盘空间,可以通过下面的命令删除所有已经存在的日志:

rosclean purge

 
 
  • 1
8. 设置日志级别

ROS 默认只处理 INFO 或者更高级别消息,DEBUG 级别的消息会被忽略

  1. terminal终端界面配置:
rosservice call /node-name/set_logger_level package-name level

 
 
  • 1

其中:

  • node-name 期望设置日志级别的节点名称;
  • set_logger_level服务由各个节点自动提供;
  • package-name 拥有这个节点的 package 名称;
  • level 是五个级别中的一个;

!!!注意:由于这条命令直接与节点进行交互,我们不能在节点启动之前使用它。如果一切正常,这个对 rosservice 的调用将输出一个空行。

  1. rqt界面配置:
rosrun rqt_logger_level rqt_logger_level

 
 
  • 1
rosrun rqt_console rqt_console

 
 
  • 1

在这里插入图片描述
图中列出了节点列表、日志记录器列表、日志级别列表。在图中操作与 rosservice 命令的效果一致。

  1. 代码中配置:

ROS node 改变自身日志级别最直接的方式是使用 log4cxx 提供的接口:

#include <log4cxx/logger.h>

log4cxx::Logger::getLogger(ROSCONSOLE_DEFAULT_NAME)->setLevel(
ros::console::g_level_lookup[ros::console::levels::Debug]);
ros::console::notifyLoggerLevelsChanged();

  • 1
  • 2
  • 3
  • 4
  • 5

其中 Debug 可以替换为 InfoWarnErrorFatal

或者

#include <ros/console.h>

if( ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug) ) {
ros::console::notifyLoggerLevelsChanged();
}

  • 1
  • 2
  • 3
  • 4
  • 5
  1. config文件中配置:
    可以在launch文件里指定一个config 文件, 在这个 config 文件里制定哪些pkg输出什么级别的log

示例rosconsole.config配置如下:

# Set the default ros output to warning and higher
log4j.logger.ros=WARN

Override my_package to output everything

log4j.logger.ros.move_base=DEBUG # WARN INFO …

  • 1
  • 2
  • 3
  • 4
  • 5

launch文件里添加如下配置:

  <env name="ROSCONSOLE_CONFIG_FILE"
       value="_myfolder_path_/rosconsole.config"/>   //_myfolder_path_是rosconsole.config 所在的文件夹路径

 
 
  • 1
  • 2

可参考:ROS中log4j的学习记录

后记

对于大型ROS项目的调试必须要利用到日志系统,所有成熟的框架都为开发者提供了代码进程的调试工具,学会这些工具能够很大程度上帮助我们少走弯路节省时间,所以我们要能够利用这些辅助工具来作为开发过程中的左膀右臂,达到事半功倍的效果。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
如果ROS的日志文件中不显示中文,可以考虑修改ROS的日志配置文件。以下是一种可能的解决方案: 1. 打开ROS的日志配置文件,一般位于`~/.ros/console_bridge.config`路径下。 2. 在配置文件中添加以下内容: ``` logger rosout { # 日志级别,可以根据实际情况进行修改 level info # 输出格式,其中%time表示时间,%logger表示节点名称,%level表示日志级别,%msg表示日志内容 format "[%time] [%logger] [%level]: %msg" # 输出到终端的颜色,可以根据实际情况进行修改 output_handlers console rosconsole # 输出到文件的路径,可以根据实际情况进行修改 filename /home/user/ros/logs/rosout.log file_format log append true output_handlers file } logger rosout_agg { # 日志级别,可以根据实际情况进行修改 level info # 输出格式,其中%time表示时间,%logger表示节点名称,%level表示日志级别,%msg表示日志内容 format "[%time] [%logger] [%level]: %msg" # 输出到终端的颜色,可以根据实际情况进行修改 output_handlers console rosconsole # 输出到文件的路径,可以根据实际情况进行修改 filename /home/user/ros/logs/rosout_agg.log file_format log append true output_handlers file } ``` 3. 保存配置文件并重启ROS,即可在日志文件中显示中文。需要注意的是,如果节点名称或日志内容中包含中文,需要确保字符编码一致,否则仍可能出现乱码的问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值