cartographer源码学习之配置文件的读取

上一篇讲到,loadOptions这个函数实现了将NodeOptions和TrajectoryOptions参数的读取,但是我们没有继续再跳一层函数分析,cartographer是怎么实现文件的读取的,这一篇就引导大家去分析
先回顾LoadOptions这个函数:

std::tuple<NodeOptions, TrajectoryOptions> LoadOptions(
    const std::string& configuration_directory,
    const std::string& configuration_basename) {
/*
    absl::make_unique这是函数名
    <cartographer::common::ConfigurationFileResolver>这是函数的返回值类型
    std::vector<std::string>这是函数输入参数的类型
*/   
// 使用了 absl::make_unique 函数创建了一个名为 file_resolver 的智能指针对象,
// 指向了 cartographer::common::ConfigurationFileResolver 类的实例。这个类用于解析配置文件。
  auto file_resolver =
      absl::make_unique<cartographer::common::ConfigurationFileResolver>(
          std::vector<std::string>{configuration_directory});
// 这行代码从 file_resolver 对象中获取指定配置文件的内容,并将其存储在名为 code 的字符串中。
// GetFileContentOrDie 方法用于获取配置文件的内容,如果文件不存在或读取失败,则会抛出错误。
  const std::string code =
      file_resolver->GetFileContentOrDie(configuration_basename);
// 使用给定的 code 字符串和 ConfigurationFileResolver 对象的独占所有权,
// 用于对 Lua 配置参数进行解析和访问。
  cartographer::common::LuaParameterDictionary lua_parameter_dictionary(
      code, std::move(file_resolver));
// CreateNodeOptions是NodeOptions的对象,第二个参数同理,因此函数声明与返回值数据类型是一致的
  return std::make_tuple(CreateNodeOptions(&lua_parameter_dictionary),
                         CreateTrajectoryOptions(&lua_parameter_dictionary));
}

接下来我们就是对ConfigurationFileResolver这个类进行详细分析

class ConfigurationFileResolver : public FileResolver {
 public:
//  这是 ConfigurationFileResolver 类的构造函数。它接受一个 configuration_files_directories 参数,
// 该参数是一个字符串向量,包含配置文件目录的路径。通过这些路径,构造函数将设置配置文件解析器的搜索目录。
  explicit ConfigurationFileResolver(
      const std::vector<std::string>& configuration_files_directories);

  // 这是一个重写的成员函数,它返回给定文件名 basename 的完整路径。
  // 函数将在配置文件目录中搜索文件,并返回找到的文件的完整路径。如果文件不存在或路径无效,函数将终止程序的执行。
  std::string GetFullPathOrDie(const std::string& basename) override;
  // 这也是一个重写的成员函数,它返回给定文件名 basename 的文件内容。
  // 函数将根据完整路径获取文件,并将文件内容作为字符串返回。如果文件不存在或读取文件内容失败,函数将终止程序的执行。
  std::string GetFileContentOrDie(const std::string& basename) override;

 private:
//  这是一个私有成员变量,存储配置文件解析器的搜索目录。
// 它是一个字符串向量,用于保存配置文件目录的路径。构造函数使用传入的目录路径来初始化这个变量。
  std::vector<std::string> configuration_files_directories_;
};

点进去我们发现ConfigurationFileResolver继承了FileResolver这个父类
然后这个类的析构函数:

 explicit ConfigurationFileResolver(
      const std::vector<std::string>& configuration_files_directories);

可以看到他的实现:

ConfigurationFileResolver::ConfigurationFileResolver(
    const std::vector<std::string>& configuration_files_directories)
    : configuration_files_directories_(configuration_files_directories) {
  configuration_files_directories_.push_back(kConfigurationFilesDirectory);
}

然后我们点击(kConfigurationFilesDirectory)这个变量,会看到这样的结果:

/*
  这段代码是 ConfigurationFileResolver 类的构造函数的实现。
  构造函数使用成员初始化列表(member initializer list)来初始
  化类的成员变量 configuration_files_directories_。
*/
ConfigurationFileResolver::ConfigurationFileResolver(
    const std::vector<std::string>& configuration_files_directories)
    : configuration_files_directories_(configuration_files_directories) {
      // 通过调用 push_back 函数,将 kConfigurationFilesDirectory 添加到 
      // configuration_files_directories_ 向量的末尾。
      // 这样,configuration_files_directories_ 向量中就包含了额外的配置文件目录,
      // 可以在后续的文件路径解析或读取操作中使用这些目录。
  configuration_files_directories_.push_back(kConfigurationFilesDirectory);
}

这就是我们一直想要找的配置文件,以及还有源文件的目录
这个目录是在我们编译后生成的,因此每次修改完文件之后,最好要重新编译一下。
这个生成目录的指令是在src/cartographer/cartographer/common/config.h.cmake文件中配置的

constexpr char kConfigurationFilesDirectory[] =
    "@CARTOGRAPHER_CONFIGURATION_FILES_DIRECTORY@";
constexpr char kSourceDirectory[] = "@PROJECT_SOURCE_DIR@";

接下来,让我们看看下一个函数:

  std::string GetFullPathOrDie(const std::string& basename) override;
// configuration_files_directories_包含了两个配置文件的目录  lua 和 launch
/*
  该函数的目的是在存储在configuration_files_directories_向量中的目录中搜索具有给定basename的文件。
  它遍历每个目录,构建完整的文件路径,并检查文件是否存在。如果找到匹配的文件,它返回完整路径;
  否则,它记录一个错误消息并终止程序的执行。
*/
std::string ConfigurationFileResolver::GetFullPathOrDie(
    const std::string& basename) {
    //  这是一个循环,遍历存储在configuration_files_directories_向量中的每个目录路径。
  for (const auto& path : configuration_files_directories_) {
    // 将当前目录路径与给定的basename拼接起来,形成完整的文件路径。
    const std::string filename = path + "/" + basename;
    // 创建一个std::ifstream对象stream,用于打开由filename指定的文件。
    std::ifstream stream(filename.c_str());
    //  检查文件流是否处于良好状态,即文件是否成功打开并可以读取
    if (stream.good()) {
      // 输出一条信息性的日志消息,指示找到的文件的完整路径和原始搜索的basename。
      LOG(INFO) << "Found '" << filename << "' for '" << basename << "'.";
      // 返回找到的文件的完整路径,并退出函数。
      return filename;
    }
  }
  // 如果循环结束后仍然没有找到匹配的文件,
  // 则记录一条致命错误消息,并指示未找到具有给定basename的文件。这会导致程序终止执行。
  LOG(FATAL) << "File '" << basename << "' was not found.";
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值