cartographer源码学习之gflag gflog

1 gflag
这是node_main.cc文件中用到的gflag代码:

DEFINE_bool(collect_metrics, false,
            "Activates the collection of runtime metrics. If activated, the "
            "metrics can be accessed via a ROS service.");
DEFINE_string(configuration_directory, "",
              "First directory in which configuration files are searched, "
              "second is always the Cartographer installation to allow "
              "including files from there.");
DEFINE_string(configuration_basename, "",
              "Basename, i.e. not containing any directory prefix, of the "
              "configuration file.");
DEFINE_string(load_state_filename, "",
              "If non-empty, filename of a .pbstream file to load, containing "
              "a saved SLAM state.");
DEFINE_bool(load_frozen_state, true,
            "Load the saved state as frozen (non-optimized) trajectories.");
DEFINE_bool(
    start_trajectory_with_default_topics, true,
    "Enable to immediately start the first trajectory with default topics.");
DEFINE_string(
    save_state_filename, "",
    "If non-empty, serialize state and write it to disk before shutting down.");

gflags(也称为Google Flags)是Google开源的一个命令行标志解析库,用于处理命令行参数。它提供了一种简单的方式来定义、解析和访问命令行标志,以及在程序中使用这些标志。
从上面中可以看出gflag的定义为DEFINE_数据类型(参数名,“参数的值”,“参数的使用说明”)

gflag的作用:当编写一个程序时,有时我们希望程序能够接收一些参数或选项来定制其行为。这些参数可以是命令行参数,也可以是配置文件中的设置。然而,手动解析和处理这些参数可能会变得复杂和繁琐。
在这种情况下,Google开发了一个开源库叫做gflags(或称为gflags),它提供了一种方便的方式来定义、解析和访问命令行参数。使用gflags库,我们可以通过在代码中添加特定的宏来定义命令行标志,并在程序运行时解析和访问这些标志的值。
在给定的代码段中,使用了gflags库的DEFINE_bool和DEFINE_string宏来定义了一些命令行标志。
DEFINE_bool用于定义布尔型的命令行标志。它接受三个参数:标志名称,标志的默认值以及一个描述该标志用途的字符串。例如,DEFINE_bool(collect_metrics, false, “Activates the collection of runtime metrics. If activated, the metrics can be accessed via a ROS service.”)定义了一个名为collect_metrics的布尔型标志,其默认值为false,并提供了描述该标志用途的字符串。
当我们使用gflags库定义了命令行标志后,我们可以在程序中使用这些标志来定制其行为。这些标志可以在程序的不同部分使用,例如在主函数中进行初始化,或者在其他函数中根据标志的值执行相应的逻辑。

在给定的代码段中,以下是每个标志的解释:
collect_metrics: 这是一个布尔型标志,用于激活运行时指标的收集。如果激活了该标志,指标可以通过一个ROS服务访问。
configuration_directory: 这是一个字符串型标志,用于指定搜索配置文件的第一个目录。程序将在该目录中查找配置文件。第二个目录总是Cartographer安装目录,以便可以包含来自该目录的文件。
configuration_basename: 这是一个字符串型标志,用于指定配置文件的文件名(不包含任何目录前缀)。
load_state_filename: 这是一个字符串型标志,如果非空,指定一个.pbstream文件的文件名,其中包含一个保存的SLAM状态。
load_frozen_state: 这是一个布尔型标志,用于确定是否以冻结(非优化)轨迹的形式加载保存的状态。
start_trajectory_with_default_topics: 这是一个布尔型标志,用于启用以默认主题立即启动第一个轨迹。
save_state_filename: 这是一个字符串型标志,如果非空,在关闭程序之前将状态序列化并写入磁盘。
在程序中,我们可以使用FLAGS_标志名称的语法来访问这些标志的值。例如,FLAGS_collect_metrics表示collect_metrics标志的值,FLAGS_configuration_directory表示configuration_directory标志的值。
通过使用gflags库,我们可以灵活地配置程序的行为和选项,而无需手动解析命令行参数。这使得程序的参数设置更加方便和可维护。
接下来是gflag的调用:

  <node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename backpack_2d.lua"
      output="screen">
    <remap from="echoes" to="horizontal_laser_2d" />
  </node>

从上面的代码块可以看出gflag的调用方式为-参数名即可。

2 gflog
gflog的初始化

 google::InitGoogleLogging(argv[0]);

google::InitGoogleLogging(argv[0]) 是一个用于初始化 Google 日志库(Google Logging Library)的函数调用。
Google 日志库是一个用于记录日志的强大工具,它提供了灵活的日志级别、日志过滤和输出控制等功能。通过使用 Google 日志库,开发人员可以在程序中插入日志语句,以便在程序运行时记录关键信息、错误消息和调试信息。
google::InitGoogleLogging(argv[0]) 函数用于初始化 Google 日志库,并将日志输出到控制台。它接受程序的命令行参数 argv[0] 作为参数,以便在日志输出中标识程序的名称。
通常,我们将 google::InitGoogleLogging(argv[0]) 放置在程序的初始化阶段,以确保在记录日志之前正确初始化日志库。这样,在程序运行时,可以使用日志宏(例如 LOG(INFO)、LOG(ERROR) 等)来记录不同级别的日志消息,并将其输出到控制台或其他指定的日志文件中。

argv[0] 是程序的命令行参数,表示程序运行时的可执行文件的名称。
在C/C++中,当我们从命令行执行一个程序时,我们可以在命令行中输入一些参数,例如:

./myprogram arg1 arg2

其中 ./myprogram 表示可执行文件的名称,arg1 和 arg2 是程序的命令行参数。
argv[0] 表示可执行文件的名称,即 ./myprogram。它是一个字符串,用于标识程序的名称。
在 google::InitGoogleLogging(argv[0]) 中,argv[0] 被传递给日志库,以便在日志输出中标识程序的名称。这样做可以使日志信息更加清晰,并能够准确地追踪日志来源。

// 使用ROS_INFO进行glog消息的输出
  cartographer_ros::ScopedRosLogSink ros_log_sink;

这个初始化怎么调用到ros_info的呢,下面就看程序分析。

  1. 先看:ScopedRosLogSink类的声明
class ScopedRosLogSink : public ::google::LogSink {
 public:
  ScopedRosLogSink();
  ~ScopedRosLogSink() override;

  void send(::google::LogSeverity severity, const char* filename,
            const char* base_filename, int line, const struct std::tm* tm_time,
            const char* message, size_t message_len) override;

  void WaitTillSent() override;

 private:
  bool will_die_;
};

可以看到是继承了google::LogSink这个父类,
ScopedRosLogSink 声明了两个函数,咱们重点看send函数的实现:

void ScopedRosLogSink::send(const ::google::LogSeverity severity,
                            const char* const filename,
                            const char* const base_filename, 
                            const int line,
                            const struct std::tm* const tm_time,
                            const char* const message,
                            const size_t message_len) {
  const std::string message_string = ::google::LogSink::ToString(
      severity, GetBasename(filename), line, tm_time, message, message_len);
  switch (severity) {
    case ::google::GLOG_INFO:
      ROS_INFO_STREAM(message_string);
      break;

    case ::google::GLOG_WARNING:
      ROS_WARN_STREAM(message_string);
      break;

    case ::google::GLOG_ERROR:
      ROS_ERROR_STREAM(message_string);
      break;

    case ::google::GLOG_FATAL:
      ROS_FATAL_STREAM(message_string);
      will_die_ = true;
      break;
  }
}

可以看到在send函数内部与ros_info_system系统联系起来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值