C++ Cartographer加载配置文件过程介绍
在node_main.cc文件中,有如下代码
std::tie(node_options, trajectory_options) =
LoadOptions(FLAGS_configuration_directory, FLAGS_configuration_basename);
std::tie作用是同时对多个变量赋值,但是只能个从元组tuple赋值,在node_options.cc中有如下定义:
std::tuple
const std::string& configuration_directory,
const std::string& configuration_basename) {
// 获取配置文件所在的目录
auto file_resolver =
absl::make_unique
// 读取配置文件内容到code中
const std::string code =
file_resolver->GetFileContentOrDie(configuration_basename);
// 根据给定的字符串, 生成一个lua字典
cartographer::common::LuaParameterDictionary lua_parameter_dictionary(
code, std::move(file_resolver));
// 创建元组tuple,元组定义了一个有固定数目元素的容器, 其中的每个元素类型都可以不相同
// 将配置文件的内容填充进NodeOptions与TrajectoryOptions, 并返回
return std::make_tuple(CreateNodeOptions(&lua_parameter_dictionary),
CreateTrajectoryOptions(&lua_parameter_dictionary));
}
这返回值为元组tuple.
ps:vector初始化:
要注意“()”和“{}”这样的初始化情况,比如:
std::vector
std::vector
CreateNodeOptions,是定义在node_options.h文件里的一个结构体,同理CreateTrajectoryOptions,里面的参数是由lua文件传入的.
trajectoryoptions只在开始轨迹的时候用了,见node_main.cc
在trajectory_options.cc中有如下定义
void CheckTrajectoryOptions(const TrajectoryOptions& options) {
CHECK_GE(options.num_subdivisions_per_laser_scan, 1);
CHECK_GE(options.num_laser_scans + options.num_multi_echo_laser_scans +
options.num_point_clouds,
1)
<< "Configuration error: 'num_laser_scans', "
"'num_multi_echo_laser_scans' and 'num_point_clouds' are "
"all zero, but at least one is required.";
}
这个说明是要至少一个激光,或者激光+超声雷达+点云的个数要>1才能运行程序
NodeOptions CreateNodeOptions(
::cartographer::common::LuaParameterDictionary* const
lua_parameter_dictionary) {
NodeOptions options;
options.map_builder_options =
::cartographer::mapping::CreateMapBuilderOptions(
lua_parameter_dictionary->GetDictionary("map_builder").get());
options.map_frame = lua_parameter_dictionary->GetString("map_frame");
options.lookup_transform_timeout_sec =
lua_parameter_dictionary->GetDouble("lookup_transform_timeout_sec");
options.submap_publish_period_sec =
lua_parameter_dictionary->GetDouble("submap_publish_period_sec");
options.pose_publish_period_sec =
lua_parameter_dictionary->GetDouble("pose_publish_period_sec");
options.trajectory_publish_period_sec =
lua_parameter_dictionary->GetDouble("trajectory_publish_period_sec");
if (lua_parameter_dictionary->HasKey("publish_to_tf")) {
options.publish_to_tf =
lua_parameter_dictionary->GetBool("publish_to_tf");
}
if (lua_parameter_dictionary->HasKey("publish_tracked_pose")) {
options.publish_tracked_pose =
lua_parameter_dictionary->GetBool("publish_tracked_pose");
}
if (lua_parameter_dictionary->HasKey("use_pose_extrapolator")) {
options.use_pose_extrapolator =
lua_parameter_dictionary->GetBool("use_pose_extrapolator");
}
return options;
}
上面的程序是根据lua字典中的参数, 生成protobuf的序列化数据结构, 结构体NodeOptions定义在头文件中,其中有个元素为::cartographer::mapping::proto::MapBuilderOptions map_builder_options;是proto类型,在上述程序中的第一个参数被赋值
在node_options.cc有个类ConfigurationFileResolver,定义在configuration_file_resolver.h中,公有继承来自FileResolver
class ConfigurationFileResolver : public FileResolver{
public:
// c++11: explicit关键字 的作用就是防止类构造函数的隐式自动转换
explicit ConfigurationFileResolver(
const std::vector
std::string GetFullPathOrDie(const std::string& basename) override;
std::string GetFileContentOrDie(const std::string& basename) override;
private:
std::vector
};
FileResolver定义在lua_parameter_dictionary.h中:
class FileResolver {
public:
virtual ~FileResolver() {}
virtual std::string GetFullPathOrDie(const std::string& basename) = 0;
virtual std::string GetFileContentOrDie(const std::string& basename) = 0;
};
这个都是虚函数,只是个接口
cartographer经常有对接口类的继承
ConfigurationFileResolver的构造函数在configuration_file_resolver.cc里面
ConfigurationFileResolver::ConfigurationFileResolver(
const std::vector
: configuration_files_directories_(configuration_files_directories) {
configuration_files_directories_.push_back(kConfigurationFilesDirectory);
}
这个函数有个初始化列表,可以看到最终传入的参数是kConfigurationFilesDirectory,这个参数定义在config.h.这个文件里,这个文件是config.h.cmake编译生成的,如下内容
namespace cartographer {
namespace common {
constexpr char kConfigurationFilesDirectory[] =
"@CARTOGRAPHER_CONFIGURATION_FILES_DIRECTORY@";
constexpr char kSourceDirectory[] = "@PROJECT_SOURCE_DIR@";
} // namespace common
} // namespace cartographer
一个是定义工程配置文件的文件夹,一个是工程地址的目录,在config.h中会生成匹配自己电脑的字符串地址.那么上面的ConfigurationFileResolver的构造函数就是为了传入自己电脑的某些目录地址..
GetFullPathOrDie:遍历整个文件夹文件名看看能不能找到相应文件,如不能就报错
GetFileContentOrDie的作用是看传入的地址变量是不是空的,然后通过GetFullPathOrDie暴力查找是否在当前目录中存在,然后读取配置文件转为string格式然后返回.
再回到node_options.cc中
接下来是读取配置文件到code中,然后从code和之前读取的file_resolver生成一个lua字典
lua是个类似cpp的程序语言,定义在lua_parameter_dictionary.cc中,不细说了
如果想自己通过lua文件写入一些配置和参数,步骤如下
在自己写的lua配置文件中写入自己的参数,如th=1.1,
在想一下这个th是属于node_options还是trajectory_options,如在node_options中,则在node_options.h中定义好自己的数据类型和初始值,如double th = 1.1;
然后在node_options.cc中写入
if (lua_parameter_dictionary->HasKey("th")) {
options.th =
lua_parameter_dictionary->GetDouble("th");
}
到此这篇关于C++ Cartographer加载配置文件过程介绍的文章就介绍到这了,更多相关C++ Cartographer 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:
- .NET Core系列之MemoryCache 初识
- 007手机一键Root(安机网一键Root) v3.0 官方最新版 一键ROOT您的Android手机
- 12306密码被盗了怎么办?12306密码外泄解决方法
- 12个字的qq网名
- 150M迷你型无线路由器怎么设置?
- 192.168.1.1打不开怎么办?路由器192.168.1.1打不开的原因以及解决办法
- 2011年电子报合订本 电子报 编辑部 中文 PDF版 [84M]
- 2015年1月15日小米新旗舰发布会现场图文直播
- 2016.3.1vivo Xplay5新品发布会现场视频直播 优酷直播
- 2016华为P9发布会视频直播地址 4月15日华为P9国行发布会直播