1. 问题现象与背景分析
最近在编译一个SLAM相关项目时,遇到了一个典型的链接错误:"libvikit_common.so: undefined reference to `Sophus::SE3::SE3(Eigen::Matrix<double, 3, 3, 0, 3, 3>..."。这个错误表面上看是链接器找不到Sophus库中SE3类的构造函数实现,但实际上涉及多个技术层面的问题。
在SLAM(Simultaneous Localization and Mapping)系统中,Sophus库是一个广泛使用的李群(Lie Group)计算库,特别是其中的SE3类表示三维空间中的刚体变换(旋转+平移)。而Eigen则是C++中著名的矩阵运算库。这个错误通常发生在以下场景:
- 项目正确包含了Sophus的头文件
- 代码中调用了SE3的构造函数
- 但链接阶段找不到对应的实现
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 错误原因深度解析
2.1 链接过程的基本原理
C++程序的编译分为预处理、编译、汇编和链接四个阶段。这个错误发生在最后的链接阶段,说明:
- 编译器阶段通过了(头文件存在且语法正确)
- 链接器找不到对应的函数实现
具体到本例,链接器在libvikit_common.so中遇到了对Sophus::SE3构造函数的引用,但在提供的库文件中找不到实现。
2.2 Sophus库的特殊性
Sophus库从2016年开始分为模板版本(Sophus Template)和非模板版本。关键区别在于:
- 模板版本(新):全部头文件实现,不需要链接.so文件
- 非模板版本(旧):需要编译并链接libSophus.so
错误信息中显示的Sophus::SE3::SE3表明使用的是非模板版本,因为模板版本的命名空间应该是Sophus::SE3d或Sophus::SE3f。
3. 解决方案与实施步骤
3.1 方案一:切换到模板版本(推荐)
- 确认安装的Sophus版本:
bash复制git clone https://github.com/strasdat/Sophus.git
cd Sophus
git log -1
- 如果是较新版本(2016年后),修改代码:
cpp复制// 旧方式
Sophus::SE3 T;
// 新方式
Sophus::SE3d T; // 双精度版本
// 或
Sophus::SE3f T; // 单精度版本
- 确保CMakeLists.txt中正确包含:
cmake复制find_package(Sophus REQUIRED)
include_directories(${Sophus_INCLUDE_DIRS})
3.2 方案二:正确链接旧版Sophus
如果必须使用旧版本:
cmake复制find_package(Sophus REQUIRED)
target_link_libraries(your_target ${Sophus_LIBRARIES})
3.3 方案三:检查ABI兼容性
有时问题出在编译器ABI不匹配:
bash复制# 查看已安装的
