日志记录
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);
node.get_logger().debug('My log message %d' % (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);
num = 4
node.get_logger().info(f'My log message {num}', once=True)
除第一次之外的所有时间都记录
以下代码将在严重程度为“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);
num = 4
node.get_logger().warning('My log message {0}'.format(num), skip_first=True)
日志记录已限制
以下代码将从 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);
num = 4
node.get_logger().error(f'My log message {num}', throttle_duration_sec=1)
除第一次之外,日志记录均受到限制
以下代码将从 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);
num = 4
node.get_logger().debug(f'My log message {num}', skip_first=True, throttle_duration_sec=1.0)
日志记录演示
在此 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
export ROS_LOG_DIR=~/my_logs
ros2 run logging_demo logging_demo_main
set "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
export ROS_HOME=~/my_ros_home
ros2 run logging_demo logging_demo_main
set "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
export RCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"
ros2 run logging_demo logging_demo_main
set "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
export RCUTILS_COLORIZED_OUTPUT=0 # 1 for forcing it
ros2 run logging_demo logging_demo_main
set "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
export RCUTILS_LOGGING_USE_STDOUT=1
set "RCUTILS_LOGGING_USE_STDOUT=1"
行缓冲控制台输出
默认情况下,所有日志输出均未缓冲。 您可以通过将“RCUTILS_LOGGING_BUFFERED_STREAM”环境变量设置为 1 来强制缓冲。 例如:
export RCUTILS_LOGGING_BUFFERED_STREAM=1
export RCUTILS_LOGGING_BUFFERED_STREAM=1
set "RCUTILS_LOGGING_BUFFERED_STREAM=1"
Then run:
ros2 run logging_demo logging_demo_main