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
    评论
Cartographer 是一款 Google 开源的用于实时构建 2D 和 3D 室内地图的工具,主要用于在机器人等移动设备上进行定位和建图任务。本文将对 Cartographer 的源代码进行分析解读,以帮助读者更好地理解该工具的实现原理。 1. 源码结构 Cartographer源码分为多个部分,包括: - cartographer:主要代码库,包含地图构建、局部地图匹配、位姿估计等核心功能。 - cartographer_ros:ROS wrapper,将 cartographer 代码库与 ROS 框架进行了整合,提供了 ROS 接口。 - cartographer_rviz:RViz 插件,用于可视化展示地图、轨迹等信息。 - cartographer_android:Android 版本,用于在 Android 系统上运行 Cartographer。 2. 核心算法 Cartographer 采用了多种算法来实现室内地图的构建和定位,其中比较重要的算法包括: - 位姿图优化(Pose Graph Optimization):通过对传感器数据进行多次优化,得到机器人在运动过程中的位置和方向信息。 - 实时建图(Real-Time Mapping):使用激光雷达等传感器,实时获取机器人周围环境的信息,构建室内地图。 - 局部地图匹配(Local Submap Matching):将当前传感器数据与已构建的局部地图进行匹配,从而得到更准确的位置信息。 - 点云滤波(Point Cloud Filtering):将激光雷达获取的点云数据进行滤波处理,去除噪声和无效数据。 3. 关键函数解析 以下是 Cartographer 中比较重要的几个函数的解析: - cartographer/mapping/internal/pose_graph_2d.cc: PoseGraph2D::AddNode():向位姿图中添加新的节点,包括节点 ID、位姿信息等。 - cartographer/mapping/internal/pose_graph_2d.cc: PoseGraph2D::AddConstraint():向位姿图中添加新的约束,包括约束类型、起始和终止节点 ID、约束值等。 - cartographer/mapping/internal/scan_matching/ceres_scan_matcher.cc: CeresScanMatcher::Match():使用 Ceres 库实现激光雷达数据与局部地图的匹配过程。 - cartographer/mapping/internal/3d/optimization/optimization_problem_3d.cc: OptimizationProblem3D::Solve():使用 Ceres 库实现位姿图优化过程,得到机器人在运动过程中的位置和方向信息。 - cartographer/mapping/internal/3d/scan_matching/real_time_correlative_scan_matcher_3d.cc: RealTimeCorrelativeScanMatcher3D::Match():实时建图过程中使用的一种激光雷达数据与局部地图的匹配算法。 4. 开发环境 Cartographer 的开发环境需要使用 Google 推荐的 Bazel 构建系统,以及 C++11 编译器和 ROS 框架。具体的开发环境搭建和编译过程可以参考 Cartographer 的官方文档。 5. 总结 Cartographer 是一款非常优秀的室内地图构建和定位工具,在机器人、自动驾驶等领域有着广泛的应用。本文对 Cartographer 的源代码进行了分析解读,希望能够帮助读者更好地理解该工具的实现原理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值