# cartographer代码解读
**Repository Path**: lijian8/cartographer_code
## Basic Information
- **Project Name**: cartographer代码解读
- **Description**: No description available
- **Primary Language**: C++
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2020-09-04
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# cartographer代码解读
## 0. 说明
* 只列主要示意性代码,其他代码省略
* 以处理LaserScan, 2D为例
* 采用Collator(参数map_builder.collate_by_trajectory 为false)
* 使用 --> 表示后续函数调用,或经过某个变量调用的后续函数
* 使用 <-- 表示在基类定义下,实际使用时的子类
* 使用 >>> 表示topic的回调函数中的后续函数调用
## 1. 总览
* 主函数 [run](#run)
+ Node node(..., new MapBuilder(...), ...)
+ node --> [Node](#Node)::[StartTrajectoryWithDefaultTopics](#StartTrajectoryWithDefaultTopics)
+ ros::spin
+ node --> [Node](#Node)::[FinishAllTrajectories](#FinishAllTrajectories)
+ node --> [Node](#Node)::[RunFinalOptimization](#RunFinalOptimization)
* [Node](#Node) 类
+ 成员变量
* [MapBuilderBridge](#MapBuilderBridge) map_builder_bridge_;
+ 构造函数 Node(..., map_builder, ...)
* 设置成员变量 map_builder_bridge_(..., map_builder, ...)
+ 成员函数 [StartTrajectoryWithDefaultTopics](#StartTrajectoryWithDefaultTopics) 及后续调用
* 初始化 [MapBuilderBridge](#MapBuilderBridge) 内容
+ map_builder_bridge_ --> 调用 [MapBuilderBridge](#MapBuilderBridge)::[AddTrajectory](#AddTrajectory)
* 设置消息回调函数
+ scanTopic >>> [HandleLaserScanMessage](#HandleLaserScanMessage)
+ imuTopic >>> [HandleImuMessage](#HandleImuMessage)
+ odomTopic >>> [HandleOdometryMessage](#HandleOdometryMessage)
+ 成员函数 [HandleLaserScanMessage](#HandleLaserScanMessage)/[HandleImuMessage](#HandleImuMessage)/[HandleOdometryMessage](#HandleOdometryMessage)
* map_builder_bridge_.sensor_bridges_[trajectory_id] --> 分别调用[SensorBridge](#SensorBridge)::[HandleLaserScanMessage](#s_HandleLaserScanMessage)/[HandleImuMessage](#s_HandleImuMessage)/[HandleOdometryMessage](#s_HandleOdometryMessage)
+ 成员函数 [FinishAllTrajectories](#FinishAllTrajectories)
* map_builder_bridge_ --> 调用 [MapBuilderBridge](#MapBuilderBridge)::[FinishTrajectory](#FinishTrajectory)
+ 成员函数 [RunFinalOptimization](#RunFinalOptimization)
* map_builder_bridge_ --> 调用 [MapBuilderBridge](#MapBuilderBridge)::[RunFinalOptimization](#b_RunFinalOptimization)
* [MapBuilderBridge](#MapBuilderBridge) 类
+ 成员变量
* [MapBuilder](#MapBuilder)* map_builder_;
* map sensor_bridges_;
* 构造函数 MapBuilderBridge(..., map_builder, ...)
* 设置成员变量 map_builder_ = map_builder;
+ 成员函数 [AddTrajectory](#AddTrajectory)
* 初始化 [MapBuilder](#MapBuilder) 内容
+ map_builder_ --> 调用 [MapBuilder](#MapBuilder)::[AddTrajectoryBuilder](#AddTrajectoryBuilder),获得trajectory_id
* 添加 SensorBridge(..., [MapBuilder](#MapBuilder)::[GetTrajectoryBuilder](#GetTrajectoryBuilder)(trajectory_id) <-- CollatedTrajectoryBuilder);
+ 成员函数 [FinishTrajectory](#FinishTrajectory)
* map_builder_ --> 调用 [MapBuilder](#MapBuilder)::[FinishTrajectory](#b_FinishTrajectory)
+ 成员函数 [RunFinalOptimization](#b_RunFinalOptimization)
* map_builder_->pose_graph() --> 调用 [PoseGraph2D](#PoseGraph2D)::[RunFinalOptimization](#p_RunFinalOptimization)
* [SensorBridge](#SensorBridge) 类
+ 成员变量
* TrajectoryBuilderInterface* (<-- [CollatedTrajectoryBuilder](#CollatedTrajectoryBuilder)) trajectory_builder_;
+ 构造函数 SensorBridge(..., trajectory_builder)
* 设置成员变量 trajectory_builder_ = trajectory_builder;
+ 成员函数 [HandleLaserScanMessage](#s_HandleLaserScanMessage)/[HandleImuMessage](#s_HandleImuMessage)/[HandleOdometryMessage](#s_HandleOdometryMessage)
* trajectory_builder_ --> 调用 [CollatedTrajectoryBuilder](#CollatedTrajectoryBuilder)::[AddSensorData](#AddSensorData)
* [MapBuilder](#MapBuilder) 类
+ 成员变量
* vector trajectory_builders_;
* PoseGraph* (<-- [PoseGraph2D](#PoseGraph2D)) pose_graph_;
* CollatorInterface* (<-- [Collator](#Collator)) sensor_collator_;
* ThreadPool thread_pool_;
+ 构造函数 MapBuilder(...)
* thread_pool_(options.num_background_threads);
* 根据配置设置成员变量pose_graph_ 和 sensor_collator_,以开始所假设的配置
* pose_graph_ = new PoseGraph2D(..., new optimization::OptimizationProblem2D(...), ...);
* sensor_collator_ = new Collator();
+ 成员函数 [AddTrajectoryBuilder](#AddTrajectoryBuilder)
* int trajectory_id = trajectory_builders_.size();
* local_trajectory_builder = new [LocalTrajectoryBuilder2D](#LocalTrajectoryBuilder2D)(...);
* g_trajectory_builder = new [GlobalTrajectoryBuilder](#GlobalTrajectoryBuilder)(local_trajectory_builder, trajectory_id, pose_graph_, res_callback);
* trajectory_builders_.push_back( new [CollatedTrajectoryBuilder](#CollatedTrajectoryBuilder)(..., sensor_collator_, trajectory_id, ..., g_trajectory_builder) );
+ 成员函数 [GetTrajectoryBuilder](#GetTrajectoryBuilder)(trajectory_id)
* return trajectory_builders_[trajectory_id];
+ 成员函数 [FinishTrajectory](#b_FinishTrajectory)(trajectory_id)
* sensor_collator_ --> 调用[Collator](#Collator)::[FinishTrajectory](#c_FinishTrajectory)(trajectory_id);
* pose_graph_ --> 调用 [PoseGraph2D](#PoseGraph2D)::[FinishTrajectory](#p_FinishTrajectory)(trajectory_id);
* [CollatedTrajectoryBuilder](#CollatedTrajectoryBuilder) 类
+ 成员变量
* int trajectory_id_;
* CollatorInterface* (<-- [Collator](#Collator)) sensor_collator_;
* TrajectoryBuilderInterface* (<-- [GlobalTrajectoryBuilder](#GlobalTrajectoryBuilder)) wrapped_trajectory_builder_;
+ 构造函数 CollatedTrajectoryBuilder(..., sensor_collator, trajectory_id, ..., wrapped_trajectory_builder)
* trajectory_id_ = trajectory_id;
* sensor_collator_ = sensor_collator;
* wrapped_trajectory_builder_ = wrapped_trajectory_builder;
* sensor_collator_ --> 调用[Collator](#Collator)::[AddTrajectory](#c_AddTrajectory)(trajectory_id, ..., HandleCollatedSensorData);
+ 成员函数 [AddSensorData](#AddSensorData)(sensor_id, raw_data)
* sensor_collator_ --> 调用[Collator](#Collator)::[AddSensorData](#c_AddSensorData)(MakeDispatchable(sensor_id, raw_data))
+ 成员函数 [HandleCollatedSensorData](#HandleCollatedSensorData)(data)
* data --> 调用[Dispatchable](#Dispatchable)::[AddToTrajectoryBuilder](#d_AddToTrajectoryBuilder)(wrapped_trajectory_builder_);
* [Dispatchable](#Dispatchable) 类
+ 成员变量
* string sensor_id_ (基类Data的成员);
* DataType data_;
+ 构造函数 Dispatchable(string sensor_id, DataType data)
* 设置相应成员变量;
+ 成员函数 [AddToTrajectoryBuilder](#d_AddToTrajectoryBuilder)(TrajectoryBuilderInterface* trajectory_builder)
* trajectory_builder --> 调用 [GlobalTrajectoryBuilder](#GlobalTrajectoryBuilder)::[AddSensorData](#g_AddSensorData1)(sensor_id_, data_);
* [Collator](#Collator) 类
+ 成员变量
* OrderedMultiQueue queue_;
+ 成员函数 [AddTrajectory](#c_AddTrajectory)(trajectory_id, topicIDList, callback)
* key = QueueKey{trajectory_id, topicID};
* queue_.AddQueue(key, callback);
+ 成员函数 [AddSensorData](#c_AddSensorData)(topicID, data)
* key = QueueKey{trajectory_id, topicID};
* queue_.Add(key, data) --> OrderedMultiQueue::Dispatch --> [CollatedTrajectoryBuilder](#CollatedTrajectoryBuilder)::[HandleCollatedSensorData](#HandleCollatedSensorData)
+ 成员函数 [FinishTrajectory](#c_FinishTrajectory)(trajectory_id)
* queue_.MarkQueueAsFinished(queue_key);
* [GlobalTrajectoryBuilder](#GlobalTrajectoryBuilder) 类
+ 成员变量
* int trajectory_id_;
* PoseGraph* pose_graph_;
* LocalTrajectoryBuilder* local_trajectory_builder_;
* LocalSlamResultCallback local_slam_result_callback_;
+ 构造函数 GlobalTrajectoryBuilder(local_trajectory_builder, trajectory_id, pose_graph_, result_callback)
* 设置相应成员变量;
+ 成员函数 [AddSensorData](#g_AddSensorData1)(sensor_id, timed_point_cloud_data)
* local_trajectory_builder_ --> 调用 matching_result = [LocalTrajectoryBuilder2D](#LocalTrajectoryBuilder2D)::[AddRangeData](#L_AddRangeData)(sensor_id, timed_point_cloud_data);
* pose_graph_ --> 调用 node_id = [PoseGraph2D](#PoseGraph2D)::[AddNode](#AddNode)(matching_result..., trajectory_id_, ...);
* local_slam_result_callback_(...);
+ 成员函数 [AddSensorData](#g_AddSensorData2)(sensor_id, imu_data)
* local_trajectory_builder_ --> 调用 [LocalTrajectoryBuilder2D](#LocalTrajectoryBuilder2D)::[AddImuData](#L_AddImuData)(imu_data);
* pose_graph_ --> 调用 [PoseGraph2D](#PoseGraph2D)::[AddImuData](#p_AddImuData)(trajectory_id_, imu_data);
+ 成员函数 [AddSensorData](#g_AddSensorData3)(sensor_id, odometry_data)
* local_trajectory_builder_ --> 调用 [LocalTrajectoryBuilder2D](#LocalTrajectoryBuilder2D)::[AddOdometryData](#L_AddOdometryData)(odometry_data);
* pose_graph_ --> 调用 [PoseGraph2D](#PoseGraph2D)::[AddOdometryData](#p_AddOdometryData)(trajectory_id_, odometry_data);
* [LocalTrajectoryBuilder2D](#LocalTrajectoryBuilder2D) 类
+ 成员变量
* PoseExtrapolator* extrapolator_;
* RangeDataCollator range_data_collator_;
* proto::LocalTrajectoryBuilderOptions2D options_; // TRAJECTORY_BUILDER_2D
* ActiveSubmaps2D active_submaps_;
+ 成员函数 [AddImuData](#L_AddImuData)(imu_data)
* [LocalTrajectoryBuilder2D](#LocalTrajectoryBuilder2D)::InitializeExtrapolator(imu_data.time);
* extrapolator_->AddImuData(imu_data);
+ 成员函数 [AddOdometryData](#L_AddOdometryData)(odometry_data)
* extrapolator_->AddOdometryData(odometry_data);
+ 成员函数 [AddRangeData](#L_AddRangeData)(sensor_id, unsynchronized_data)
* 利用range_data_collator_ 调用 [RangeDataCollator](#RangeDataCollator)::[AddRangeData](#r_AddRangeData)将不同传感器的unsynchronized_data按时间戳先后顺序重新编排,获得synchronized_data;
* 利用extrapolator_进行运动补偿,将不同时刻的synchronized_data变换到统一时刻下;
* 按距离对数据切割和初始化;
+ 丢弃掉距离小于options_.min_range的点云数据;
+ 将距离小于 options_.max_range数据累积到accumulated_range_data_.returns里;
+ 将距离大于 options_.max_range数据累积到accumulated_range_data_.misses里,
累积前先把数据的距离变到options_.missing_data_ray_length;
* 如果累积消息数达到options_.num_accumulated_range_data,则开始处理数据;
+ 调用 TransformToGravityAlignedFrameAndFilter 预处理数据;
+ 调用 AddAccumulatedRangeData 开始正式SLAM处理;
+ 成员函数 [TransformToGravityAlignedFrameAndFilter](#TransformToGravityAlignedFrameAndFilter)
* 按照重力方向对点云数据进行变换,使得z轴与重力方向重合;
* 保留z坐标在options_.min_z和options_.max_z间的数据;
* 用VoxelFilter对点云数据进行滤波,即按照options_.voxel_filter_size参数划分格子,每个格子只保留一个点
+ 成员函数 [AddAccumulatedRangeData](#AddAccumulatedRangeData)
* 利用 extrapolator_生成预测位姿;
* 按照 options_.adaptive_voxel_filter里面的参数,用AdaptiveVoxelFilter对点云数据进行滤波;
* 用预测位姿,将滤波后的点云数据和地图做 ScanMatch(预测位姿, 点云数据),获得位姿pose_estimate;
* extrapolator_->AddPose(time, pose_estimate);
* 利用pose_estimate对点云数据变换到地图坐标系下,InsertIntoSubmap(地图坐标系下的点云数据, ...);
+ 成员函数 [ScanMatch](#ScanMatch)(预测位姿,点云数据)
* 取当前活跃子地图列表中的最新一个作为 matching_submap;
* initial_ceres_pose = pose_prediction;
* 如果 options_.use_online_correlative_scan_matching 为真,按照 options_.real_time_correlative_scan_matcher 里面的参数,调用 [RealTimeCorrelativeScanMatcher2D](#RealTimeCorrelativeScanMatcher2D) ::[Match](#r_Match)(预测位姿, 点云数据, matching_submap),修改initial_ceres_pose;
* 按照 options_.ceres_scan_matcher 里面的参数,调用 [CeresScanMatcher2D](#CeresScanMatcher2D)::[Match](#c_Match)(预测位姿, initial_ceres_pose, 点云数据, matching_submap),获得最终位姿;
+ 成员函数 [InsertIntoSubmap](#InsertIntoSubmap)(地图坐标系下的点云数据)
* active_submaps_ --> 调用 [ActiveSubmaps2D](#ActiveSubmaps2D)::InsertRangeData(地图坐标系下的点云数据);
* [ActiveSubmaps2D](#ActiveSubmaps2D) 类
+ 成员变量
+ 成员函数
* [PoseGraph2D](#PoseGraph2D) 类
+ 成员函数 [AddNode](#AddNode)
+ 成员函数 [AddImuData](#p_AddImuData)
+ 成员函数 [AddOdometryData](#p_AddOdometryData)
+ 成员函数 [FinishTrajectory](#p_FinishTrajectory)(trajectory_id)
* [AdaptiveVoxelFilter](#AdaptiveVoxelFilter) 类
+ 成员函数 Filter及后续调用函数FilterByMaxRange和AdaptivelyVoxelFiltered
+ 剔除距离大于 adaptive_voxel_filter.max_range的点;
+ 如果点云数小于 adaptive_voxel_filter.min_num_points,返回当前点云;
+ 用 adaptive_voxel_filter.max_length 为参数,用VoxelFilter对点云数据进行滤波,如果点云数大于 adaptive_voxel_filter.min_num_points(点数足够密),则返回当前点云;
+ 从 adaptive_voxel_filter.max_length 开始,做二分查找VoxelFilter参数,使得滤波后的点云数点云数尽量接近 adaptive_voxel_filter.min_num_points;
* [RealTimeCorrelativeScanMatcher2D](#RealTimeCorrelativeScanMatcher2D) 类
+ 成员函数 [Match](#r_Match)
* [CeresScanMatcher2D](#CeresScanMatcher2D) 类
+ 成员函数 [Match](#c_Match)
## 2. cartographer_ros
### 2.1 主函数 Run (node_main.cc) [返回总览](#overview)
```
Node node(..., new MapBuilder(...), ...)
node.StartTrajectoryWithDefaultTopics(...)
::ros::spin()
node.FinishAllTrajectories();
node.RunFinalOptimization();
```
### 2.2 主节点类 Node (node.h, node.cc)
* 成员变量
```
MapBuilderBridge* map_builder_bridge_;
```
* Node(..., map_builder, ...)
```
设置成员变量 map_builder_bridge_(..., map_builder, ...)
```
* StartTrajectoryWithDefaultTopics(...) --> AddTrajectory(...) [返回总览](#overview)
```
map_builder_bridge_.AddTrajectory(topicIDList, ...);
AddExtrapolator(...);
LaunchSubscribers(...);
```
* LaunchSubscribers(...) [返回总览](#overview)
```
scanTopic >>> HandleLaserScanMessage
if (trajectory_builder_2d.use_imu_data)
imuTopic >>> HandleImuMessage
if (options.use_odometry)
odomTopic >>> HandleOdometryMessage
```
* HandleLaserScanMessage(trajectory_id, ...) [返回总览](#overview)
```
map_builder_bridge_.sensor_bridge_[trajectory_id]->HandleLaserScanMessage(...);
```
* HandleImuMessage(trajectory_id, ...) [返回总览](#overview)
```
extrapolators.AddImuData(...);
map_builder_bridge_.sensor_bridge_[trajectory_id]->HandleImuMessage(...);
```
* HandleOdometryMessage(trajectory_id, ...) [返回总览](#overview)
```
extrapolators.AddOdometryData(...);
map_builder_bridge_.sensor_bridge_[trajectory_id]->HandleOdometryMessage(...);
```
* FinishAllTrajectories() [返回总览](#overview)
```
...
map_builder_bridge_.FinishTrajectory(...);
```
* RunFinalOptimization() [返回总览](#overview)
```
...-->map_builder_bridge_.FinishTrajectory(...);
map_builder_bridge_.RunFinalOptimization();
```
### 2.3 MapBuilderBridge 类 (map_builder_bridge.h, map_builder_bridge.cc)
* 成员变量
```
MapBuilder* map_builder_;
map sensor_bridges_;
```
* MapBuilderBridge(..., map_builder, ...)
```
设置成员变量 map_builder_ = map_builder;
```
* AddTrajectory(topicIDList, ...) [返回总览](#overview)
```
trajectory_id = map_builder_->AddTrajectoryBuilder(topicIDList, ...);
sensor_bridges_[trajectory_id] = new SensorBridge(..., map_builder_->GetTrajectoryBuilder(trajectory_id));
```
* FinishTrajectory(trajectory_id) [返回总览](#overview)
```
map_builder_->FinishTrajectory(trajectory_id);
```
* RunFinalOptimization() [返回总览](#overview)
```
map_builder_->pose_graph()->RunFinalOptimization();
```
### 2.4 SensorBridge 类 (sensor_bridge.h, sensor_bridge.cc)
* 成员变量
```
TrajectoryBuilderInterface* (<-- CollatedTrajectoryBuilder) trajectory_builder_
```
* SensorBridge(..., trajectory_builder)
```
设置成员变量 trajectory_builder_ = trajectory_builder;
```
* HandleLaserScanMessage(...) --> HandleLaserScan(...) [返回总览](#overview)
```
for (num_subdivisions_per_laser_scan){
set subdivision data;
HandleRangefinder(topicID, ..., subdivision) --> trajectory_builder_->AddSensorData(topicID, TimedPointCloudData);
}
```
* HandleImuMessage(...) [返回总览](#overview)
```
trajectory_builder_->AddSensorData(topicID, ImuData);
```
* HandleOdometryMessage(...) [返回总览](#overview)
```
trajectory_builder_->AddSensorData(topicID, OdometryData);
```
## 3. cartographer
### 3.1 MapBuilder 类 (map_builder.h, map_builder.cc)
* 成员变量
```
vector trajectory_builders_
PoseGraph* (<-- PoseGraph2D) pose_graph_
CollatorInterface* (<-- Collator) sensor_collator_
```
* MapBuilder(...)
```
if (map_builder.use_trajectory_builder_2d){
pose_graph_ = new PoseGraph2D(..., new optimization::OptimizationProblem2D(...), ...);
}
if (map_builder.use_trajectory_builder_3d){
pose_graph_ = new PoseGraph3D(..., new optimization::OptimizationProblem3D(...), ...);
}
if (map_builder.collate_by_trajectory)
sensor_collator_ = new TrajectoryCollator();
else
sensor_collator_ = new Collator();
```
* AddTrajectoryBuilder(topicIDList, ...) [返回总览](#overview)
```
int trajectory_id = trajectory_builders_.size();
if (map_builder.use_trajectory_builder_3d){
if (!map_builder.has_trajectory_builder_3d_options)
local_trajectory_builder = new LocalTrajectoryBuilder3D(topicIDList, ...)
trajectory_builders_.push_back( CollatedTrajectoryBuilder(..., sensor_collator, trajectory_id, topicIDList,
new GlobalTrajectoryBuilder(local_trajectory_builder, trajectory_id, pose_graph, result_callback) ) );
}else{
if (!map_builder.has_trajectory_builder_2d_options)
local_trajectory_builder = new LocalTrajectoryBuilder2D(topicIDList, ...)
trajectory_builders_.push_back( CollatedTrajectoryBuilder(..., sensor_collator, trajectory_id, topicIDList,
new GlobalTrajectoryBuilder(local_trajectory_builder, trajectory_id, pose_graph, result_callback) ) );
}
MaybeAddPureLocalizationTrimmer(trajectory_id, ..., pose_graph_);
if (trajectory_builder.has_initial_trajectory_pose)
pose_graph_->SetInitialTrajectoryPose(trajectory_id, trajectory_builder.initial_trajectory_pose, ...);
```
* GetTrajectoryBuilder(trajectory_id) [返回总览](#overview)
```
return trajectory_builders_[trajectory_id]; // CollatedTrajectoryBuilder
```
* FinishTrajectory(...) [返回总览](#overview)
```
sensor_collator_->FinishTrajectory(trajectory_id);
pose_graph_->FinishTrajectory(trajectory_id);
```
### 3.2 CollatedTrajectoryBuilder 类 (collated_trajectory_builder.h, collated_trajectory_builder.cc)
* CollatedTrajectoryBuilder(..., sensor_collator, trajectory_id, topicIDList, wrapped_trajectory_builder)
```
sensor_collator->AddTrajectory(trajectory_id, topicIDList, HandleCollatedSensorData);
```
* HandleCollatedSensorData(topicID, data) [返回总览](#overview)
```
data->AddToTrajectoryBuilder(wrapped_trajectory_builder); // GlobalTrajectoryBuilder
```
* AddSensorData(topicID, TimedPointCloudData/ImuData/OdometryData) --> AddData --> sensor_collator->AddSensorData
### 3.3 Collator 类 (collator.h, collator.cc) // sensor_collator
* AddTrajectory(trajectory_id, topicIDList, callback) [返回总览](#overview)
```
for (topicID: topicIDList){
queue_key = QueueKey{trajectory_id, topicID};
queue_.AddQueue(queue_key, callback);
}
```
* AddSensorData(topicID, data) [返回总览](#overview)
```
queue_key = QueueKey{trajectory_id, topicID};
queue_.Add(queue_key, data) --> Dispatch --> callback
```
### 3.4 GlobalTrajectoryBuilder 类 (map_builder.h, map_builder.cc)
### 3.5 LocalTrajectoryBuilder2D 类 (map_builder.h, map_builder.cc)
### 3.6 PoseGraph2D 类 (map_builder.h, map_builder.cc)
* RunFinalOptimization(...) [返回总览](#overview)
```
```