日志记录

See the logging page for details on available functionality.

在代码中使用日志语句

基本日志记录

以下代码将在“DEBUG”严重性下从 ROS 2 节点输出日志消息:

// printf style
RCLCPP_DEBUG(node->get_logger(), "My log message %d", 4);

// C++ stream style
RCLCPP_DEBUG_STREAM(node->get_logger(), "My log message " << 4);

请注意,在这两种情况下,都不会添加尾随换行符,因为日志记录基础结构会自动添加一个。

仅在第一次记录

以下代码将在严重性为“INFO”的 ROS 2 节点输出日志消息,但仅在第一次命中时输出:

// printf style
RCLCPP_INFO_ONCE(node->get_logger(), "My log message %d", 4);

// C++ stream style
RCLCPP_INFO_STREAM_ONCE(node->get_logger(), "My log message " << 4);

除第一次之外的所有时间都记录

以下代码将在严重程度为“WARN”时从 ROS 2 节点输出日志消息,但不会输出第一次遇到的日志消息:

// printf style
RCLCPP_WARN_SKIPFIRST(node->get_logger(), "My log message %d", 4);

// C++ stream style
RCLCPP_WARN_STREAM_SKIPFIRST(node->get_logger(), "My log message " << 4);

日志记录已限制

以下代码将从 ROS 2 节点以“ERROR”严重性输出一条日志消息,但每秒不超过一次。

指定消息间隔毫秒数的间隔参数应具有整数数据类型,以便可以将其转换为“rcutils_duration_value_t”(“int64_t”):

// printf style
RCLCPP_ERROR_THROTTLE(node->get_logger(), *node->get_clock(), 1000, "My log message %d", 4);

// C++ stream style
RCLCPP_ERROR_STREAM_THROTTLE(node->get_logger(), *node->get_clock(), 1000, "My log message " << 4);

// For now, use the nanoseconds() method to use an existing rclcpp::Duration value, see https://github.com/ros2/rclcpp/issues/1929
RCLCPP_ERROR_STREAM_THROTTLE(node->get_logger(), *node->get_clock(), msg_interval.nanoseconds()/1000000, "My log message " << 4);

除第一次之外,日志记录均受到限制

以下代码将从 ROS 2 节点以“DEBUG”严重性输出一条日志消息,每秒不超过一次,并跳过第一次命中的情况:

// printf style
RCLCPP_DEBUG_SKIPFIRST_THROTTLE(node->get_logger(), *node->get_clock(), 1000, "My log message %d", 4);

RCLCPP_DEBUG_SKIPFIRST_THROTTLE(node->get_logger(), *node->get_clock(), 1000, "My log message " << 4);

日志记录演示

在此 demo, 显示不同类型的日志调用,并在本地和外部配置不同记录器的严重性级别。

使用以下命令启动演示:

ros2 run logging_demo logging_demo_main

随着时间的推移,您将看到具有不同属性的各种日志调用的输出。 首先,您将只看到严重性为“INFO”及以上的日志调用的输出(“WARN”、“ERROR”、“FATAL”)。 请注意,第一条消息只会记录一次,尽管每次迭代都会到达该行,因为这是用于该消息的日志调用的属性。

日志目录配置

可以通过两个环境变量配置日志目录:“ROS_LOG_DIR”和“ROS_HOME”。 逻辑如下:

  • 如果“ROS_LOG_DIR”已设置且不为空,则使用“$ROS_LOG_DIR”。

  • 否则,使用“$ROS_HOME/log”,如果未设置或为空,则使用“~/.ros”作为“ROS_HOME”。

例如,将日志目录设置为“~/my_logs”:

export ROS_LOG_DIR=~/my_logs
ros2 run logging_demo logging_demo_main

然后,您将在 ~/my_logs/ 下找到日志。

或者,您可以设置 ROS_HOME,日志目录将与其相关 ($ROS_HOME/log)。 ROS_HOME 旨在供任何需要基本目录的内容使用。 请注意,ROS_LOG_DIR 必须未设置或为空。 例如,将 ROS_HOME 设置为 ~/my_ros_home

export ROS_HOME=~/my_ros_home
ros2 run logging_demo logging_demo_main

然后,您将在 ~/my_ros_home/log/ 下找到日志。

记录器级别配置:以编程方式

经过 10 次迭代后,记录器的级别将设置为 DEBUG,这将导致记录其他消息。

其中一些调试消息会导致评估其他函数/表达式,这些函数/表达式之前被跳过,因为未启用 DEBUG 日志调用。 请参阅 the source code 演示中有关所用调用的进一步说明,并参阅 rclcpp 日志记录文档以获取受支持的日志记录调用的完整列表。

记录器级别配置:外部​​

将来,将有一种通用的方法来在运行时对记录器进行外部配置(类似于 rqt_logger_level 在 ROS1 中允许通过远程过程调用配置记录器)。 This concept is not yet officially supported in ROS 2. 演示中有关所用调用的进一步说明,并参阅 rclcpp 日志记录文档以获取受支持的日志记录调用的完整列表。

记录器级别配置:外部​​

将来,将有一种通用的方法来在运行时对记录器进行外部配置(类似于

ros2 service call /config_logger logging_demo/srv/ConfigLogger "{logger_name: 'logger_usage_demo', level: INFO}"

如果您知道其名称,此服务调用将适用于进程中运行的任何记录器。 这包括 ROS 2 核心中的记录器,例如“rcl”(通用客户端库包)。 要为“rcl”启用调试日志记录,请调用:

ros2 service call /config_logger logging_demo/srv/ConfigLogger "{logger_name: 'rcl', level: DEBUG}"

您应该会看到“rcl”的调试输出开始显示。

使用记录器配置组件

响应记录器配置请求的服务器已开发为组件,因此可以将其添加到现有的基于组合的系统中。 例如,如果您使用“容器运行节点 <../Intermediate/Composition>”,则为了能够配置记录器,您只需请求它另外将“logging_demo::LoggerConfig”组件加载到容器中。

例如,如果您想调试“composition::Talker”演示,您可以像往常一样启动 talker:

Shell 1:

ros2 run rclcpp_components component_container

Shell 2:

ros2 component load /ComponentManager composition composition::Talker

然后,当您想要启用调试日志记录时,请使用以下命令加载“LoggerConfig”组件:

Shell 2

ros2 component load /ComponentManager logging_demo logging_demo::LoggerConfig

最后,通过寻址空名记录器将所有未设置的记录器配置为调试严重性。 请注意,已专门配置为使用特定严重性的记录器不会受到此调用的影响。

Shell 2:

ros2 service call /config_logger logging_demo/srv/ConfigLogger "{logger_name: '', level: DEBUG}"

您应该会看到进程中任何先前未设置的记录器的调试输出开始出现,包括来自 ROS 2 核心的记录器。

记录器级别配置:命令行

从 Bouncy ROS 2 版本开始,可以从命令行配置未明确设置严重性的记录器的严重性级别。 重新启动演示,包括以下命令行参数:

ros2 run logging_demo logging_demo_main --ros-args --log-level debug

这会将任何未设置的记录器的默认严重性配置为调试严重性级别。 您应该会看到来自演示本身和 ROS 2 核心的记录器的调试输出。

从 Galactic ROS 2 版本开始,可以从命令行配置单个记录器的严重性级别。 重新启动演示,包括以下命令行参数:

ros2 run logging_demo logging_demo_main --ros-args --log-level logger_usage_demo:=debug

控制台输出格式

如果您想要更详细或更简洁的格式,可以使用 RCUTILS_CONSOLE_OUTPUT_FORMAT 环境变量。 例如,要额外获取日志调用的时间戳和位置,请停止演示并使用环境变量设置重新启动它:

export RCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"
ros2 run logging_demo logging_demo_main

您应该会看到时间戳(以秒为单位)以及每条消息中额外打印的函数名称、文件名和行号。 ``time`` 选项仅在 ROS 2 Bouncy 版本中受支持。

控制台输出着色

默认情况下,当输出针对终端时,它会被着色。 如果您想强制启用或禁用它,您可以使用 RCUTILS_COLORIZED_OUTPUT 环境变量。 例如:

export RCUTILS_COLORIZED_OUTPUT=0  # 1 for forcing it
ros2 run logging_demo logging_demo_main

您应该看到调试、警告、错误和严重日志现在没有彩色。

Note

在 Linux 和 MacOS 中,强制彩色输出意味着如果您将输出重定向到文件,则 ansi 转义颜色代码将出现在该文件上。 在 Windows 中,着色方法依赖于控制台 API。 如果强制执行,您将收到一条新警告,提示着色失败。 默认行为已经检查输出是否为控制台,因此不建议强制着色。

控制台输出的默认流

在 Foxy 及更高版本中,所有调试级别的输出默认转到 stderr。可以通过将“RCUTILS_LOGGING_USE_STDOUT”环境变量设置为“1”来强制所有输出转到 stdout。 例如:

export RCUTILS_LOGGING_USE_STDOUT=1

行缓冲控制台输出

默认情况下,所有日志输出均未缓冲。 您可以通过将“RCUTILS_LOGGING_BUFFERED_STREAM”环境变量设置为 1 来强制缓冲。 例如:

export RCUTILS_LOGGING_BUFFERED_STREAM=1

Then run:

ros2 run logging_demo logging_demo_main