cartographer的gflag和glog日志

gflag

CHECK宏.png
先看DEFINE宏,有三个宏:flag的名称,flag的默认值,help字符串。如何查看help信息呢,在执行可执行文件时加上–help选项即可,但是如果要显示help信息,代码里需要调用接口gflags::ParseCommandLineFlags(&argc, &argv, true)

gflags支持的变量类型如下:

  • DEFINE_bool: 布尔类型
  • DEFINE_int32: 32-bit 整型
  • DEFINE_int64: 64-bit 整型
  • DEFINE_uint64: 无符号 64-bit 整型
  • DEFINE_double: double
  • DEFINE_string: C++ string

在程序中使用flag,对于DEFINE过的flag我们可以像使用普通变量那样读写它,只需加一个FLAGS_前缀即可,如下:

1
2
3
4
5
6
7
8
if (FLAGS_is_handsome)
FLAGS_is_handsome = false;
std::cout << FLAGS_hobby << std::endl;

DEFINE_string(configuration_directory, "",
"First directory in which configuration files are searched, "
"second is always the Cartographer installation to allow "
"including files from there.");


1
2
3
4
5
6
CHECK_EQ(x,y)    ==
CHECK_NE(x,y) =
CHECK_LE(x,y) <=
CHECK_LT(x,y) <
CHECK_GE(x,y) >=
CHECK_GT(x,y) >

glog

Google glog是一个基于程序级记录日志信息的c++库,编程使用方式与c++的stream操作类似。 每个级别的日志除了输出到对应日志文件中,还输出到每个低级别日志文件中。默认ERROR和FATAL消息除了输出到日志文件中之外,还会输出到标准错误中
在CMakeLists中的配置.png
每个级别都对应有相应的日志文件,文件默认存放在临时文件中,Linux是 /tmp。运行cartographer之后,可以在/tmp里看到

glog的库文件都在/usr/lib/x86_64-linux-gnu

自定义cartographer的日志格式

glog的明显缺点就是配置输出格式不方便,还要修改源码的logging.cc,重新编译。我下载glog 0.5.0后,修改logging.cc文件再编译安装,结果导致cartographer报错,ScopedRosLogSink::send没有链接,应当是和现有的glog造成了冲突,然后一直解决不了。

然后尝试在ros_log_sink.cc中添加函数,就是把::google::LogSink::ToString重新定义到ros_log_sink.cc,这样避开glog的链接问题。头文件当然也要添加这个成员函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
string ScopedRosLogSink::ToString(const ::google::LogSeverity severity, const char* file, int line,
const struct ::tm* tm_time,
const char* message, size_t message_len)
{
ostringstream stream(string(message, message_len));
stream.fill('0');

stream << '['
<< setw(2) << 1+tm_time->tm_mon
<< '_'
<< setw(2) << tm_time->tm_mday
<< " "
<< setw(2) << tm_time->tm_hour << ':'
<< setw(2) << tm_time->tm_min << ':'
<< setw(2) << tm_time->tm_sec << " "
<< file << ": " << line << "] ";

stream << string(message, message_len);
return stream.str();
}

tm_time只精确到秒,这样日志就不能精确到毫秒了,不过目前还不需要。ScopedRosLogSink::send的开头改为ToString函数。这样改完后,日志格式可能还不是想要的
默认日志格式.png
后来才发现原来cartographer的日志格式是把glog的格式和ROS的格式融合一起了,所以修改环境变量如下
1
export ROSCONSOLE_FORMAT='[${message}'

修改后的日志.png

几个常用参数

1
2
3
4
5
6
7
8
9
10
11
FLAGS_logtostderr = true; // 设置日志消息是否转到标准输出而不是日志文件

FLAGS_alsologtostderr = true; // 设置日志消息除了日志文件之外是否去标准输出

FLAGS_colorlogtostderr = true; // 设置记录到标准输出的颜色消息(如果终端支持)

FLAGS_logbufsecs = ; // 设置可以缓冲日志的最大秒数,0指实时输出

FLAGS_max_log_size = ; // 设置最大日志文件大小(以MB为单位)

FLAGS_stop_logging_if_full_disk = true; // 设置是否在磁盘已满时避免日志记录到磁盘

cartographer的大部分文件都可以直接使用LOG(INFO)<<"log";这样的语句,因为都提前配置好了,但是最好重新指定日志路径。

  • google::SetLogDestination(google::INFO, "log/INFO_"); // 设置特定级别的日志的输出目录和前缀。第一个参数为日志级别,第二个参数表示输出目录及日志文件名前缀
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <glog/logging.h>

int main(int argc, char** argv)
{
google::InitGoogleLogging(argv[0]);
// INFO
std::string str_info;
// 文件名最后只能是 等级+下划线
str_info.append("/home/user/log/INFO_");
google::SetLogDestination(google::INFO, str_info.c_str());
LOG(INFO)<< "The is a info!";
// WARNING
std::string str_warn;
str_warn.append("/home/user/log/WARNING_");
google::SetLogDestination(google::WARNING, str_warn.c_str());
LOG(WARNING) << "The is a warning!";

// stop glog 可以没有
google::ShutdownGoogleLogging();
}

每次运行cartographer后发现在自定义的路径里,INFO开头的日志文件每次都会新建,而INFO结尾的日志是最新运行得到的日志