1. ROS2日志系统概述:日志级别、日志格式、日志存储位置

做自动驾驶系统这些年,我调试过不少奇奇怪怪的问题。说实话,日志系统是我最依赖的工具之一。没有它,很多bug根本无从下手。ROS2的日志系统比ROS1强了不少,今天我们就来好好聊聊。

1.1 日志级别:从DEBUG到FATAL

ROS2定义了5个日志级别。嗯,其实严格来说是6个,但有个特殊的我们后面再说。先看这张图:

ROS2日志级别金字塔 DEBUG (调试信息) INFO (普通信息) WARN (警告) ERROR (错误) FATAL (致命错误) 严重程度递增 →

每个级别都有明确的用途。我个人习惯这样用:

级别 含义 我常用的场景
DEBUG 调试信息 传感器原始数据、中间变量值
INFO 普通信息 节点启动成功、参数加载完成
WARN 警告 传感器数据偶尔丢失、参数超出推荐范围
ERROR 错误 CAN总线通信失败、TF树断裂
FATAL 致命错误 内存耗尽、核心算法崩溃
💡 小技巧: 调试阶段把日志级别设成DEBUG,上线前改成INFO或WARN。我在项目里吃过亏——DEBUG日志太多,导致系统响应变慢。

1.2 日志格式:一眼看懂关键信息

ROS2的日志格式其实挺讲究的。你看这条日志:

[INFO] [1700000000.123456789] [my_autonomous_car]: Lidar node started successfully.

拆开来看,它包含三个部分:

  • 日志级别:用方括号括起来,比如 [INFO]
  • 时间戳:秒.纳秒 格式,精确到纳秒级别
  • 节点名称:告诉你是哪个节点发的
  • 消息内容:冒号后面的就是具体信息

你想想看,在自动驾驶系统里,时间精度有多重要?我曾经排查过一个传感器时间不同步的问题,就是靠日志里的纳秒级时间戳找到的。嗯,这个后面会细讲。

🔑 关键点: 日志格式可以通过环境变量自定义。比如 RCUTILS_CONSOLE_OUTPUT_FORMAT 可以调整显示顺序。

1.3 日志存储位置:文件都去哪了?

ROS2的日志默认存在 ~/.ros/log 目录下。但说实话,这个位置在生产环境里不太够用。我一般会改到专门的日志分区。

来看一下典型的日志目录结构:

~/.ros/log/
├── latest -> /home/user/.ros/log/2024-01-15-10-30-00-123456
├── 2024-01-15-10-30-00-123456/
│   ├── node_1.log
│   ├── node_2.log
│   └── ...
└── 2024-01-15-11-00-00-654321/
    ├── node_1.log
    └── ...

这里有个很贴心的设计:latest 是个软链接,永远指向最近一次运行的日志目录。我在调试时经常用这个,省得翻目录。

⚠️ 注意: 日志文件会不断增长。我曾经遇到过磁盘写满导致系统崩溃的情况。建议设置日志轮转,或者挂载单独的日志分区。

1.4 如何设置日志级别?

有两种方式。第一种是代码里设置:

// C++ 示例
rclcpp::Logger logger = rclcpp::get_logger("my_node");
rclcpp::set_logger_level(logger, rclcpp::LoggerLevel::Debug);

// Python 示例
import rclpy
logger = rclpy.logging.get_logger('my_node')
logger.set_level(rclpy.logging.LoggingSeverity.DEBUG)

第二种是通过命令行:

ros2 run my_package my_node --ros-args --log-level debug

我个人更推荐第二种。为什么?因为不用改代码,上线时直接改成 --log-level info 就行。你想想看,改代码还要重新编译,多麻烦。

1.5 避坑指南

🛠️ 我曾经踩过的坑:
  • DEBUG日志里打印了敏感数据(比如GPS坐标),结果日志文件被其他人看到了。建议生产环境关掉DEBUG。
  • 日志文件没有轮转,导致一个文件几十GB。用 logrotate 工具可以解决。
  • 多个节点写同一个日志文件,导致内容交错。ROS2默认每个节点一个文件,这个设计很合理。

好了,关于ROS2日志系统的基本概念就这些。记住一句话:日志是你的第一道防线。遇到问题先看日志,别急着改代码。这个习惯能帮你省下大量时间。

可可精品资料库