1. 课程导论与预备知识
各位同学好,我是这门课的主讲。在正式开始之前,我想先聊聊——为什么我们要把点云滤波和IMU放在一起讲?
说实话,我刚开始做SLAM那会儿,也踩过不少坑。记得有一次在自动驾驶项目里,激光雷达的数据被雨点打得稀碎,定位直接飘到马路牙子上去了。后来加了IMU做融合,才算稳住。嗯,这就是我们这门课要解决的核心问题。
1.1 点云与IMU融合定位的应用场景
先说说这东西用在哪。你想想看,现在最火的那几个方向,哪个离得开定位?
- 自动驾驶:车在路上跑,激光雷达扫出点云,IMU提供加速度和角速度。两者一结合,哪怕GPS信号丢了,车也能知道自己在哪。我在做园区无人车时,就靠这套方案扛过了隧道和地下车库。
- 机器人:不管是扫地机还是仓储AGV,室内没有GPS,全靠点云建图和IMU推算。说白了,这就是机器人的「眼睛」和「小脑」。
- AR/VR:你戴着头显,头一动,画面就得跟上。IMU负责快速响应,点云负责修正漂移。我试过只用IMU做AR定位,十分钟后虚拟物体就跑到天花板上了——所以必须融合。
核心观点:点云提供「绝对观测」,IMU提供「相对运动」。两者互补,缺一不可。
1.2 课程知识体系概览
这门课一共30章,我把它分成四个模块。先给你画张图,心里有个底。
看到没?从基础到实战,层层递进。我个人建议你按顺序学,别跳。尤其是李群李代数那块,很多人觉得抽象就跳过了,后面因子图优化时又回来补课——何必呢?
1.3 所需数学基础
数学这东西,我懂,一提就头疼。但做SLAM绕不开,我尽量用白话给你讲明白。
坐标系变换
说白了就是「把一个点从A坐标系挪到B坐标系」。比如激光雷达扫到一个点,坐标是相对于雷达自己的。但我们要把它放到世界坐标系里,就得做旋转和平移。
我的经验:写代码时最容易搞混的就是坐标系顺序。我曾经在ROS里把base_link和odom搞反了,结果机器人原地转圈跑了十分钟。从那以后,我每次做变换前都会画个坐标系草图。
四元数
旋转矩阵有9个参数,但只有3个自由度,冗余不说还容易产生数值问题。四元数用4个参数表示旋转,紧凑且无奇点。
// 四元数基本形式:q = w + xi + yj + zk
// 单位四元数表示旋转
Eigen::Quaterniond q(1.0, 0.0, 0.0, 0.0); // 单位四元数,无旋转
// 绕Z轴旋转90度
q = Eigen::Quaterniond(Eigen::AngleAxisd(M_PI/2, Eigen::Vector3d::UnitZ()));
注意:四元数乘法不满足交换律!q1 * q2 和 q2 * q1 结果不同。我见过有人在这上面debug了一整天,最后发现只是乘法的顺序写反了。
李群与李代数简介
嗯,这里要稍微烧脑一点。李群(SO(3)、SE(3))描述的是连续的旋转和变换。李代数则是李群在单位元处的切空间。
为什么要学这个?因为SLAM里要做优化。你想想看,优化需要在流形上求导,但旋转矩阵本身不是向量空间,不能直接加减。李代数把旋转映射到了向量空间,求导就方便了。
| 概念 | 李群 | 李代数 |
|---|---|---|
| 旋转 | SO(3) — 3x3旋转矩阵 | so(3) — 3维向量(旋转向量) |
| 变换 | SE(3) — 4x4齐次矩阵 | se(3) — 6维向量(平移+旋转) |
| 核心操作 | 乘法(复合变换) | 加法(优化更新) |
我个人习惯用Sophus库,它把李群李代数的运算都封装好了。后面实战章节我们会手写一个简单的李代数求导,到时候你就知道这东西有多好用了。
1.4 开发环境搭建
工欲善其事,必先利其器。环境搭不好,后面全是坑。我直接给你一个经过验证的配置清单。
系统与基础软件
- Ubuntu 20.04:我推荐这个版本,ROS Noetic原生支持,兼容性好。
- ROS Noetic:机器人操作系统,负责节点通信、数据录制回放。
- PCL 1.10:点云库,滤波、分割、配准一条龙。
- Eigen 3.3:线性代数库,矩阵运算、四元数、几何变换。
一键安装脚本
别一个个去apt-get了,我整理了个脚本,直接跑就行。
#!/bin/bash
# 安装ROS Noetic
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
sudo apt update
sudo apt install ros-noetic-desktop-full -y
# 安装PCL
sudo apt install libpcl-dev pcl-tools -y
# 安装Eigen
sudo apt install libeigen3-dev -y
# 安装Sophus(李群李代数库)
cd ~
git clone https://github.com/strasdat/Sophus.git
cd Sophus
mkdir build && cd build
cmake ..
make -j4
sudo make install
避坑指南:我曾经在Ubuntu 22.04上装ROS Noetic,折腾了两天发现不兼容。后来老老实实换回20.04,半小时搞定。所以别跟版本较劲,用推荐的配置最省心。
验证环境
装完后跑个简单的PCL程序,看看能不能正常编译。
# 创建测试文件 test_pcl.cpp
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int main() {
pcl::PointCloud<pcl::PointXYZ> cloud;
cloud.width = 5;
cloud.height = 1;
cloud.points.resize(cloud.width * cloud.height);
for (size_t i = 0; i < cloud.points.size(); ++i) {
cloud.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
cloud.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
cloud.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
}
pcl::io::savePCDFileASCII("test.pcd", cloud);
std::cout << "Saved " << cloud.points.size() << " data points to test.pcd." << std::endl;
return 0;
}
// CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(test_pcl)
find_package(PCL 1.10 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable(test_pcl test_pcl.cpp)
target_link_libraries(test_pcl ${PCL_LIBRARIES})
编译通过,生成test.pcd文件,说明环境没问题。如果报错,多半是PCL版本不对或者路径没配好。检查一下/usr/include/pcl-1.10目录是否存在。
最后说一句:数学基础和环境搭建是这门课的「入场券」。别急着往后赶,把这块吃透了,后面30章你会走得很顺。我当年就是基础没打牢,后面反复回头补课,浪费了不少时间。
好,第一章就到这。去把环境搭起来,我们第二章见。