1. 从相对位姿到绝对位姿:SE(3)约束的本质理解
在SLAM系统的后端优化中,位姿图优化是最核心的环节之一。当我们处理3D空间中的位姿约束时,通常会遇到两种基本形式:相对位姿约束和绝对位姿约束。相对位姿约束描述的是两个位姿节点之间的相对运动关系,而绝对位姿约束则直接将位姿节点与全局坐标系中的观测值联系起来。
绝对位姿SE(3)约束之所以重要,是因为它能够:
- 提供全局参考框架下的直接观测
- 有效防止累计误差的无限增长
- 在闭环检测中发挥关键作用
- 为系统提供绝对尺度信息
在实际工程中,我们常常需要将旋转和平移分开处理。这种分离处理的优势在于:
- 计算复杂度降低:SO(3)和R³可以分别优化
- 数值稳定性更好:避免耦合带来的病态问题
- 物理意义更明确:便于调试和分析
- 实现更灵活:可以根据需求选择是否耦合
关键提示:在实现分离优化时,必须注意旋转和平移之间的相关性不能被完全忽略,否则可能导致次优解。实践中通常采用交替优化的策略。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数学基础:SO(3)和SE(3)的表示与运算
2.1 SO(3)群的基本性质
三维旋转群SO(3)是所有3×3实正交矩阵且行列式为1的矩阵构成的群。其关键性质包括:
- 闭合性:两个旋转矩阵的乘积仍是旋转矩阵
- 结合律:(R₁R₂)R₃ = R₁(R₂R₃)
- 单位元:存在单位矩阵I
- 逆元:对每个R存在逆矩阵R⁻¹=Rᵀ
在参数化方面,常用的表示方法有:
- 旋转矩阵:3×3矩阵,9个参数+6个约束
- 轴角表示:3个参数,紧凑但有奇异性
- 欧拉角:3个参数,直观但有万向锁问题
- 四元数:4个参数,计算效率高
2.2 SE(3)群的表示与运算
刚体运动的特殊欧氏群SE(3)可以表示为:
SE(3) =
其群运算定义为:
(R₁,t₁)·(R₂,t₂) = (R₁R₂, R₁t₂+t₁)
对应的李代数se(3)可以表示为:
ξ = [ρ,φ]ᵀ ∈ R⁶
其中φ对应旋转部分,ρ对应平移部分。指数映射将李代数映射到李群:
exp(ξ^) = (exp(φ^), Jρ)
3. 右乘形式的位姿约束建模
3.1 残差函数的定义
在右乘形式的位姿约束中,我们定义残差函数为观测值减去预测值:
r(T) = T⁻¹·z
其中:
- T∈SE(3)是待优化的位姿变量
- z∈SE(3)是观测到的绝对位姿
- 运算符"·"表示SE(3)上的群作用
这种定义方式与常用的视觉重投影误差有相似的形式,保持了SLAM系统中误差定义的一致性。
3.2 右扰动模型的推导
采用右扰动模型,我们在位姿T的右侧施加一个小扰动ΔT=exp(δξ^):
r(T·exp(δξ^)) ≈ r(T) + J_rδξ
雅可比矩阵J_r可以通过一阶泰勒展开得到。具体推导步骤如下:
-
将扰动后的残差展开:
r(T·exp(δξ^)) = (T·exp(δξ^))⁻¹·z -
利用SE(3)的逆运算性质:
= exp(-δξ^)·T⁻¹·z -
使用BCH公式的一阶近似:
≈ (I - δξ^)·T⁻¹·z -
展开后得到:
≈ T⁻¹z - δξ^·T⁻¹z -
提取雅可比矩阵:
J_r = -∂(δξ^·T⁻¹z)/∂δξ
3.3 分离形式的雅可比计算
当我们需要将旋转和平移分开处理时,雅可比矩阵可以分解为旋转部分和平移部分。对于右扰动模型:
旋转部分的雅可比:
∂r_R/∂φ = -J_r(φ)
平移部分的雅可比:
∂r_t/∂ρ = -J_r(ρ)
其中J_r(·)表示相应的右雅可比矩阵。这种分离形式使得我们可以针对性地优化旋转或平移分量。
4. 左乘形式的位姿约束建模
4.1 左扰动模型的建立
与右扰动模型相对应,左扰动模型在位姿T的左侧施加扰动:
r(exp(δξ^)·T) = (exp(δξ^)·T)⁻¹·z
推导过程与右扰动类似,但会得到不同的雅可比表达式。左扰动模型在某些情况下计算更为简便,特别是在涉及全局坐标系下的观测时。
4.2 左扰动雅可比的推导
具体推导步骤:
-
展开扰动后的残差:
r(exp(δξ^)·T) = T⁻¹·exp(-δξ^)·z -
使用一阶近似:
≈ T⁻¹·(I - δξ^)·z -
展开得到:
≈ T⁻¹z - T⁻¹·δξ^·z -
提取雅可比矩阵:
J_l = -∂(T⁻¹·δξ^·z)/∂δξ
4.3 左右扰动模型的选择策略
在实际应用中,选择左扰动还是右扰动需要考虑以下因素:
- 计算效率:某些情况下一种形式可能比另一种更高效
- 实现复杂度:与已有代码库的兼容性
- 数值稳定性:不同问题可能导致不同模型的稳定性差异
- 物理意义:左扰动通常对应全局坐标系,右扰动对应局部坐标系
经验法则:
- 当处理传感器自身的位姿优化时,右扰动通常更自然
- 当处理全局地图中的位姿约束时,左扰动可能更合适
5. 实现细节与工程实践
5.1 代码实现框架
一个典型的SE(3)约束优化实现包含以下组件:
cpp复制class SE3CostFunction : public ceres::SizedCostFunction<6, 7> {
public:
SE3CostFunction(const Eigen::Matrix4d& observation) : z_(observation) {}
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
// 解析参数
Eigen::Map<const Eigen::Quaterniond> q(parameters[0]);
Eigen::Map<const Eigen::Vector3d> t(parameters[0] + 4);
// 构建当前位姿
Eigen::Matrix4d T = Eigen::Matrix4d::Identity();
T.block<3,3>(0,0) = q.toRotationMatrix();
T.block<3,1>(0,3) = t;
// 计算残差
Eigen::Matrix4d error = T.inverse() * z_;
Eigen::Map<Eigen::Vector6d> r(residuals);
r.block<3,1>(0,0) = error.block<3,1>(0,3); // 平移残差
r.block<3,1>(3,0) = SO3log(error.block<3,3>(0,0)); // 旋转残差
// 计算雅可比(此处省略具体实现)
if (jacobians != nullptr && jacobians[0] != nullptr) {
// 实现雅可比计算
}
return true;
}
private:
Eigen::Matrix4d z_;
};
5.2 数值稳定性的保障措施
在实际实现中,需要特别注意以下可能导致数值不稳定的情况:
- 旋转矩阵的正交性保持:迭代过程中需要定期重新正交化
- 小角度近似的有效性:当旋转较大时需要特殊处理
- 奇异性问题:某些参数化在特定情况下会出现奇异性
- 尺度一致性:平移和旋转的量级可能差异很大
常用解决方案:
- 使用四元数表示旋转
- 实现自动微分避免手动推导错误
- 添加正则化项防止病态问题
- 采用鲁棒核函数处理异常值
5.3 性能优化技巧
- 稀疏性利用:位姿图本质是稀疏的,应使用稀疏求解器
- 并行计算:独立约束可以并行处理
- 增量式优化:只优化受影响的局部区域
- 近似计算:在保证精度的前提下简化计算
6. 常见问题与调试技巧
6.1 收敛问题诊断
当优化不收敛时,可以检查以下方面:
- 残差定义是否正确:物理量纲是否一致
- 雅可比实现是否正确:与数值微分结果对比
- 初始值是否合理:太差的初始值可能导致失败
- 观测噪声设置:是否与实际传感器噪声匹配
调试工具:
- 残差变化曲线监控
- 雅可比数值验证
- 优化过程可视化
- 单步调试关键变量
6.2 典型错误模式
- 螺旋形轨迹:通常表明旋转和平移的耦合处理不当
- 尺度漂移:绝对约束不足或权重设置不合理
- 局部最优:初始值太差或观测约束不足
- 数值爆炸:雅可比计算错误或步长过大
6.3 实用调试技巧
- 简化问题:先验证单个约束的正确性
- 逐步增加复杂度:从2D到3D,从少量节点到完整系统
- 可视化中间结果:发现异常模式
- 单元测试:为每个组件编写测试用例
7. 扩展与进阶方向
7.1 四元数表示的应用
四元数表示在SLAM中有广泛应用,其优势包括:
- 紧凑表示:4个参数表示旋转
- 计算高效:避免三角函数运算
- 无奇异性:不存在万向锁问题
在优化中处理四元数需要注意:
- 单位约束的保持
- 切空间投影的处理
- 局部参数化的选择
7.2 流形上的优化
现代SLAM系统普遍采用流形优化框架,关键点包括:
- 定义合适的retraction操作
- 实现局部参数化的lift和lift操作
- 处理流形上的雅可比传递
7.3 鲁棒优化技术
为了提高系统对异常值的鲁棒性,常用技术包括:
- Huber核函数
- Cauchy核函数
- Tukey双权函数
- 自适应协方差估计
8. 实战经验分享
在实际工程中实现SE(3)约束优化时,我总结了以下几点经验:
- 优先验证旋转部分的正确性:平移问题通常更容易发现和调试
- 保持物理单位的统一:避免因单位不一致导致的数值问题
- 实现自动微分版本作为基准:即使使用解析雅可比
- 注意坐标系一致性:这是最常见的错误来源之一
- 记录优化过程:便于事后分析和问题复现
一个特别有用的调试技巧是构造已知最优解的合成数据,从简单场景开始逐步增加复杂度,确保每个组件在理想条件下都能正确工作,然后再处理真实数据中的各种噪声和异常。
