【ROS2】概念:中级-日志和记录器配置

 目录

  •  概述

  •  严重程度

  •  API 接口

  •  配置

    •  环境变量

    •  节点创建

  • 日志子系统设计

    • rcutils

    • rcl_logging_spdlog

    • rcl

    • rclcpp

    • rclpy

  •  记录使用情况

 概述 

ROS 2 中的日志子系统旨在将日志消息传递到各种目标包括:

  • 到控制台(如果已连接)

  • 将文件记录到磁盘(如果本地存储可用)

  • 到 ROS 2 网络上的 /rosout 主题

默认情况下,ROS 2 节点中的日志消息将输出到控制台(在 stderr 上)、磁盘上的日志文件以及 ROS 2 网络上的 /rosout 主题。所有目标都可以在每个节点的基础上单独启用或禁用。

本文档的其余部分将介绍日志子系统背后的一些想法。

 严重级别 

日志消息具有与之关联的严重性级别: DEBUG 、 INFO 、 WARN 、 ERROR 或 FATAL ,按升序排列。

记录器将只处理严重性等于或高于为记录器选择的指定级别的日志消息

每个节点都有一个与之关联的记录器,该记录器会自动包含节点的名称和命名空间。如果节点的名称被外部重新映射为源代码中定义的名称以外的其他名称,则会反映在记录器名称中。还可以创建使用特定名称的非节点记录器。

记录器名称表示一个层次结构。如果名为“abc.def”的记录器的级别未设置,它将推迟到其父级“abc”的级别,如果该级别也未设置,将使用默认记录器级别。当更改记录器“abc”的级别时,所有后代(例如“abc.def”,“abc.ghi.jkl”)的级别将受到影响,除非它们的级别已被明确设置。

 API 接口 

这些是 ROS 2 日志基础设施的最终用户应该使用的 API,按客户端库分开。

C++:

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL} - 每次命中此行时输出给定的 printf 样式消息

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_ONCE - 仅在第一次命中此行时输出给定的 printf 样式消息

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_EXPRESSION - 仅在给定表达式为真时输出给定的 printf 样式消息

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_FUNCTION - 仅当给定函数返回 true 时才输出给定的 printf 样式消息

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_SKIPFIRST - 输出给定的 printf 样式消息,除了第一次命中此行以外的所有时间

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_THROTTLE - 以整数毫秒为单位输出给定的 printf 样式消息,不超过给定的速率

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_SKIPFIRST_THROTTLE - 以整数毫秒为单位输出给定的 printf 样式消息,但跳过第一个

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM - 每次命中此行时输出给定的 C++流式消息

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_ONCE - 仅在第一次命中此行时输出给定的 C++流样式消息

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_EXPRESSION - 仅当给定表达式为真时输出给定的 C++ 流样式消息

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_FUNCTION - 仅当给定函数返回 true 时输出给定的 C++ 流样式消息

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_SKIPFIRST - 输出给定的 C++ 流式消息,除了第一次命中该行以外

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_THROTTLE - 以整数毫秒为单位输出给定速率的 C++流式消息

  • RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_SKIPFIRST_THROTTLE - 以整数毫秒为单位输出给定的 C++流式消息,但跳过第一个

上述每个 API 都将 rclcpp::Logger 对象作为第一个参数。这可以通过调用 node->get_logger() (推荐)从节点 API 中提取,或者通过构造一个独立的 rclcpp::Logger 对象来实现。

  • rcutils_logging_set_logger_level - 将特定记录器名称的日志级别设置为给定的严重级别

  • rcutils_logging_get_logger_effective_level - 给定一个记录器名称,返回记录器级别(可能未设置)

Python:

  • logger.{debug,info,warning,error,fatal} - 将给定的 Python 字符串输出到日志基础设施。调用接受以下关键字参数来控制行为:

    • throttle_duration_sec - 如果不是 None,则节流间隔的持续时间(以浮点秒为单位)

    • skip_first - 如果为 True,则每次命中此行时输出消息,但第一次除外

    • once - 如果为真,则仅在第一次命中此行时输出消息

  • rclpy.logging.set_logger_level - 将特定记录器名称的日志级别设置为给定的严重级别

  • rclpy.logging.get_logger_effective_level - 给定一个记录器名称,返回记录器级别(可能未设置)

 配置 

由于 rclcpp 和 rclpy 使用相同的底层日志记录基础设施,因此配置选项相同。

 环境变量 

以下环境变量控制 ROS 2 记录器的某些方面。对于每个环境设置,请注意这是一个进程范围的设置,因此它适用于该进程中的所有节点。

  • ROS_LOG_DIR - 控制用于将日志消息写入磁盘的日志目录(如果启用)。如果非空,则使用此变量中指定的确切目录。如果为空,则使用 ROS_HOME 环境变量的内容构造 $ROS_HOME/.log 形式的路径。在所有情况下, ~ 字符将扩展到用户的 HOME 目录。

  • ROS_HOME - 控制用于各种 ROS 文件的主目录,包括日志记录和配置文件。在日志记录的上下文中,该变量用于构建日志文件目录的路径。如果非空,则使用该变量的内容作为 ROS_HOME 路径。在所有情况下, ~ 字符将扩展到用户的 HOME 目录。

  • RCUTILS_LOGGING_USE_STDOUT - 控制流输出消息的去向。如果未设置或为 0,则使用 stderr。如果为 1,则使用 stdout。

  • RCUTILS_LOGGING_BUFFERED_STREAM - 控制日志流(在 RCUTILS_LOGGING_USE_STDOUT 中配置)是否应为行缓冲或非缓冲。如果未设置此项,请使用流的默认值(通常为 stdout 的行缓冲和 stderr 的非缓冲)。如果此值为 0,则强制流为非缓冲。如果此值为 1,则强制流为行缓冲。

  • RCUTILS_COLORIZED_OUTPUT - 控制输出消息时是否使用颜色。如果未设置,则根据平台和控制台是否为 TTY 自动确定。如果为 0,则强制禁用输出颜色。如果为 1,则强制启用输出颜色。

  • RCUTILS_CONSOLE_OUTPUT_FORMAT - 控制每个日志消息输出的字段。可用的字段有:

    如果没有给出格式,则使用默认的 [{severity}] [{time}] [{name}]: {message} 。

    • {severity} - 严重程度。

    • {name} - 记录器的名称(可能为空)。

    • {message} - 日志消息(可能为空)。

    • {function_name} - 此函数被调用时的名称(可能为空)。

    • {file_name} - 此文件名是从中调用的(可能为空)。

    • {time} - 自纪元以来的时间(以秒为单位)。

    • {time_as_nanoseconds} - 自纪元以来的时间(纳秒)。

    • {date_time_with_ms} - ISO 格式的时间,例如 2024-06-11 09:29:19.304

    • {line_number} - 此被调用的行号(可能为空)。

RCUTILS_CONSOLE_OUTPUT_FORMAT 还支持以下转义字符语法。

 转义字符语法

 字符表示

\a

 警报

\b

 退格键

\n

 新行

\r

 回车

\t

 水平制表符

 节点创建 

在初始化 ROS 2 节点时,可以通过节点选项控制行为的某些方面。由于这些是每个节点的选项,即使节点组合成一个单一的进程,它们也可以为不同的节点设置不同的选项。

  • log_levels - 用于此特定节点内组件的日志级别。可以使用以下命令进行设置: ros2 run demo_nodes_cpp talker --ros-args --log-level talker:=DEBUG

  • external_log_config_file - 用于配置后端记录器的外部文件。如果为 NULL,将使用默认配置。请注意,此文件的格式是特定于后端的(目前尚未为 spdlog 的默认后端记录器实现)。可以通过以下方式设置: ros2 run demo_nodes_cpp talker --ros-args --log-config-file log-config.txt

  • log_stdout_disabled - 是否禁用将日志消息写入控制台。可以通过以下方式完成: ros2 run demo_nodes_cpp talker --ros-args --disable-stdout-logs

  • log_rosout_disabled - 是否禁用将日志消息写出到 /rosout 。这可以显著节省网络带宽,但外部观察者将无法监控日志记录。可以通过以下方式完成: ros2 run demo_nodes_cpp talker --ros-args --disable-rosout-logs

  • log_ext_lib_disabled - 是否完全禁用外部记录器的使用。这在某些情况下可能更快,但意味着日志不会写入磁盘。可以通过以下方式完成: ros2 run demo_nodes_cpp talker --ros-args --disable-external-lib-logs

日志子系统设计 

下图显示了日志子系统的五个主要部分及其交互方式。

b9dee17349cf101c0da90d3a0175e9ec.png

rcutils

rcutils 具有一个日志实现,可以根据某种格式格式化日志消息(见上文 Configuration ),并将这些日志消息输出到控制台。 rcutils 实现了一个完整的日志解决方案,但允许更高级别的组件以依赖注入模型插入到日志基础设施中。当我们在下面讨论 rcl 层时,这一点将变得更加明显。

请注意,这是一个每个进程的日志记录实现,因此在此级别配置的任何内容都将影响整个进程,而不仅仅是单个节点。

rcl_logging_spdlog

rcl_logging_spdlog 实现了 rcl_logging_interface API,从而为 rcl 层提供外部日志服务。特别是, rcl_logging_spdlog 实现获取格式化的日志消息,并使用 spdlog 库将它们写入磁盘上的日志文件,通常在 ~/.ros/log 内(尽管这是可配置的;请参阅上面的 Configuration )。

rcl

rcl 中的日志子系统使用 rcutils 和 rcl_logging_spdlog 提供大部分 ROS 2 日志服务。当日志消息进入时, rcl 决定将它们发送到哪里。日志消息可以传递到三个主要位置;单个节点可以启用它们的任意组合:

  • 通过 rcutils 层到控制台

  • 通过 rcl_logging_spdlog 层到磁盘

  • 通过 RMW 层到 ROS 2 网络上的 /rosout 主题

rclcpp

这是主要的 ROS 2 C++ API,它位于 rcl API 之上。在日志记录的上下文中, rclcpp 提供了 RCLCPP_ 日志宏;请参阅上面的 APIs 以获取完整列表。当其中一个 RCLCPP_ 宏运行时,它会根据宏的严重级别检查节点的当前严重级别。如果宏的严重级别大于或等于节点的严重级别,则消息将被格式化并输出到当前配置的所有位置。请注意, rclcpp 使用全局互斥锁进行日志调用,因此同一进程中的所有日志调用最终都是单线程的。

rclpy

这是主要的 ROS 2 Python API,它位于 rcl API 之上。在日志记录的上下文中, rclpy 提供了 logger.debug 风格的函数;请参阅上面的 APIs 以获取完整列表。当运行其中一个 logger.debug 函数时,它会根据宏的严重性级别检查节点的当前严重性级别。如果宏的严重性级别大于或等于节点的严重性级别,则消息将被格式化并输出到当前配置的所有位置。

记录使用情况 

C++:

  • 请参阅 rclcpp 日志演示 https://github.com/ros2/demos/tree/jazzy/logging_demo 以获取一些简单的示例。

  • 请参阅日志演示 https://docs.ros.org/en/jazzy/Tutorials/Demos/Logging-and-logger-configuration.html 以了解示例用法。

Python:

查看 rclpy 示例 https://github.com/ros2/examples/blob/jazzy/rclpy/services/minimal_client/examples_rclpy_minimal_client/client.py 以了解节点日志记录器的用法。

查看 rclpy 测试 https://github.com/ros2/rclpy/blob/jazzy/rclpy/test/test_logging.py 以了解关键字参数(例如 skip_first、once)的用法。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这是一个关于ROS Noetic软件包依赖关系的问题。其中,下列软件包的依赖关系尚不足够满足要求,无法安装: ros-noetic-desktop-full: 依赖于 ros-noetic-desktop,但它不会被安装。 依赖于 ros-noetic-perception,但它不会被安装。 依赖于 ros-noetic-simulators,但它不会被安装。 依赖于 ros-noetic-urdf-sim-tu,但它不会被安装。 ### 回答2: 这个错误提示是说明在安装 ros-noetic-desktop-full 软件包时,发现它需要依赖一些其他的软件包,但是这些软件包未被安装。其中,ros-noetic-desktop、ros-noetic-perception、ros-noetic-simulators 和 ros-noetic-urdf-sim-tu 是四个未满足依赖关系的软件包。 这个错误提示一般是由于软件源的问题所导致的。在安装软件包时,系统会从软件源中查找该软件包以及它所需的依赖关系。如果软件源中不存在某个软件包的依赖关系,则会提示这个错误信息。 要解决这个问题,可以尝试以下几个方法: 1. 更新软件源:可通过修改软件源配置文件或使用软件源管理工具来更新软件源。更新后再次尝试安装软件包,看是否能够解决依赖关系问题。 2. 手动安装依赖关系:如果更新软件源后仍然无法解决依赖关系问题,可以尝试手动安装依赖关系。按照依赖关系的提示,逐个安装这四个软件包。安装完成后再次尝试安装 ros-noetic-desktop-full 软件包,看是否能够正常安装。 3. 使用 aptitude 命令安装:aptitude 命令可以自动处理依赖关系,可能会更好地解决这个问题。可以通过运行以下命令安装 ros-noetic-desktop-full 软件包: sudo aptitude install ros-noetic-desktop-full 以上是我的回答,希望能对你有所帮助。如果你还有其他问题,请随时回复。 ### 回答3: 这个问题意味着在安装 ros-noetic-desktop-full 软件包时,计算机无法满足所有需要的依赖关系。这些依赖关系包括 ros-noetic-desktop、ros-noetic-perception、ros-noetic-simulators 和 ros-noetic-urdf-sim-tu。 在解决这个问题之前,我们需要了解什么是依赖关系。在软件工程中,依赖关系指的是一个软件包需要另一个软件包才能正常运行的情况。例如,在 ROS 中,ros-noetic-desktop-full 需要依赖其他的软件包才能提供完整的功能。 为了解决这个问题,我们可以使用以下方法: 1. 更新软件包源列表。我们可以更新软件包源列表,这有助于计算机查找所需的软件包。在 Ubuntu 系统中,我们可以使用以下命令更新软件包源列表:sudo apt-get update。 2. 安装依赖关系。我们可以尝试单独安装缺失的依赖关系。在 ROS 中,我们可以使用以下命令安装缺失的软件包:sudo apt-get install ros-noetic-desktop ros-noetic-perception ros-noetic-simulators ros-noetic-urdf-sim-tu。 3. 检查软件包仓库。某些情况下,软件包源可能已经过时或不再受支持。我们可以检查软件包仓库,查看软件包是否可用。在 Ubuntu 系统中,我们可以使用以下命令查看软件包仓库:apt-cache search ros-noetic-desktop-full。 总之,无法满足依赖关系的问题是常见的,在解决这个问题之前,我们需要了解依赖关系的概念,并掌握一些解决方法。在 ROS 中,我们可以使用更新软件包源列表、安装依赖关系和检查软件包仓库等方法解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值