cartographer之MapBuilder类

随笔2个月前发布 风吹雪
3 0 0

node_main.cc

 node_main.cc—>node.cc—>map_builder_bridge.cc—>map_builder.cc

node_main.cc:cartographer_ros/cartographer_ros/cartographer_ros/node_main.cc

  // MapBuilder类是完整的SLAM算法类,包含前端(TransformingTrajectoryBuilder,scan to submap)、后端(用于查找回环的PoseGraph)、优化器等模块。
  auto map_builder =
      cartographer::mapping::CreateMapBuilder(node_options.map_builder_options);
  // 输入:
  // node_options:节点选项
  // map_builder:地图构建器
  // tf_buffer:tf缓存
  // collect_metrics:是否收集运行时指标
  // 输出:
  // node:Cartographer节点
  // 这里使用了std::move()函数,将map_builder转移到Node对象中,避免map_builder被销毁。
  // std::move()函数将左值(左值引用)转移到右值(右值引用)并返回右值。
  Node node(node_options, std::move(map_builder), &tf_buffer,
            FLAGS_collect_metrics); //node.cc

 

Node类的构造函数:cartographer_ros/cartographer_ros/cartographer_ros/node.cc

// 该构造函数主要是初始化Node对象,包括初始化ROS节点句柄、地图构建器桥接、TF缓冲区、度量注册表、发布者、服务服务器、定时器等。
// 其中,初始化ROS节点句柄、地图构建器桥接、TF缓冲区、发布者、服务服务器、定时器等的过程,均是通过调用相应的初始化函数完成。
// 其中,初始化地图构建器桥接的过程,主要是创建地图构建器接口对象,并将其传递给地图构建器桥接对象。
// 作用:创建Node对象,并初始化Node对象。
Node::Node(
    const NodeOptions& node_options,  // 节点选项
    std::unique_ptr<cartographer::mapping::MapBuilderInterface> map_builder,  // 地图构建器接口
    tf2_ros::Buffer* const tf_buffer,  // TF缓冲区
    const bool collect_metrics)  // 是否收集度量
    // 
    : node_options_(node_options),  // 初始化节点选项只是赋值给成员变量
      map_builder_bridge_(node_options_, std::move(map_builder), tf_buffer) // map_builder_bridge.cc

MapBuilderBridge类的构造函数:cartographer_ros/cartographer_ros/cartographer_ros/map_builder_bridge.cc

// MapBuilderBridge类的构造函数,用于初始化MapBuilderBridge对象。
// 参数:
//   node_options: NodeOptions对象,包含节点配置选项。
//   map_builder: 指向cartographer::mapping::MapBuilderInterface对象的智能指针,用于地图构建。
//   tf_buffer: 指向tf2_ros::Buffer对象的指针,用于处理TF变换。
MapBuilderBridge::MapBuilderBridge(
    const NodeOptions& node_options,
    std::unique_ptr<cartographer::mapping::MapBuilderInterface> map_builder,
    tf2_ros::Buffer* const tf_buffer)
    : node_options_(node_options),
      map_builder_(std::move(map_builder)),// map_builder.cc
      tf_buffer_(tf_buffer) {}

 MapBuilder类的构造函数:cartographer/cartographer/mapping/map_builder.cc

MapBuilder::MapBuilder(const proto::MapBuilderOptions& options)
    : options_(options), thread_pool_(options.num_background_threads())

ThreadPool类的构造函数:cartographer/cartographer/common/thread_pool.cc

// 线程池类构造函数,接受一个整数参数num_threads,表示线程池中的线程数量。
// 该构造函数会检查传入的线程数量是否大于0,如果不大于0则输出错误信息。
// 然后,它会创建指定数量的线程,并将它们添加到线程池中。每个线程都会执行ThreadPool::DoWork方法。
ThreadPool::ThreadPool(int num_threads) {
  CHECK_GT(num_threads, 0) << "ThreadPool requires a positive num_threads!";
  absl::MutexLock locker(&mutex_);
  for (int i = 0; i != num_threads; ++i) {
    pool_.emplace_back([this]() { ThreadPool::DoWork(); });
  }
}

ThreadPool::DoWork函数:

// 线程池的工作线程执行函数。该函数负责从任务队列中取出任务并执行。
void ThreadPool::DoWork() {
#ifdef __linux__
  // 在Linux系统上,调整当前线程的优先级,以确保后台任务不会占用前台线程的CPU资源。
  CHECK_NE(nice(10), -1);
#endif
  const auto predicate = [this]() EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
    return !task_queue_.empty() || !running_;
  };
  // 死循环,不断从任务队列中取出任务并执行。
  for (;;) {
    std::shared_ptr<Task> task;
    {
      absl::MutexLock locker(&mutex_);
      mutex_.Await(absl::Condition(&predicate));
      if (!task_queue_.empty()) {
        task = std::move(task_queue_.front());
        task_queue_.pop_front();
      } else if (!running_) {
        // 线程池停止运行,退出循环。
        return;
      }
    }
    CHECK(task);
    CHECK_EQ(task->GetState(), common::Task::DEPENDENCIES_COMPLETED);
    Execute(task.get());
  }
}

 

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...