• Cartographer源码阅读(4):Node和MapBuilder对象2


      MapBuilder的成员变量sensor::Collator sensor_collator_;

      再次阅读MapBuilder::AddTrajectoryBuilder方法。首先构造了mapping::GlobalTrajectoryBuilder实例,接着作为参数构造了CollatedTrajectoryBuilder实例。

    trajectory_builders_.push_back(
    common::make_unique<CollatedTrajectoryBuilder>(
    &sensor_collator_, trajectory_id, expected_sensor_ids,
    common::make_unique<mapping::GlobalTrajectoryBuilder<mapping_2d::LocalTrajectoryBuilder,mapping_2d::proto::LocalTrajectoryBuilderOptions,mapping_2d::PoseGraph>>
    (trajectory_options.trajectory_builder_2d_options(),trajectory_id, pose_graph_2d_.get(),local_slam_result_callback)
    )
    );
    

      这里sensor_collator_作为参数传入,参与CollatedTrajectoryBuilder构造。查看构造函数:

    CollatedTrajectoryBuilder::CollatedTrajectoryBuilder(sensor::Collator* const sensor_collator, const int trajectory_id, const std::unordered_set<std::string>& expected_sensor_ids,   std::unique_ptr<TrajectoryBuilderInterface> wrapped_trajectory_builder)
        : sensor_collator_(sensor_collator)
        , trajectory_id_(trajectory_id)
        , wrapped_trajectory_builder_(std::move(wrapped_trajectory_builder))
        , last_logging_time_(std::chrono::steady_clock::now()) 
    {
         sensor_collator_->AddTrajectory(trajectory_id, expected_sensor_ids,
          [this](const std::string& sensor_id, std::unique_ptr<sensor::Data> data)
          {
            HandleCollatedSensorData(sensor_id, std::move(data));
          }
          );
    }
    

      这里是回调函数,std::unique_ptr是表示参数为智能指针。

     [this](const std::string& sensor_id, std::unique_ptr<sensor::Data> data)
     {
            HandleCollatedSensorData(sensor_id, std::move(data));
      }
    

      (1)查看sensor::Collator的AddTrajectory方法:

    void Collator::AddTrajectory( const int trajectory_id, const std::unordered_set<std::string>& expected_sensor_ids, const Callback& callback) 
    {
       for (const auto& sensor_id : expected_sensor_ids)
      {
          const auto queue_key = QueueKey{trajectory_id, sensor_id};
          queue_.AddQueue(queue_key, [callback, sensor_id](std::unique_ptr<Data> data)
                        {
                          callback(sensor_id, std::move(data));
                        });
           queue_keys_[trajectory_id].push_back(queue_key);
      }
    }
    

      for (const auto& sensor_id : expected_sensor_ids)用到了C++11的auto新特性。

      (2)查看HandleCollatedSensorData方法。调用了data->AddToTrajectoryBuilder(wrapped_trajectory_builder_.get());这里wrapped_trajectory_builder_是在CollatedTrajectoryBuilder构造函数中赋值的。为GlobalTrajectoryBuilder对象。因而查看sensor::Data的AddToTrajectoryBuilder() 方法。

      virtual void AddToTrajectoryBuilder(mapping::TrajectoryBuilderInterface *trajectory_builder) = 0;是sensor::Data类的一个虚方法。内部执行了trajectory_builder->AddSensorData(sensor_id_, data_);

    最后调用的是GlobalTrajectoryBuilder对象的AddSensorData(xx)方法。

     1 void CollatedTrajectoryBuilder::HandleCollatedSensorData( const std::string& sensor_id, std::unique_ptr<sensor::Data> data)
     2 {
     3   auto it = rate_timers_.find(sensor_id);
     4   if (it == rate_timers_.end())
     5   {
     6       it = rate_timers_ .emplace(
     7                  std::piecewise_construct, std::forward_as_tuple(sensor_id),
     8                  std::forward_as_tuple(common::FromSeconds(kSensorDataRatesLoggingPeriodSeconds))) .first;
     9   }
    10   it->second.Pulse(data->GetTime());
    11 
    12   if (std::chrono::steady_clock::now() - last_logging_time_ >
    13       common::FromSeconds(kSensorDataRatesLoggingPeriodSeconds)) 
    14   {
    15        for (const auto& pair : rate_timers_) 
    16       {
    17         LOG(INFO) << pair.first << " rate: " << pair.second.DebugString();
    18       }
    19       last_logging_time_ = std::chrono::steady_clock::now();
    20   }
    21 
    22    data->AddToTrajectoryBuilder(wrapped_trajectory_builder_.get());
    23   }
    24 
    25 } 
    CollatedTrajectoryBuilder::HandleCollatedSensorData
    template <typename DataType>
    class Dispatchable : public Data 
    {
     public:
      Dispatchable(const std::string &sensor_id, const DataType &data): Data(sensor_id), data_(data) {}
    
      common::Time GetTime() const override { return data_.time; }
    
      void AddToTrajectoryBuilder( mapping::TrajectoryBuilderInterface *const trajectory_builder) override 
     {
        trajectory_builder->AddSensorData(sensor_id_, data_);
      }
    
     private:
      const DataType data_;
    };
    

      再以IMU数据为例,GlobalTrajectoryBuilder类的AddSensorData(xx):

    void AddSensorData(const std::string& sensor_id,  const sensor::ImuData& imu_data) override 
    {
          local_trajectory_builder_.AddImuData(imu_data);
          pose_graph_->AddImuData(trajectory_id_, imu_data);
    }
    

      再看一下激光点云的数据

     1 void AddSensorData( const std::string& sensor_id, const sensor::TimedPointCloudData& timed_point_cloud_data) override
     2  {
     3     std::unique_ptr<typename LocalTrajectoryBuilder::MatchingResult>  matching_result = 
     4        local_trajectory_builder_.AddRangeData( timed_point_cloud_data.time, 
     5                                                sensor::TimedRangeData {timed_point_cloud_data.origin, 
     6                                                timed_point_cloud_data.ranges, {}}
     7        );
     8     if (matching_result == nullptr) 
     9     {
    10         // The range data has not been fully accumulated yet.
    11         return;
    12     }
    13     std::unique_ptr<mapping::NodeId> node_id;
    14     if (matching_result->insertion_result != nullptr) 
    15     {
    16           node_id = ::cartographer::common::make_unique<mapping::NodeId>(
    17           pose_graph_->AddNode(matching_result->insertion_result->constant_data, 
    18 trajectory_id_, matching_result->insertion_result->insertion_submaps));
    19           CHECK_EQ(node_id->trajectory_id, trajectory_id_);
    20     }
    21     if (local_slam_result_callback_) 
    22     {
    23       local_slam_result_callback_( trajectory_id_, matching_result->time, 
    24              matching_result->local_pose,
    25           std::move(matching_result->range_data_in_local), std::move(node_id));
    26      }
    27   }

      这里有两个重要的步骤一个是local_trajectory_builder_.AddRangeData(xxx),一个是 pose_graph_->AddNode(xxx)方法。同时std::unique_ptr<typename LocalTrajectoryBuilder::MatchingResult> matching_result作为AddNode方法的参数。

     1 mapping::NodeId PoseGraph::AddNode(
     2     std::shared_ptr<const mapping::TrajectoryNode::Data> constant_data,
     3     const int trajectory_id,
     4     const std::vector<std::shared_ptr<const Submap>>& insertion_submaps) {
     5   const transform::Rigid3d optimized_pose(
     6       GetLocalToGlobalTransform(trajectory_id) * constant_data->local_pose);
     7 
     8   common::MutexLocker locker(&mutex_);
     9   AddTrajectoryIfNeeded(trajectory_id);
    10   const mapping::NodeId node_id = trajectory_nodes_.Append(
    11       trajectory_id, mapping::TrajectoryNode{constant_data, optimized_pose});
    12   ++num_trajectory_nodes_;
    13 
    14   // Test if the 'insertion_submap.back()' is one we never saw before.
    15   if (submap_data_.SizeOfTrajectoryOrZero(trajectory_id) == 0 ||
    16       std::prev(submap_data_.EndOfTrajectory(trajectory_id))->data.submap !=
    17           insertion_submaps.back()) {
    18     // We grow 'submap_data_' as needed. This code assumes that the first
    19     // time we see a new submap is as 'insertion_submaps.back()'.
    20     const mapping::SubmapId submap_id =
    21         submap_data_.Append(trajectory_id, SubmapData());
    22     submap_data_.at(submap_id).submap = insertion_submaps.back();
    23   }
    24 
    25   // We have to check this here, because it might have changed by the time we
    26   // execute the lambda.
    27   const bool newly_finished_submap = insertion_submaps.front()->finished();
    28   AddWorkItem([=]() REQUIRES(mutex_) {
    29     ComputeConstraintsForNode(node_id, insertion_submaps,
    30                               newly_finished_submap);
    31   });
    32   return node_id;
    33 }
    PoseGraph::AddNode

      PoseGraph::AddNode方法很重要,分析节点和子图的关系。

      此处强调一下GlobalTrajectoryBuilder的两个关键对象local_trajectory_builder_和pose_graph_。

      PoseGraph* const pose_graph_;
      LocalTrajectoryBuilder local_trajectory_builder_;
    

      接下来按照准备安装ROS消息发布和处理的流程进行分析,即数据流。


    参考资料:

    http://blog.csdn.net/datase/article/details/78665862

    http://blog.csdn.net/learnmoreonce/article/category/6989560

  • 相关阅读:
    MongoDB repair on Ubuntu
    java后台图形相关代码,weblogic报错
    weblogic配置达梦数据源
    详解JavaScript中的this
    web app指南之构建html5离线应用
    android中的跨进程通信的实现(一)——远程调用过程和aidl
    android应用开发全程实录出版
    android窗口管理框架解析
    BizTalk调用SAP系统RFC含多个参数以及DateTime类型参数
    plsql连接64位oracle在windows 764下连接设置方法
  • 原文地址:https://www.cnblogs.com/yhlx125/p/8260990.html
Copyright © 2020-2023  润新知