
1. 从零开始搭建SLAM学习路线一个过来人的完整笔记SLAM这个词如果你刚接触机器人或者自动驾驶领域大概率已经被它反复轰炸过了。全称Simultaneous Localization and Mapping中文叫同步定位与建图。说白了就是一台机器在一个完全陌生的环境里一边要知道自己在哪一边还要把周围的地图画出来。听起来像是个鸡生蛋蛋生鸡的问题——不知道地图怎么定位不知道位置怎么建图。但SLAM就是要把这两个事情同时解决。我最初接触SLAM的时候踩的坑可以说是一个接一个。装ROS环境折腾了三天跑第一个激光雷达建图的时候rviz里一片空白好不容易出了点地图又飘得不成样子。后来慢慢从2D激光SLAM摸到视觉SLAM再到现在的3DGS SLAM走了不少弯路。这篇笔记就是把我这些年积累的学习路径、实操经验和避坑技巧完整梳理出来适合刚入门的同学建立知识框架也适合有一定基础的朋友查漏补缺。不管你是做ROS SLAM建图和自主导航的工程开发还是研究视觉SLAM算法的学术方向或者只是想让自己的机器人跑起来别撞墙下面的内容应该都能帮到你。2. SLAM学习路线整体设计与思路拆解2.1 为什么SLAM的学习顺序不能乱很多人一上来就想搞视觉SLAM觉得激光雷达太贵相机便宜。这个想法本身没错但如果你连基本的坐标系变换、概率论基础、非线性优化都没搞清楚直接啃视觉SLAM十四讲大概率是看一页忘一页。我自己就是这么过来的第一遍看十四讲的时候李群李代数那章直接把我劝退了。SLAM的学习有一条比较合理的路径先建立数学基础再理解传感器特性然后从简单的2D激光SLAM入手跑通整个流程最后再深入到视觉SLAM和3D SLAM。这条路径的核心逻辑是——先见森林再见树木。你得先知道一个完整的SLAM系统长什么样各个模块之间怎么交互再去深挖每个模块的算法细节。具体来说我建议的学习顺序是这样的第一阶段数学与编程基础。线性代数矩阵运算、特征值分解、概率论贝叶斯滤波、高斯分布、非线性优化最小二乘、高斯牛顿法、LM算法、C和Python编程能力。第二阶段ROS基础与2D激光SLAM。学会用ROS做话题通信、TF变换、rviz可视化然后跑通gmapping或cartographer理解栅格地图的构建过程。第三阶段视觉SLAM入门。理解相机模型、特征点提取与匹配、对极几何、PnP求解、光束法平差。第四阶段现代SLAM系统。ORB-SLAM3、VINS-Mono、LIO-SAM等开源框架的源码阅读与实战。第五阶段前沿方向。3DGS SLAM、语义SLAM、多传感器融合等。2.2 激光SLAM和视觉SLAM该怎么选这是被问得最多的问题之一。我的建议是如果你做的是室内机器人、扫地机、AGV这类产品激光雷达SLAM是首选因为2D激光雷达成本已经很低了而且建图精度和鲁棒性都很好。如果你做的是无人机、AR/VR、自动驾驶视觉SLAM或者视觉惯性融合方案更合适因为相机成本低、信息丰富而且能提供更稠密的环境描述。但说实话现在纯视觉或者纯激光的方案都越来越少了主流趋势是多传感器融合。激光雷达提供精确的深度信息相机提供丰富的纹理信息IMU提供高频的运动先验三者互补。所以你不用太纠结先学哪个关键是理解每种传感器的优缺点和适用场景。对比维度激光SLAM视觉SLAM传感器成本2D雷达较低3D雷达较贵相机成本低建图精度高直接测距中等依赖三角化光照鲁棒性不受光照影响对光照变化敏感纹理依赖不依赖纹理弱纹理场景容易丢失地图类型栅格地图/点云地图稀疏/半稠密/稠密点云计算量相对较低特征提取和优化计算量大典型框架gmapping、cartographer、LIO-SAMORB-SLAM3、VINS-Mono、DSO2.3 学习SLAM需要什么样的硬件和软件环境软件环境方面Ubuntu是标配ROS NoeticUbuntu 20.04或者ROS2 HumbleUbuntu 22.04是目前比较稳定的选择。如果你刚开始学我建议直接用ROS1 Noetic资料多、社区活跃、踩坑容易找到答案。ROS2虽然是大势所趋但学习阶段的资料丰富度还是不如ROS1。硬件方面最低配置是一台带独显的笔记本或者台式机因为SLAM的编译和运行对CPU和内存要求不低。如果你要跑视觉SLAM最好有一块NVIDIA显卡方便跑CUDA加速的特征提取。如果要做实机验证一个便宜的2D激光雷达比如思岚的RPLIDAR系列加一个树莓派或者Jetson Nano就能跑起来。注意不要在Windows上折腾ROSWSL虽然能跑但坑很多尤其是涉及到USB设备直通和图形化显示的时候。老老实实装双系统或者用Ubuntu单系统。3. 核心细节解析与实操要点3.1 坐标系变换SLAM中最容易被忽视的基础坐标系变换是SLAM的基石但很多人在学习初期会跳过这部分直接去看算法。结果就是跑代码的时候TF树报错完全不知道从哪查起。我用一个生活化的类比来解释你站在房间里你知道自己相对于房间的位置房间相对于整栋楼的位置整栋楼相对于地图的位置。这三个关系就是三层坐标系变换任何一层断了你就无法知道自己在全局地图中的位置。在ROS中TF树维护了所有这些坐标系之间的变换关系。常见的坐标系包括map全局地图坐标系原点固定在地图某个位置odom里程计坐标系原点在机器人启动位置base_link机器人本体坐标系laser_link激光雷达坐标系camera_link相机坐标系TF变换的本质是旋转矩阵和平移向量的组合。一个三维空间中的刚体变换可以用一个4x4的变换矩阵表示T [ R t ] [ 0 1 ]其中R是3x3的旋转矩阵t是3x1的平移向量。旋转矩阵可以用欧拉角、四元数或者旋转向量来表示。在ROS中四元数是最常用的旋转表示方式因为它没有万向锁问题插值也平滑。实操中最容易出错的地方是TF变换的时间戳。ROS的TF要求每个变换都带时间戳而且不同坐标系之间的变换需要时间对齐。如果你发现rviz里机器人模型闪烁或者激光数据对不上八成是TF的时间戳出了问题。3.2 激光雷达SLAM建图的核心流程以最经典的gmapping为例整个建图流程可以拆解为以下几个关键步骤第一步数据预处理。激光雷达输出的原始数据是极坐标下的距离和角度信息需要转换成笛卡尔坐标系的点云。同时要过滤掉超出量程的无效点和噪声点。这个步骤看起来简单但实际中激光雷达的噪声特性需要仔细标定尤其是低成本雷达在强光或者黑色物体表面容易产生噪点。第二步扫描匹配。这是激光SLAM的核心。简单来说就是把当前帧的激光扫描数据和已有地图进行对齐找到最优的位姿变换。gmapping用的是粒子滤波的方法每个粒子代表一个可能的机器人位姿通过观测模型计算每个粒子的权重然后重采样。cartographer则用了基于图优化的方法先构建子图再做全局优化。第三步地图更新。根据扫描匹配的结果把当前帧的激光数据插入到栅格地图中。每个栅格有一个占据概率被激光击中的栅格概率增加激光穿过的栅格概率降低。用对数几率log-odds来表示可以避免数值溢出l(m) log(p(m) / (1 - p(m)))更新时直接做加法l_new l_old l_measurement非常高效。第四步位姿修正。当机器人重新访问之前到过的区域时通过回环检测发现这一点然后对整条轨迹进行优化消除累积误差。这一步是建图精度的关键没有回环检测的SLAM系统跑久了地图一定会歪。3.3 视觉SLAM的特征点法与直接法之争视觉SLAM有两大流派特征点法和直接法。特征点法先提取图像中的关键点如ORB、SIFT、SURF然后匹配相邻帧的特征点通过几何关系求解相机运动。直接法则跳过特征提取直接利用像素灰度值构建光度误差来优化相机位姿。特征点法的优势在于对光照变化和运动模糊更鲁棒因为特征描述子本身具有一定的光照不变性。ORB-SLAM系列就是特征点法的集大成者它的跟踪、局部建图、回环检测三个线程并行运行精度和鲁棒性都很好。但特征点法的缺点也很明显特征提取耗时在弱纹理场景下容易丢失而且只能构建稀疏点云地图。直接法的优势在于能利用所有像素信息可以构建半稠密甚至稠密地图在纹理丰富的场景下精度更高。DSO、LSD-SLAM是直接法的代表。但直接法对光照变化非常敏感而且光度误差函数的非凸性更强优化容易陷入局部极小值。我的建议是入门阶段先学特征点法因为它的理论体系更成熟调试工具更完善。等你对SLAM的整体框架有了感觉再去研究直接法。3.4 3DGS SLAMSLAM领域的新范式3D Gaussian Splatting3DGS是最近两年非常火的方向它用一堆三维高斯椭球来表示场景每个高斯有位置、协方差、不透明度和球谐系数等属性。渲染的时候把这些高斯投影到图像平面做alpha混合就能得到高质量的渲染结果。3DGS SLAM就是把3DGS作为地图表示替代传统的点云或者体素地图。这样做的好处是地图更紧凑、渲染质量更高、还能做新视角合成。但挑战也很大3DGS的优化需要大量计算实时性是个问题而且3DGS地图的更新和回环修正不像传统地图那么直接。目前比较有代表性的工作包括SplaTAM、Gaussian-SLAM等。如果你对这个方向感兴趣建议先跑通原版3DGS的代码理解它的渲染管线和优化过程再去研究怎么把它嵌入SLAM框架。4. 实操过程与核心环节实现4.1 ROS环境搭建与第一个激光SLAM建图假设你已经装好了Ubuntu 20.04下面是从零开始跑通一个2D激光SLAM建图的完整步骤。安装ROS Noeticsudo sh -c echo deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main /etc/apt/sources.list.d/ros-latest.list sudo apt install curl curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - sudo apt update sudo apt install ros-noetic-desktop-full echo source /opt/ros/noetic/setup.bash ~/.bashrc source ~/.bashrc安装gmapping和导航包sudo apt install ros-noetic-gmapping ros-noetic-navigation ros-noetic-teleop-twist-keyboard启动建图节点。假设你有一个激光雷达发布在/scan话题上里程计发布在/odom话题上rosrun gmapping slam_gmapping scan:/scan然后在rviz中添加LaserScan和Map显示用键盘遥控机器人慢慢走一圈你就能看到地图逐渐构建出来。保存地图rosrun map_server map_saver -f ~/my_map这会生成my_map.pgm和my_map.yaml两个文件前者是地图图像后者是地图的元数据配置。4.2 关键参数调优与计算过程gmapping的参数很多但真正影响建图效果的就这么几个参数名默认值作用调优建议particles30粒子数量场景大且复杂时增加到50-80delta0.05扫描匹配的位姿变化阈值减小到0.02可提高精度但增加计算量linearUpdate1.0机器人移动多少米更新一次减小到0.5可提高地图密度angularUpdate0.5机器人旋转多少弧度更新一次减小到0.2可改善旋转时的建图maxRange5.0激光最大有效距离根据实际雷达量程设置sigma0.05扫描匹配的方差雷达噪声大时适当增大粒子数量的选择有一个经验公式粒子数应该与地图面积和机器人位姿不确定性成正比。如果地图是100平米左右的室内环境30个粒子通常够用。但如果环境中有很多相似的结构比如长走廊需要增加粒子数来避免粒子退化。4.3 视觉SLAM十四讲配套代码实操视觉SLAM十四讲是入门视觉SLAM最好的教材之一但书中的代码需要自己配置环境。以下是我实际跑通的环境配置安装依赖sudo apt install cmake g git libeigen3-dev libopencv-dev libpcl-dev libceres-dev libg2o-dev安装Sophus李代数库git clone https://github.com/strasdat/Sophus.git cd Sophus mkdir build cd build cmake .. make -j4 sudo make install编译并运行ch7的PnP求解示例cd slambook2/ch7 mkdir build cd build cmake .. make -j4 ./pose_estimation_3d2d这个示例演示了如何用3D-2D的匹配点对求解相机位姿。核心是构建重投影误差然后用Ceres或者g2o做非线性优化。如果你跑出来的位姿和真值差距很大检查一下特征匹配的质量可以加一个RANSAC剔除误匹配。4.4 从建图到自主导航的完整链路建好地图只是第一步让机器人在地图上自主导航才是最终目标。ROS的navigation包提供了完整的导航框架包括全局规划、局部规划、代价地图、恢复行为等模块。配置导航包的核心文件costmap_common_params.yaml代价地图通用参数包括机器人半径、障碍物膨胀半径、传感器配置global_costmap_params.yaml全局代价地图参数local_costmap_params.yaml局部代价地图参数base_local_planner_params.yaml局部规划器参数包括最大速度、加速度、路径评分权重启动导航roslaunch my_robot_nav navigation.launch然后在rviz中用2D Pose Estimate设置初始位置用2D Nav Goal设置目标点机器人就会自动规划路径并移动过去。实操中导航最容易出的问题是代价地图膨胀半径设置不当。膨胀半径太小机器人会贴着墙走甚至撞墙膨胀半径太大狭窄通道会被完全堵死规划不出路径。我的经验是膨胀半径设置为机器人半径的1.5到2倍比较合适。5. 常见问题与排查技巧实录5.1 建图过程中地图漂移怎么办地图漂移是SLAM中最常见的问题表现为建好的地图出现重影、墙壁变厚、回环处对不齐。原因通常有以下几个里程计精度不够。如果轮式里程计的标定不准确累积误差会很快导致地图漂移。解决方法是重新标定轮子半径和轮距或者引入IMU做融合。回环检测失败。如果机器人回到了之前到过的位置但没有识别出来误差就无法消除。可以尝试调整回环检测的搜索半径和匹配阈值。对于gmapping可以增大linearUpdate和angularUpdate的灵敏度。激光雷达安装位置不准确。如果TF树中激光雷达相对于底盘的变换有偏差扫描匹配就会出错。用卷尺实际测量雷达的安装位置确保TF配置中的平移和旋转参数准确。环境特征太少。在长走廊或者空旷大厅中激光扫描的几何特征不明显扫描匹配容易退化。这种情况下可以考虑加入视觉信息或者反光板辅助定位。5.2 视觉SLAM跟踪丢失的排查思路视觉SLAM跟踪丢失通常发生在快速运动、弱纹理区域或者光照剧烈变化的时候。排查步骤检查图像质量。在rviz或者image_view中查看相机图像确认曝光是否正常、是否有运动模糊。检查特征点数量。ORB-SLAM会在图像上绘制提取到的特征点如果特征点太少少于100个说明场景纹理不足。检查IMU数据。如果用了视觉惯性方案IMU的偏置和噪声参数需要仔细标定。IMU数据异常会导致跟踪发散。降低运动速度。快速旋转是视觉SLAM最容易丢失的运动模式因为帧间重叠区域太小。放慢速度通常能解决问题。5.3 常见问题速查表问题现象可能原因排查方法解决方案rviz中无激光数据显示话题名不匹配rostopic list查看实际话题名修改launch文件中的话题映射TF报错Lookup would require extrapolation时间戳不同步rosrun tf view_frames查看TF树检查传感器时间戳加ros::Time::waitForTransform建图时地图抖动扫描匹配不稳定查看odom和laser的TF频率降低机器人速度增大粒子数导航时机器人原地转圈局部规划器陷入局部极小查看局部代价地图调整局部规划器参数增加恢复行为编译ORB-SLAM3报错依赖版本不兼容查看CMake错误信息使用指定版本的OpenCV和Eigen3DGS训练显存不足高斯数量过多nvidia-smi查看显存占用降低图像分辨率增加稠密化阈值5.4 几个让我印象深刻的踩坑经历坑一ROS时间戳问题。有一次跑建图地图每隔几秒就跳一下。查了两天才发现是激光雷达的驱动节点用了系统时间而不是ROS时间导致TF变换的时间戳和激光数据对不上。解决方法是在驱动中统一使用ros::Time::now()。坑二OpenCV版本冲突。ORB-SLAM3需要OpenCV 3.x但Ubuntu 20.04默认装的是OpenCV 4.x。直接编译会报一堆API不兼容的错误。我的做法是从源码编译OpenCV 3.4并安装到/usr/local然后在CMake中指定路径。坑三3DGS SLAM的实时性。第一次跑SplaTAM的时候每帧要优化好几秒完全没法实时。后来发现是高斯数量增长太快稠密化策略太激进。调整了稠密化阈值和修剪策略之后帧率提升到了可接受的范围。提示SLAM的调试过程中可视化工具是你的最好朋友。rviz、Foxglove、PlotJuggler这些工具能帮你快速定位问题。不要只盯着终端里的日志看把数据画出来往往一目了然。6. 进阶方向与学习资源推荐6.1 值得深入研究的开源框架当你跑通了基础的建图之后下一步就是阅读优秀开源项目的源码。以下是我认为最值得花时间研究的几个ORB-SLAM3视觉SLAM的标杆支持单目、双目、RGB-D和IMU融合代码结构清晰适合学习完整的SLAM系统架构。LIO-SAM激光惯性紧耦合方案基于因子图优化适合学习多传感器融合的工程实现。CartographerGoogle开源的2D和3D建图方案工程化程度极高适合学习工业级SLAM系统的设计。VINS-Mono视觉惯性里程计香港科技大学开源适合学习VIO的滑动窗口优化。SplaTAM3DGS SLAM的代表工作适合了解SLAM与神经渲染的结合。阅读源码的时候不要试图一次看懂所有文件。我的方法是先跑通demo然后从main函数开始沿着数据流一步步跟踪画出模块之间的调用关系图。遇到不懂的函数就查文档或者看论文慢慢就能把整个系统串起来。6.2 数学基础补强建议SLAM涉及到的数学知识比较多但不需要全部学完再开始。我建议采用用到什么学什么的策略线性代数重点掌握矩阵分解、特征值、最小二乘。推荐MIT的18.06课程。概率论重点掌握贝叶斯公式、高斯分布、马尔可夫链。推荐《概率机器人》前几章。非线性优化重点掌握高斯牛顿法、LM算法、图优化。推荐《视觉SLAM十四讲》第6章和第9章。李群李代数这是SLAM中比较抽象的部分但理解了之后会发现它其实就是描述旋转和平移的数学工具。推荐Barfoot的《State Estimation for Robotics》。6.3 保持学习动力的几个建议SLAM的学习曲线确实陡峭我见过太多人中途放弃了。几个实用的建议第一不要追求一次学透。第一遍看不懂很正常先跑通代码有个感性认识再回头啃理论会容易很多。第二找一个具体的项目做驱动。比如让你的机器人自动巡逻、让无人机自主飞行有了明确的目标学习效率会高很多。第三加入社区多交流。ROS Answers、GitHub Issues、各种SLAM技术群遇到问题不要自己死磕问出来往往很快就能解决。第四定期复盘和记录。我现在还保持着写学习笔记的习惯每次解决了一个bug或者理解了一个新概念就记下来。过一段时间回头看能明显感觉到自己的进步。这个方向后续还可以往语义SLAM、神经辐射场SLAM、多机器人协同SLAM等方向扩展。但不管往哪个方向走基础打牢了上层的东西都是触类旁通的。