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的呢,下面就看程序分析。
- 先看: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系统联系起来了。