cartographer 原理及代码
文章目录
- 原理
- 核心思想
- 关键技术
- 1. 子图
- 2. 前端:基于子图的扫描匹配(Scan-to-Submap Matching)
- 3. 匹配求解器 - Ceres Scan Matcher
- 4. 后端:子图间约束与全局优化(Submap-to-Submap Constraints)
- 5. 回环检测与优化后端
- 6. 分支定界法
- 算法流程
- 相关链接
- 代码架构
- 核心模块深度解析
- 1. 传感器数据预处理
- 2. 前端 Local SLAM:扫描匹配与子图构建*
- 3. 后端 Global SLAM:闭环检测与全局优化
- 代码结构
原理
Cartographer 是一个实时同时定位与建图 系统,适用于长期的 2D 和 3D 地图。它的核心优势在于其回环检测能力,能够有效地纠正随着时间累积的里程计误差,从而生成全局一致的地图。
- 高精度: 强大的回环检测和全局优化能力。
- 大规模建图: 子图概念和高效的优化后端使其适合构建工厂、园区等大规模地图。
- 鲁棒性强: 对传感器要求和初始配置相对友好,能在各种环境中稳定工作。
- 开源与可配置: 代码开源,提供了丰富的配置参数以适应不同的机器人和传感器配置。
Cartographer 的成功在于它巧妙地将 SLAM 问题分解为局部的扫描匹配与子图构建,以及全局的回环检测与图优化。它通过 Ceres Scan Matcher 保证了前端的精度,通过 分支定界法 实现了高效的全局回环检测,最终通过稀疏姿态图优化 解决了累积误差这一 SLAM 的核心难题,从而能够生成高质量、全局一致的地图。
核心思想
Cartographer 的核心思想是:通过将连续的激光雷达扫描数据匹配到一张不断优化的子图序列中,并利用强大的回环检测与优化后端,来保证地图的全局一致性。
系统架构分为两个部分:
-
局部 SLAM(前端)
- 任务: 实时地处理传感器数据(主要是激光雷达和里程计),进行扫描匹配,构建一系列连续的、高质量的子图。
- 特点: 速度快,保证实时性,但会累积局部误差。通常以
odom
为原点坐标系。
-
全局 SLAM(后端)
- 任务: 负责检测回环(即识别出机器人再次到达之前去过的地方),并执行全局优化,调整所有子图和位姿的位置,以消除累积误差。
- 特点: 计算量大,通常在后台线程运行,不要求严格的实时性。通常以
map
为原点坐标系。
关键技术
1. 子图
子图是一小段连续时间内构建的局部地图,它本身是连续且一致的,误差很小。
- 作用:
- 作为新一帧激光扫描数据进行匹配的参考坐标系。
- 将大规模的建图问题分解为多个小规模的子图构建问题,简化了计算。
- 构建过程: 局部 SLAM 通过将新的激光扫描帧与当前正在构建的子图进行匹配,找到最优的位姿,然后将该帧数据插入到子图中,从而逐渐完善这个子图。
2. 前端:基于子图的扫描匹配(Scan-to-Submap Matching)
Cartographer的前端(Local SLAM)核心是将当前激光扫描数据与正在构建的子图(submap)匹配,而非直接与前一帧扫描数据匹配。
- 子图的作用:子图是由多帧连续激光扫描数据累积构建的局部地图(如5cm×5cm分辨率的概率栅格地图),包含障碍物占据概率信息。
- 匹配流程:
- 初始位姿估计:通过姿态外推器(
Pose Extrapolator
)结合IMU、里程计数据,预测当前扫描的初始位姿。 - 扫描匹配优化:以初始位姿为起点,通过Ceres Scan Matching(基于非线性最小二乘)或Fast Correlative Scan Matching(基于分支定界法),将当前扫描数据与子图匹配,求解最优位姿。
- 子图更新:匹配后的扫描数据被插入子图,直到子图完成(不再更新)并启动新子图。
- 初始位姿估计:通过姿态外推器(
关键区别:传统scan-to-scan matching
仅依赖相邻两帧数据,易累积误差;而Cartographer通过与局部子图匹配(包含多帧历史信息),显著提高位姿估计稳定性。
3. 匹配求解器 - Ceres Scan Matcher
这是局部 SLAM 的核心。当一个新的激光扫描数据到来时,需要确定机器人在当前子图中的最可能位姿。
- 原理: 这是一个非线性优化问题。它寻找一个位姿
(x, y, θ)
(2D),使得当前激光扫描到的所有点,在子图的概率栅格地图中,命中“已占据”栅格的概率总和最大。 提供的局部位姿估计。
- 数学表达: 可以看作是一个最大似然估计问题。
M
是子图(栅格地图),H
是激光扫描点集,T
是要求解的变换矩阵(包含位姿)。
目标就是找到T
,使得sum(M(T * H))
最大,可化成如下最小二乘问题:
arg minξ∑k=1K(1−Msmooth(Tξhk))2\argmin_{\xi} \sum_{k=1}^{K} \left(1 - M_{\text{smooth}}(T_{\xi} h_k)\right)^2ξargmink=1∑K(1−Msmooth(Tξhk))2
4. 后端:子图间约束与全局优化(Submap-to-Submap Constraints)
Cartographer的后端(Global SLAM)并非简单的scan-to-map matching
,而是通过子图间的闭环约束优化全局位姿。
- 闭环检测:当新子图完成后,系统会与所有已完成的历史子图进行匹配(通过分支定界法加速搜索),若找到可靠匹配,则生成子图间的相对位姿约束。
- 全局优化:使用稀疏位姿调整(SPA),以子图和扫描帧的位姿为变量,以子图间约束为残差,通过Ceres库求解非线性最小二乘问题,修正累积误差。
核心逻辑:后端通过子图间的约束关系(而非单帧扫描与全局地图的匹配)实现全局一致性,本质是图优化问题。
5. 回环检测与优化后端
这是 Cartographer 的灵魂所在,也是它区别于许多其他 SLAM 系统的关键。
-
问题: 尽管扫描匹配很精确,但微小的误差会随着机器人的运动不断累积,导致子图与子图之间出现错位。当机器人绕一圈回到原点时,地图无法闭合。
-
回环检测:
- 如何检测: Cartographer 使用分支定界法 来加速扫描匹配,从而在全局所有已构建的子图中,快速地为当前扫描帧寻找可能匹配的位姿。
- 过程: 当机器人运动时,后台线程会不断地将当前的激光扫描数据与所有历史子图进行匹配。如果发现在某个历史子图的某个位姿上,当前扫描能非常匹配地“对上”,这就形成了一个回环约束。
- 效果: 一旦优化完成,回环约束会像一根“橡皮筋”,把错误累积而拉开的子图“拉”回正确的位置,从而生成一个全局一致的地图。这个过程是“牵一发而动全身”的,会优化整个地图。
-
全局优化: 一个巨大的稀疏姿态图优化问题。
- 图的构成:
- 节点: 机器人的位姿(通常对应每一帧激光扫描的位姿)。
- 边:
- 局部约束边: 由前端扫描匹配产生,连接相邻的位姿节点。
- 回环约束边: 由后端回环检测产生,连接相隔很远的位姿节点。
- 优化过程: 使用 SPA(Sparse Pose Adjustment) 算法,调整图中所有节点的位姿,使得所有约束边的误差(即预测位姿差和观测位姿差之间的差异)的平方和最小。
- 图的构成:
Cartographer中的回环闭合优化问题,属于非线性最小二乘优化问题。核心是通过非线性最小二乘方法优化子图位姿Xim)和扫描位姿(ΞsXi^{\text{m}})和扫描位姿(\Xi^{\text{s}}Xim)和扫描位姿(Ξs,最小化由相对位姿约束ξij\xi_{ij}ξij和协方差Σij\Sigma_{ij}Σij定义的残差平方和(经鲁棒核函数ρ\rhoρ处理),残差(e)通过坐标变换计算平移与旋转偏差,最终实现全局位姿优化以消除累计误差。
通过调整子图位姿集合Xim=ξimXi^{\text{m}} = {\xi_i^{\text{m}}}Xim=ξim和扫描位姿集合Xis=ξjsXi^{\text{s}} = {\xi_j^{\text{s}}}Xis=ξjs,最小化整体残差。
首先,总体优化问题公式定义如下:
argminΞm,Ξs12∑ijρ(E2(ξim,ξjs;Σij,ξij))argmin_{\Xi^{\text{m}},\Xi^{\text{s}}} \frac{1}{2} \sum_{ij} \rho(E^2(\xi_i^{\text{m}}, \xi_j^{\text{s}}; \Sigma_{ij}, \xi_{ij}))argminΞm,Ξs21ij∑ρ(E2(ξim,ξjs;Σij,ξij))
其中:
⦁ 目标函数:寻找使代价函数最小的位姿参数,12\frac{1}{2}21为缩放因子,sumijsum_{ij}sumij表示对所有子图-扫描对的约束求和。
⦁ 鲁棒核函数rho(⋅)rho(\cdot)rho(⋅):用于处理异常值,降低错误约束对优化结果的影响,常见如Huber核或Cauchy核。
⦁ 残差项E2E^2E2:衡量实际位姿与约束位姿的偏差,定义为eTΣij−1ee^T \Sigma_{ij}^{-1} eeTΣij−1e,即马氏距离的平方,
其中SigmaijSigma_{ij}Sigmaij是约束的协方差矩阵,反映相对位姿xiijxi_{ij}xiij的不确定性,其逆矩阵Sigmaij−1Sigma_{ij}^{-1}Sigmaij−1为信息矩阵,权重与不确定性成反比。
残差向量(E)由公式(5)计算:E(ξim,ξjs;ξij)=ξij−(Rξim−1(tξim−tξjs)ξi;θm−ξj;θs)E(\xi_i^{\text{m}}, \xi_j^{\text{s}}; \xi_{ij}) = \xi_{ij} - \begin{pmatrix} R_{\xi_i^{\text{m}}}^{-1}(t_{\xi_i^{\text{m}}} - t_{\xi_j^{\text{s}}}) \ \xi_{i;\theta}^{\text{m}} - \xi_{j;\theta}^{\text{s}} \end{pmatrix}E(ξim,ξjs;ξij)=ξij−(Rξim−1(tξim−tξjs) ξi;θm−ξj;θs)
其中:
⦁ xiijxi_{ij}xiij是子图(i)与扫描(j)之间的相对位姿约束(包含平移和旋转)。
⦁ 右侧第一项Rξim−1(tξim−tξjs)R_{\xi_i^{\text{m}}}^{-1}(t_{\xi_i^{\text{m}}} - t_{\xi_j^{\text{s}}})Rξim−1(tξim−tξjs):将扫描位姿xijs)的平移量(tξjsxi_j^{\text{s}})的平移量(t_{\xi_j^{\text{s}}}xijs)的平移量(tξjs通过子图位姿ξim)的旋转矩阵逆(Rξim−1\xi_i^{\text{m}})的旋转矩阵逆(R_{\xi_i^{\text{m}}}^{-1}ξim)的旋转矩阵逆(Rξim−1转换到子图坐标系下,再与子图平移量tξimt_{\xi_i^{\text{m}}}tξim作差,得到平移残差。
⦁ 第二项ξi;θm−ξj;θs\xi_{i;\theta}^{\text{m}} - \xi_{j;\theta}^{\text{s}}ξi;θm−ξj;θs:子图与扫描的旋转角(θ\thetaθ分量)之差,即旋转残差。
综上,该公式通过最小化所有子图-扫描对的相对位姿约束残差(考虑协方差加权和鲁棒核函数),优化全局位姿,从而消除SLAM过程中的累计误差,实现高精度地图构建。
6. 分支定界法
这是 Cartographer 实现快速全局扫描匹配的关键算法。
- 要解决的问题: 暴力搜索所有可能位姿的计算量是无法接受的。
- 核心思想:
- 分支: 将搜索空间(位置和角度)表示为一棵树。根节点代表整个搜索空间,子节点代表被划分的更小的搜索空间。
- 定界: 对每个节点(即每个搜索空间),计算一个分数上界(即在该空间内可能得到的最高匹配分数)。这个上界可以通过预计算的多分辨率栅格地图来高效获得。
- 剪枝: 在深度优先搜索这棵树时,如果某个节点的分数上界已经低于当前已知的最佳分数,那么就可以“剪掉”这个分支(即这个节点下的所有子空间),因为它们不可能产生更好的结果。
- 优势: 通过聪明的剪枝,它避免了遍历所有可能性,从而在保证找到全局最优解(或近似最优解)的同时,极大地提高了搜索效率。
算法流程
- 数据输入: 接收激光雷达扫描数据和里程计/IMU数据。
- 局部SLAM(前端):
- 使用 Ceres Scan Matcher 将新扫描帧与当前子图匹配,得到精确的局部位姿。
- 将该帧数据插入到当前子图中。
- 当子图积累了足够多的数据后,将其标记为完成,并开启一个新的子图。
- 全局SLAM(后端):
- 在后台,使用分支定界法不断尝试将当前的扫描帧与所有已完成的历史子图进行匹配。
- 如果找到良好的匹配(回环),就在姿态图中添加一个回环约束边。
- 当找到足够多的回环约束或经过一定时间后,触发全局优化(SPA)。
- 地图输出: 优化后的位姿用于生成最终全局一致的栅格地图或点云地图。
相关链接
https://www.bilibili.com/video/BV1yD42137qj
https://www.bilibili.com/video/BV1mK4y1u7MK
代码架构
Cartographer 的核心设计思想是 “前后端分离”:
- 前端 负责实时处理传感器数据,进行扫描匹配,构建局部一致的子图。
- 后端 负责全局优化,通过闭环检测校正前端累积的误差。
核心模块深度解析
1. 传感器数据预处理
对应图中的 数据输入层 -> 传感器数据预处理。
-
PoseExtrapolator
(pose_extrapolator.cc
)- 作用:预测新激光帧到达时的机器人位姿,为扫描匹配提供良好的初始值。
- 工作原理:
// 融合IMU、里程计和之前的位姿进行预测 void PoseExtrapolator::AdvanceTo(const common::Time time) {// 使用IMU积分计算旋转,里程计计算平移const transform::Rigid3d pose = transform::Rigid3d::Rotation(ExtrapolateRotation(time)) *odometry_pose_ *transform::Rigid3d::Translation(ExtrapolateTranslation(time)); }
-
RangeDataCollator
(range_data_collator.cc
)- 作用:当有多个激光雷达时,按时间顺序整理和同步数据。
-
VoxelFilter
(voxel_filter.cc
)- 作用:对点云进行体素滤波降采样,减少计算量。
// 将点云划分体素网格,每个体素只保留一个点 PointCloud VoxelFilter::Filter(const PointCloud& points) {VoxelKeySet voxels;for (const auto& point : points) {voxels.insert(GetVoxelKey(point)); // 计算点所属的体素}return ReconstructPoints(voxels); // 从体素重建点云 }
2. 前端 Local SLAM:扫描匹配与子图构建*
对应图中的 前端 Local SLAM。
-
扫描匹配 (
local_trajectory_builder_2d.cc
)-
实时相关扫描匹配器 (
real_time_correlative_scan_matcher_2d.cc
):- 在预测位姿附近进行暴力搜索,找到最佳匹配位置。
- 为后续的Ceres优化提供良好的初始值。
-
Ceres扫描匹配器 (
ceres_scan_matcher_2d.cc
):- 使用非线性优化进一步精化位姿。
// Ceres优化问题构建 void CeresScanMatcher2D::Match(const transform::Rigid2d& initial_pose_estimate,const PointCloud& point_cloud,const Grid2D& grid,transform::Rigid2d* const pose_estimate) {ceres::Problem problem;// 添加占据栅格代价函数problem.AddResidualBlock(OccupiedSpaceCostFunction2D::CreateAutoDiffCostFunction(...));// 添加位姿先验代价函数problem.AddResidualBlock(TranslationDeltaCostFunctor2D::CreateAutoDiffCostFunction(...));problem.AddResidualBlock(RotationDeltaCostFunctor2D::CreateAutoDiffCostFunction(...)); }
-
-
子图构建 (
submap_2d.cc
)- 作用:维护一个局部一致的地图片段。
- 关键方法:
// 将扫描数据插入子图 void Submap2D::InsertRangeData(const sensor::RangeData& range_data,const RangeDataInserterInterface* range_data_inserter) {// 更新概率栅格地图range_data_inserter->Insert(range_data, grid_.get()); }
3. 后端 Global SLAM:闭环检测与全局优化
对应图中的 后端 Global SLAM。
-
约束构建器 (
constraint_builder_2d.cc
)- 作用:在后台线程中搜索闭环约束。
- 工作流程:
- 当子图完成时,将其加入闭环检测池
- 对于新的扫描节点,使用
FastCorrelativeScanMatcher
在所有已完成子图中搜索匹配 - 如果找到足够好的匹配,形成一个闭环约束
-
位姿图优化 (
pose_graph_2d.cc
)- 作用:基于所有约束优化整个轨迹。
- 优化问题构建:
// 在 optimization_problem_2d.cc 中定义代价函数 class SpaCostFunction2D {// 实现扫描到子图匹配的代价计算template <typename T>bool operator()(const T* const pose_i, const T* const pose_j, T* residual) const {// 计算两个位姿间的相对变换误差const auto relative_pose = pose_i->inverse() * pose_j;residual[0] = (relative_pose.translation().x() - observed_relative_pose_.translation().x());residual[1] = (relative_pose.translation().y() - observed_relative_pose_.translation().y());residual[2] = NormalizeAngle(relative_pose.rotation().angle() - observed_relative_pose_.rotation().angle());return true;} };
代码结构
cartographer
├── bazel :存放Bazel 构建工具的配置文件,用于定义Bazel 的构建规则和依赖管理逻辑。Bazel 作为Google 内部广泛使用的构建工具。与其他.bazel等通常不需要直接修改
├── BUILD.bazel :Bazel 构建的核心配置文件,定义根目录下的构建目标(如可执行文件、库文件)及依赖关系
├── cartographer :代码核心,按功能拆分为多个子模块,覆盖SLAM的全流程(传感器处理、地图构建、定位优化等)
│ ├── BUILD.bazel
│ ├── cloud :负责SLAM的云端化能力,支持客户端-服务器(C/S)模式,实现多机器人分布式地图构建与数据交互
│ │ ├── ... ...服务端处理:客户端上传数据 → map_builder_server(接收请求 + 调度) → 调用map_builder_context_impl(获取资源) → 调用mapping/sensor(序列化 / 反序列化) → 调用handlers(处理具体数据) → map_builder_server 返回结果
│ │ ├── client :提供客户端接口
│ │ │ └── map_builder_stub.cc/h :用于与云端服务器通信,发送传感器数据、接收地图结果
│ │ ├── internal :云端核心实现,包括客户端桩(Stub)、数据处理器、服务器逻辑
│ │ │ ├── client/ :客户端底层桩代码, 如pose_graph_stub.cc/h,封装与服务器的RPC 通信细节
│ │ │ ├── handlers :处理各类传感器数据和服务请求的处理器, 实现数据的解析与响应
│ │ │ │ ├── add_imu_data_handler.cc/h :IMU数据处理
│ │ │ │ ├── get_submap_handler.cc/h :子图获取处理
│ │ │ │ └── ... ...
│ │ │ ├── local_trajectory_uploader.cc/h :本地轨迹上传器,负责将本地轨迹、子图、传感器数据等,按protobuf协议序列化后上传至云端服务器,是客户端向云端同步数据的核心组件
│ │ │ ├── map_builder_context_impl.cc/h : 地图构建上下文实现,封装云端地图构建的底层资源(如子图数据、轨迹元信息、全局位姿图实例),为map_builder_server 提供数据访问与能力支撑(如让服务器通过它获取子图、更新轨迹状态)
│ │ │ ├── map_builder_context_interface.h :地图构建上下文的抽象接口,定义云端地图构建过程中所需的核心能力(如获取子图数据、查询轨迹状态、触发优化),为map_builder_context_impl提供接口规范,实现接口与实现的解耦
│ │ │ ├── map_builder_server.cc/h :云端地图构建服务器的核心逻辑实现,基于map_builder_context_impl 提供的资源,接收客户端的RPC 请求(如传感器数据上传、子图查询),调度对应的处理器(如handlers 模块)处理请求,执行全局地图构建与优化,并向客户端返回结果
│ │ │ ├── client_server_test.cc
│ │ │ ├── mapping & sensor: 负责云端地图数据和传感器数据的序列化 / 反序列化,便于网络传输
│ │ │ │ └── serialization.cc/h :基于protobuf 协议,将C++ 数据结构(如子图、IMU数据)与二进制流互转
│ │ │ └── testing/ :各类数据测试代码
│ │ ├── map_builder_server_main.cc :启动一个gRPC服务器,作为中心节点接收来自多个机器人的SLAM数据
│ │ ├── map_builder_server_interface.cc/h :云端地图构建服务器的抽象接口,定义服务器的核心功能(如启动服务、处理客户端请求、管理全局地图),统一不同服务器实现(如单机服务器、分布式服务器)的对外接口
│ │ ├── map_builder_server_options.cc/h :云端地图服务器的配置参数处理,解析configuration_files/map_builder_server.lua中的配置(如服务器端口、最大连接数、地图存储路径),为map_builder_server提供初始化参数
│ │ ├── metrics/prometheus/ :集成Prometheus 监控工具,实现云端服务的指标采集(如请求延迟、数据吞吐量)
│ │ └── proto/ :定义云端通信的protobuf 协议,规范客户端与服务器的数据交互格式
│ ├── common :提供全项目通用的基础工具和组件,如数学工具、配置解析、并发组件等
│ │ ├── internal :通用组件的底层实现
│ │ │ ├── blocking_queue.h :阻塞队列
│ │ │ ├── ceres_solver_options.cc/h :Ceres 求解器配置
│ │ │ ├── rate_timer.h :速率计时器
│ │ │ ├── xxx_test.cc
│ │ │ └── testing/ :lua配置解析测试、线程池测试
│ │ ├── configuration_file_resolver.cc/h: 配置文件解析
│ │ ├── lua_parameter_dictionary.cc/h :Lua 参数字典
│ │ ├── lua.h
│ │ ├── fixed_ratio_sampler.cc/h :按固定比例对输入数据进行采样,筛选出部分数据参与后续处理,平衡算法性能与精度
│ │ ├── histogram.cc/h :统计直方图工具
│ │ ├── math.h :数学工具
│ │ ├── port.h :端口管理
│ │ ├── print_configuration_main.cc :打印配置
│ │ ├── task.cc/h :用于在线程池中调度和管理任务。&blocking_queue结合
│ │ ├── thread_pool.cc/h :线程池
│ │ ├── time.cc/h :时间处理
│ │ ├── proto/ceres_solver_options.proto
│ │ └── xxx_test.cc: 各类测试文件
│ ├── ground_truth :负责生成和处理 “真值” 数据,用于评估SLAM算法的精度(如定位误差、地图一致性)
│ │ ├── autogenerate_ground_truth_main.cc :自动生成真值数据(半仿真)
│ │ ├── autogenerate_ground_truth.cc/h
│ │ ├── proto/relations.proto :定义真值数据的protobuf 格式
│ │ ├── relations_text_file.cc/h :处理真值关系文件
│ │ └── compute_relations_metrics_main.cc
│ ├── io: 负责数据的输入 / 输出(I/O)处理,包括传感器数据读取、地图文件写入、数据格式转换
│ │ ├── internal :I/O 的底层实现
│ │ │ ├── in_memory_proto_stream.cc/h :在内存中实现protobuf数据的流式读写,用于高效处理序列化数据
│ │ │ ├── in_memory_proto_stream_test.cc :验证内存中protobuf 流的读写、序列化 / 反序列化功能是否正确
│ │ │ ├── mapping_state_serialization.cc/h :地图状态序列化,负责将SLAM的完整状态保存/加载
│ │ │ ├── pbstream_info.cc/h :解析.pbstream格式文件(Cartographer 的地图状态文件),提取关键信息,提供地图地图元数据的快速查看,无需完整加载地图
│ │ │ ├── pbstream_migrate.cc/h :处理.pbstream文件的格式迁移,当Cartographer 版本更新导致序列化格式变化时,将旧版本.pbstream文件转换为新版本格式,保证历史地图数据的兼容性
│ │ │ └── testing/test_helpers.cc/h :io/internal模块的测试辅助工具
│ │ ├── coloring_points_processor.cc/h :点云着色
│ │ ├── color.cc/h :提供着色基础结构及接口,如定义颜色结构,颜色转换接口
│ │ ├── points_batch.cc/h :定义PointsBatch结构,点云处理器之间的数据传输载体
│ │ ├── points_processor.h :点云处理器的基类接口,如滤波、着色等,支持组合模式构建点云处理流水线
│ │ ├── min_max_range_filtering_points_processor.cc/h :基于距离范围的点云滤波,移除过近或过远的点
│ │ ├── xray_points_processor.cc/h :通过沿某一轴(如Z 轴)投影点云,生成"X射线"俯视图,用于可视化地图的剖面结构
│ │ ├── counting_points_processor.cc/h :统计点云处理过程中的点数量(如输入点数、过滤后剩余点数),用于调试或性能分析
│ │ ├── draw_trajectories.cc/h :轨迹数据(位姿序列)绘制为图像或矢量图,评估定位结果的精度
│ │ ├── fake_file_writer.cc/h :模拟文件写入器,用于单元测试中替代真实文件操作,不产生实际文件(不写入磁盘),同时校验写入内容
│ │ ├── file_writer.cc/h :文件写入的基础实现,为点云文件(PCD/PLY)、地图文件(.pbstream)等提供跨平台接口
│ │ ├── fixed_ratio_sampling_points_processor.cc/h :按固定比例对点云进行采样,降低资源消耗
│ │ ├── frame_id_filtering_points_processor.cc/h :根据点云的帧(frame_id)进行过滤
│ │ ├── hybrid_grid_points_processor.cc/h :将点云数据转换为混合网格(HybridGrid)格式并写入文件,混合网格是Cartographer 中一种紧凑的3D地图表示方式,
│ │ ├── image.cc/h :图像处理工具,支持从点云或地图数据生成图像,提供图像缩放、保存等功能
│ │ ├── intensity_to_color_points_processor.cc/h :根据点云的强度值(如激光反射强度)为点云着色,增强点云可视化的辨识度
│ │ ├── null_points_processor.h :空点云处理器(什么也不做),通常作为处理流水线的终点或默认处理器,用于测试流水线结构或在无需实际处理时占位
│ │ ├── outlier_removing_points_processor.cc/h :移除点云中的离群点,提升点云质量
│ │ ├── pcd_writing_points_processor.cc/h :点云写入PCD(Point Cloud Data)格式文件
│ │ ├── ply_writing_points_processor.cc/h :点云写入PLY(Polygon File Format)格式文件
│ │ ├── points_processor_pipeline_builder.cc/h :构建点云处理流水线,将多个处理器串联
│ │ ├── probability_grid_points_processor.cc/h :2D概率网格地图格式转换
│ │ ├── pbstream_main.cc :处理.pbstream地图文件(如保存、加载、查看信息)
│ │ ├── submap_painter.cc/h :将子图(Submap)数据绘制为图像,2D栅格地图渲染为灰度图,3D子图投影为俯视图
│ │ ├── vertical_range_filtering_points_processor.cc/h :按垂直方向(Z 轴)的距离范围过滤点云,用于剔除地面或天花板等无关点
│ │ ├── xyz_writing_points_processor.cc/h : 将点云写入简单的XYZ文本格式文件
│ │ ├── proto_stream.cc/h :protobuf流的核心实现,处理地图数据的序列化读写
│ │ ├── proto_stream_deserializer.cc/h :反序列化工具,负责将.pbstream文件中的protobuf 流解析为Cartographer 的内部数据结构,支持地图的加载与复用
│ │ ├── proto_stream_interface.h :protobuf 流的抽象接口,定义ProtoStreamReader和ProtoStreamWriter的抽象方法,为不同实现(如文件流proto_stream.cc/h、内存流in_memory_proto_stream.cc/h)提供统一接口
│ │ ├── serialization_format_migration.cc/h :处理Cartographer 内部数据序列化格式的跨版本迁移,不仅限于.pbstream文件,还包括传感器数据、地图元数据等格式的兼容转换,确保不同版本算法能交互数据
│ │ └── xxx_test.cc: 各类测试文件
│ ├── mapping :**核心建图与定位模块**
│ │ ├── 2d
│ │ │ ├── grid_2d.cc/h :2D网格地图的基类实现,提供网格的基本操作接口,如网格的尺寸、坐标转换、数据存储逻辑
│ │ │ ├── map_limits.h :定义2D地图的边界范围(如坐标最小值、最大值、分辨率),限制点云或障碍物数据在地图内的存储与处理
│ │ │ ├── probability_grid.cc/h :2D概率网格地图,用概率值(占据/空闲/未知)表示网格状态,支持概率更新
│ │ │ ├── probability_grid_range_data_inserter_2d.cc/h :将2D激光雷达的距离数据(RangeData)插入到概率网格地图中,计算并更新网格的占据概率
│ │ │ ├── submap_2d.cc/h :定义2D子图结构,一个子图包含多帧激光数据构建的概率网格,支持子图的序列化、更新与可视化
│ │ │ ├── xy_index.h :提供2D坐标与网格索引的转换工具(如将世界坐标 (x,y) 转为网格数组的行/列索引),支撑网格地图的坐标计算
│ │ │ └── xxx_test.cc
│ │ ├── 3d
│ │ │ ├── hybrid_grid.h :定义3D混合网格结构,结合体素网格的紧凑性和稀疏存储的高效性,用于3D环境的地图表示
│ │ │ ├── range_data_inserter_3d.cc/h :将3D激光雷达(如Velodyne)的距离数据插入到3D子图(或混合网格)中,更新3D网格的占据状态
│ │ │ ├── submap_3d.cc/h :定义3D子图结构,包含多帧3D激光数据构建的网格,支持3D地图的分层构建与全局拼接
│ │ │ └── xxx_test.cc
│ │ ├── internal : 定位与地图构建底层实现
│ │ │ ├── 2d
│ │ │ │ ├── scan_matching :扫描匹配算法
│ │ │ │ │ ├── ceres_scan_matcher_2d.cc/h :基于Ceres 求解器的2D扫描匹配,通过最小化点云与地图的误差(如点到网格距离),优化机器人位姿,精度高但耗时略长
│ │ │ │ │ ├── correlative_scan_matcher_2d.cc/h :2D关联扫描匹配,通过遍历预设的位姿搜索空间,找到点云与地图匹配度最高的位姿,速度快但精度依赖搜索步长
│ │ │ │ │ ├── fast_correlative_scan_matcher_2d.cc/h :快速2D关联扫描匹配,通过分层搜索(如粗匹配 + 精匹配)优化搜索效率,平衡速度与精度,适用于实时场景
│ │ │ │ │ ├── interpolated_tsdf_2d.h :提供2DTSDF 地图的插值工具,支持非整数网格坐标的距离值计算(如亚像素级插值),提升扫描匹配精度
│ │ │ │ │ ├── occupied_space_cost_function_2d.cc/h :定义2D占据空间代价函数,作为Ceres 优化的误差项(如点云到占据网格的距离误差),支撑ceres_scan_matcher_2d
│ │ │ │ │ ├── real_time_correlative_scan_matcher_2d.cc/h :实时2D关联扫描匹配,进一步优化搜索策略(如动态调整搜索范围),确保在高帧率下的实时性
│ │ │ │ │ ├── rotation_delta_cost_functor_2d.h :定义2D旋转误差代价函数,作为Ceres 优化的约束项,限制机器人位姿的旋转突变,提升优化稳定性
│ │ │ │ │ ├── translation_delta_cost_functor_2d.h :定义2D平移误差代价函数,约束机器人位姿的平移突变,避免优化后位姿跳变
│ │ │ │ │ ├── tsdf_match_cost_function_2d.cc/h :定义基于TSDF 地图的匹配代价函数,用TSDF 距离值计算点云与地图的误差,提升高精度地图的匹配效果
│ │ │ │ │ └── xxx_test.cc
│ │ │ │ ├── local_slam_result_2d.cc/h :封装2D局部SLAM的输出结果,包含当前帧位姿、插入子图的数据、时间戳等,作为局部SLAM与全局SLAM的数据接口
│ │ │ │ ├── local_trajectory_builder_2d.cc/h :2D局部SLAM核心逻辑,结合IMU预测与激光扫描匹配,实时估计机器人位姿,并构建局部子图
│ │ │ │ ├── local_trajectory_builder_options_2d.cc/h:解析2D局部SLAM的配置参数(如扫描匹配窗口、子图分辨率),为local_trajectory_builder_2d 提供参数支撑
│ │ │ │ ├── normal_estimation_2d.cc/h :估计2D点云的法向量,用于分析环境表面的朝向(如墙面、地面),辅助扫描匹配或障碍物分类
│ │ │ │ ├── overlapping_submaps_trimmer_2d.cc/h :裁剪2D重叠子图,删除冗余或重叠度高的旧子图,减少内存占用,保证地图轻量化
│ │ │ │ ├── pose_graph_2d.cc/h :2D全局位姿图核心,管理机器人位姿、子图及约束关系,触发全局优化以消除局部SLAM的累积误差
│ │ │ │ ├── ray_to_pixel_mask.cc/h :生成激光射线在2D网格中经过的所有网格索引(如Bresenham 算法),用于概率网格地图的 “空闲概率” 更新(射线未命中区域标记为空闲)
│ │ │ │ ├── tsdf_2d.cc/h :实现2D截断符号距离函数(TSDF),用距离值表示网格到最近障碍物的距离,提升2D地图的精度与平滑性
│ │ │ │ ├── tsdf_range_data_inserter_2d.cc/h :将2D激光数据插入到TSDF 地图中,更新网格的距离值,支撑高精度2D地图构建
│ │ │ │ ├── tsd_value_converter.cc/h :提供TSDF 距离值与概率值的转换工具(如将TSDF 距离转为占据概率),兼容不同地图表示格式
│ │ │ │ └── xxx_test.cc
│ │ │ ├── 3d
│ │ │ │ ├── scan_matching :扫描匹配算法
│ │ │ │ │ ├── ceres_scan_matcher_3d.cc/h :基于Ceres 求解器的3D扫描匹配,最小化3D点云与3D地图的误差(如点到体素距离),优化3D位姿
│ │ │ │ │ ├── fast_correlative_scan_matcher_3d.cc/h :快速3D关联扫描匹配,通过分层搜索优化3D位姿搜索效率,平衡实时性与精度
│ │ │ │ │ ├── intensity_cost_function_3d.cc/h :定义3D点云强度代价函数,结合激光反射强度(如不同物体反射率差异)优化匹配精度,适用于纹理丰富的环境
│ │ │ │ │ ├── interpolated_grid.h :提供3D网格的插值工具,支持非整数体素坐标的数值计算(如亚体素级插值),提升3D扫描匹配精度
│ │ │ │ │ ├── low_resolution_matcher.cc/h :低分辨率3D匹配器,先用低分辨率地图快速粗匹配,再用高分辨率地图精匹配,提升大场景下的匹配速度
│ │ │ │ │ ├── occupied_space_cost_function_3d.h :定义3D占据空间代价函数,作为Ceres 优化的误差项,计算3D点云到占据体素的距离误差
│ │ │ │ │ ├── precomputation_grid_3d.cc/h :预计算3D网格的匹配代价(如点云到网格的距离预计算),减少扫描匹配时的重复计算,提升速度
│ │ │ │ │ ├── real_time_correlative_scan_matcher_3d.cc/h :实时3D关联扫描匹配,动态调整搜索范围与步长,确保3D场景下的实时位姿估计
│ │ │ │ │ ├── rotational_scan_matcher.cc/h :3D旋转扫描匹配,单独优化机器人的旋转角度(roll/pitch/yaw),再结合平移优化,提升3D位姿估计的稳定性
│ │ │ │ │ ├── rotation_delta_cost_functor_3d.h :定义3D旋转误差代价函数,约束3D位姿优化中的旋转突变,避免姿态跳变
│ │ │ │ │ ├── translation_delta_cost_functor_3d.h :定义3D平移误差代价函数,约束3D位姿优化中的平移突变,提升优化平滑性
│ │ │ │ │ └── xxx_test.cc
│ │ │ │ │── imu_integration.h :提供3DIMU数据积分工具,通过加速度计和陀螺仪数据预测机器人的短期位姿(如速度、姿态),支撑局部SLAM的位姿初始化
│ │ │ │ ├── local_slam_result_3d.cc/h :封装3D局部SLAM的输出结果,包含3D位姿、3D子图数据、传感器时间戳,作为局部与全局SLAM的数据接口
│ │ │ │ ├── local_trajectory_builder_3d.cc/h :3D局部SLAM核心逻辑,结合IMU积分与3D扫描匹配,估计机器人3D位姿(x,y,z,roll,pitch,yaw),构建3D子图
│ │ │ │ ├── local_trajectory_builder_options_3d.cc/h :解析3D局部SLAM的配置参数(如3D体素分辨率、IMU噪声系数),为local_trajectory_builder_3d 提供参数支撑
│ │ │ │ ├── pose_graph_3d.cc/h :3D全局位姿图核心,管理3D机器人位姿、3D子图及约束关系,触发全局优化以消除3D局部SLAM的累积误差(如高度漂移)
│ │ │ │ ├── rotation_parameterization.h :定义3D旋转的参数化方式(如四元数、欧拉角),适配Ceres 求解器的旋转优化,避免数值奇异问题
│ │ │ │ └── xxx_test.cc
│ │ │ ├── constraints :位姿图约束构建
│ │ │ │ ├── constraint_builder_2d.cc/h :构建2D位姿图的约束关系,包括 “帧 - 帧约束”(相邻帧位姿关系)和 “回环约束”(当前帧与历史帧的匹配关系),为全局优化提供误差项
│ │ │ │ ├── constraint_builder_3d.cc/h :构建3D位姿图的约束关系,逻辑与2D类似,但适配3D位姿(四元数 + 平移向量)和3D点云匹配
│ │ │ │ ├── constraint_builder.cc/h :约束构建的基础工具类,封装2D/3D约束构建的通用逻辑(如点云匹配、约束权重计算),为constraint_builder_2d/3d 提供支撑
│ │ │ │ └── xxx_test.cc
│ │ │ ├── optimization :位姿图优化实现
│ │ │ │ ├── cost_functions :优化代价函数
│ │ │ │ │ ├── acceleration_cost_function_3d.h :定义3D加速度代价函数,约束机器人运动的加速度连续性(如避免突然加速 / 减速),提升位姿优化的物理合理性
│ │ │ │ │ ├── cost_helpers.h
│ │ │ │ │ ├── cost_helpers_impl.h :优化代价函数的辅助工具,封装通用计算逻辑(如误差向量计算、权重映射),支撑各类代价函数的实现
│ │ │ │ │ ├── landmark_cost_function_2d.h :定义2D地标约束代价函数,用已知地标的位置(如二维码、路标)作为固定约束,优化机器人位姿,提升定位精度
│ │ │ │ │ ├── landmark_cost_function_3d.h :定义3D地标约束代价函数,逻辑与2D类似,适配3D地标位置(x/y/z),支撑3D场景下的地标辅助定位
│ │ │ │ │ ├── rotation_cost_function_3d.h :定义3D旋转连续性代价函数,约束机器人相邻帧姿态的旋转变化率,避免姿态突变
│ │ │ │ │ ├── spa_cost_function_2d.cc/h :实现2D稀疏pose adjustment(SPA)代价函数,是位姿图优化的核心误差项,描述两个位姿间的相对约束关系
│ │ │ │ │ ├── spa_cost_function_3d.h :实现3D稀疏pose adjustment(SPA)代价函数,逻辑与2D类似,适配3D位姿的相对约束
│ │ │ │ │ └── xxx_test.cc
│ │ │ │ ├── ceres_pose.cc/h :封装Ceres 优化中的位姿参数(如2D位姿的x/y/theta,3D位姿的四元数 / 平移),提供位姿的更新、插值工具,适配Ceres 求解器接口
│ │ │ │ ├── optimization_problem_2d.cc/h :2D位姿图优化核心,将机器人位姿、子图及约束转化为Ceres 优化问题,调用求解器最小化全局误差,修正累积漂移
│ │ │ │ ├── optimization_problem_3d.cc/h :3D位姿图优化核心,逻辑与2D类似,但适配3D位姿和3D约束,解决3D场景下的姿态与位置漂移
│ │ │ │ ├── optimization_problem_interface.h :位姿图优化的抽象接口,定义2D/3D优化的统一方法(如添加位姿、添加约束、执行优化),实现接口隔离
│ │ │ │ ├── optimization_problem_options.cc/h :解析位姿图优化的配置参数(如Ceres 求解器迭代次数、误差权重),为optimization_problem_2d/3d 提供参数支撑
│ │ │ │ ├── xxx_test.cc
│ │ │ ├── scan_matching/real_time_correlative_scan_matcher.cc/h :通用实时关联扫描匹配工具,提供2D/3D扫描匹配的基础逻辑,被局部SLAM模块复用
│ │ │ ├── testing :顾名思义
│ │ │ │ ├── fake_trimmable.h
│ │ │ │ ├── mock_map_builder.h
│ │ │ │ ├── mock_pose_graph.h
│ │ │ │ ├── mock_trajectory_builder.h
│ │ │ │ └── test_helpers.cc/h
│ │ │ ├── collated_trajectory_builder.cc/h :整合多传感器数据(激光、IMU、里程计),按时间戳排序后分发给局部SLAM,确保数据时序一致性
│ │ │ ├── connected_components.cc/h :分析位姿图的连通组件(如多个独立轨迹的关联关系),用于处理多机器人协同建图或轨迹分段拼接
│ │ │ ├── eigen_quaterniond_from_two_vectors.cc/h :通过两个向量计算对应的四元数(如从初始方向向量到目标方向向量的旋转四元数),支撑3D姿态计算
│ │ │ ├── global_trajectory_builder.cc/h :全局轨迹构建器,整合局部SLAM的轨迹与全局优化的结果,生成最终的全局一致轨迹
│ │ │ ├── imu_based_pose_extrapolator.cc/h :基于IMU的位姿外推器,在激光数据未到达时,通过IMU积分预测机器人位姿,填补数据间隙
│ │ │ ├── local_slam_result_data.h :封装局部SLAM结果的通用数据结构(兼容2D/3D),包含位姿、子图数据、传感器标识,作为跨模块数据载体
│ │ │ ├── motion_filter.cc/h :运动滤波器,判断机器人是否发生有效运动(如移动距离 / 旋转角度超过阈值),避免静止时重复处理数据,减少冗余计算
│ │ │ ├── pose_graph_data.h :存储位姿图的核心数据(机器人位姿、子图、约束、轨迹状态),作为pose_graph_2d/3d 的数据容器
│ │ │ ├── range_data_collator.cc/h :多传感器距离数据(如激光、超声)的整理器,按时间戳和传感器ID 分类,确保数据有序分发
│ │ │ ├── submap_controller.cc/h :子图控制器,管理子图的创建、更新、标记(如 “完成” 或 “待优化”),协调局部SLAM与全局SLAM的子图交互
│ │ │ ├── trajectory_connectivity_state.cc/h :跟踪多轨迹的连通状态(如轨迹A 与轨迹B 是否通过回环关联),支撑多轨迹的全局拼接
│ │ │ ├── work_queue.h :任务队列,管理异步任务(如约束计算、子图更新),实现多线程并行处理,提升算法效率
│ │ │ └── xxx_test.cc
│ │ ├── detect_floors.cc/h :检测3D地图中的地面层,通过分析点云的高度分布(如连续平面、高度一致区域),标记地面位置,辅助机器人高度定位或导航
│ │ ├── grid_interface.h :网格地图的抽象接口(兼容2D/3D),定义网格的通用方法(如坐标转换、数据访问、概率更新),实现2D/3D网格的接口统一
│ │ ├── id.h :定义Cartographer 内部的唯一标识(如子图ID、轨迹ID、约束ID),用于数据关联与索引(如通过子图ID 查找对应的子图数据)
│ │ ├── imu_tracker.cc/h :IMU跟踪器,处理IMU数据(去偏置、积分),估计机器人的姿态(roll/pitch)和角速度,支撑位姿计算
│ │ ├── map_builder.cc/h :SLAM地图构建器顶层实现,整合所有模块(局部SLAM、全局位姿图、I/O、传感器处理),提供建图的统一接口(如启动建图、添加传感器数据、获取地图)
│ │ ├── map_builder_interface.cc/h :地图构建器的抽象接口,定义建图的通用方法(兼容单机 / 云端建图),实现接口隔离,便于扩展
│ │ ├── pose_extrapolator.cc/h :位姿外推器顶层实现,整合IMU、里程计数据,提供位姿预测、速度估计功能,支撑实时位姿输出
│ │ ├── pose_extrapolator_interface.cc/h :位姿外推器的抽象接口,定义外推的通用方法(如预测下一位姿、重置外推器),兼容不同外推算法(如IMU基于、里程计基于)
│ │ ├── pose_graph.cc/h :位姿图顶层实现,整合pose_graph_2d/3d 与优化模块,提供全局位姿图的创建、优化、查询接口
│ │ ├── pose_graph_interface.h :位姿图的抽象接口,定义位姿图的通用方法(如添加约束、获取优化后位姿、触发回环检测),兼容2D/3D场景
│ │ ├── pose_graph_trimmer.cc/h :位姿图裁剪器,删除过期或冗余的位姿、约束(如只保留最近 100 帧位姿),减少内存占用,保证长期建图的稳定性
│ │ ├── probability_values.cc/h :提供概率值与对数概率值的转换工具(如将占据概率转为对数概率,便于计算),支撑概率网格地图的概率更新
│ │ ├── xxx_test.cc
│ │ └── proto/
│ ├── metrics :性能监控与指标采集
│ │ ├── counter.cc/h :计数器指标,用于统计事件发生次数(如传感器数据接收次数、优化执行次数),支持累加操作,输出累计值
│ │ ├── family_factory.h :指标家族工厂,创建和管理同类指标(如多个计数器、多个直方图),统一指标的命名、标签与生命周期
│ │ ├── gauge.cc/h :仪表盘指标,用于记录瞬时值(如当前内存占用、实时帧率),支持实时更新,反映当前系统状态
│ │ ├── histogram.cc/h :直方图指标,用于统计数据分布(如扫描匹配耗时、约束计算耗时),支持计算分位数(如 90% 耗时 < 50ms),分析性能瓶颈
│ │ └── register.cc/h :指标注册器,管理所有指标的注册与销毁,确保指标在程序生命周期内有效,且能被监控工具(如Prometheus)发现
│ ├── sensor :传感器数据处理与标准化
│ │ ├── internal :传感器数据底层处理, 提供传感器数据标准化与接口
│ │ │ ├── collator.cc/h :传感器数据整理器,接收多传感器数据(激光、IMU、里程计),按轨迹ID 和时间戳排序,分发给对应的轨迹处理器
│ │ │ ├── dispatchable.h :传感器数据的可分发封装,将数据与处理回调绑定,支持异步分发(如数据到达后自动触发处理函数)
│ │ │ ├── ordered_multi_queue.cc/h :多队列时序排序工具,管理多个传感器的数据流队列,按时间戳合并输出,确保数据时序一致性(如激光与IMU按时间对齐)
│ │ │ ├── trajectory_collator.cc/h :轨迹专属数据整理器,为每个轨迹分配独立的数据队列,处理该轨迹的所有传感器数据,避免跨轨迹数据干扰
│ │ │ ├── voxel_filter.cc/h :体素滤波器,通过体素网格下采样(如每个体素保留一个点)减少点云数量,降低后续处理压力,同时保留点云整体结构
│ │ │ └── *test*.cc
│ │ ├── collator_interface.h :传感器数据整理器的抽象接口,定义数据整理的通用方法(如添加数据、设置处理回调),兼容不同整理器实现
│ │ ├── compressed_point_cloud.cc/h :压缩点云数据结构,支持点云的压缩(如减少坐标精度、稀疏存储)与解压,降低数据传输和存储成本
│ │ ├── data.h :传感器数据的基础抽象类,定义所有传感器数据的通用属性(如时间戳、传感器ID),实现传感器数据的接口统一
│ │ ├── fixed_frame_pose_data.cc/h :固定坐标系位姿数据,存储机器人在固定坐标系(如世界坐标系)下的位姿(如GPS 定位结果),作为绝对定位参考
│ │ ├── imu_data.cc/h :IMU数据结构,存储IMU的加速度(x/y/z 轴)、角速度(x/y/z 轴)及时间戳,标准化IMU数据格式,方便后续积分处理
│ │ ├── landmark_data.cc/h :地标数据结构,存储地标(如二维码、人工路标)的观测信息(如地标ID、相对位姿、观测置信度),支撑地标辅助定位
│ │ ├── map_by_time.h :按时间戳排序的数据集容器,存储传感器数据(如IMU数据序列),支持按时间戳查询、插入数据,方便时序相关操作(如插值)
│ │ ├── odometry_data.cc/h :里程计数据结构,存储里程计(如轮式里程计、视觉里程计)的位姿和速度,标准化里程计数据格式,支撑位姿预测或融合
│ │ ├── point_cloud.cc/h :点云数据结构,存储点的坐标(x/y/z)、强度、颜色等信息,标准化点云格式,兼容激光雷达、深度相机等不同传感器
│ │ ├── range_data.cc/h :距离数据结构,存储传感器的距离观测(如激光的原点、命中点、未命中的端点),标准化距离传感器数据,支撑地图插入
│ │ ├── rangefinder_point.h :距离传感器点的坐标结构(如激光命中点的x/y/z 坐标),作为点云或距离数据的基础单元
│ │ ├── timed_point_cloud_data.cc/h :带时间戳的点云数据,为点云中的每个点添加独立时间戳(如激光雷达的逐点时间戳),支撑高精度时序对齐
│ │ ├── xxx_test.cc
│ │ └── proto/
│ └── transform
│ ├── rigid_transform.cc/h :刚性变换工具,实现2D/3D刚性变换(旋转 + 平移)的计算(如变换组合、逆变换、点变换),支撑不同坐标系间的位姿转换
│ ├── timestamped_transform.cc/h :带时间戳的刚性变换,存储某一时刻的坐标系变换关系(如传感器坐标系到机器人基坐标系的变换),支撑时序相关的坐标转换
│ ├── transform.cc/h :坐标变换基础工具,提供欧拉角与四元数的转换、旋转矩阵计算、坐标映射等通用功能,支撑所有坐标系相关操作
│ ├── transform_interpolation_buffer.cc/h :坐标变换插值缓冲器,存储多个时间戳的变换关系,支持对任意时间戳的变换进行插值(如通过t1 和t3 的变换插值得到t2 的变换),解决传感器数据时间不同步问题
│ ├── xxx_test.cc
│ └── proto/
├── CMakeLists.txt
├── configuration_files: 存放SLAM算法的核心配置文件,均为Lua 脚本,用于灵活调整地图构建、轨迹构建等模块的参数(如2D/3D轨迹构建参数、位姿图优化参数)
│ ├── map_builder.lua
│ ├── map_builder_server.lua
│ ├── pose_graph.lua
│ ├── trajectory_builder_2d.lua
│ ├── trajectory_builder_3d.lua
│ └── trajectory_builder.lua
├── docs: 顾名思义
├── package.xml
├── scripts: 存放自动化脚本,涵盖依赖安装(Abseil、gRPC)、构建测试(如ASAN 内存检测构建)、测试结果转换(如CTest 转JUnit)等
├── WORKSPACE :Bazel 的工作空间配置文件,定义项目的根目录,声明外部依赖的来源和版本
└── ... ...
TODO: 待改