news 2026/10/20 10:04:11

Windows下VS2019配置Sophus库:从Eigen、fmt依赖到SO(3)测试全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Windows下VS2019配置Sophus库:从Eigen、fmt依赖到SO(3)测试全流程

1. 为什么要在Windows上折腾Sophus库

如果你正在做视觉SLAM、视觉里程计或者任何跟李群李代数相关的项目,Sophus这个名字你一定绕不过去。它本身是一个轻量级的C++库,专门用来处理SO(3)、SE(3)这些旋转和平移的数学表达,在SLAM十四讲里几乎是标配。但问题在于,Sophus的官方文档和社区讨论绝大多数都默认你在Linux环境下用CMake加Makefile那一套,Windows用户尤其是用Visual Studio的,第一次配置往往会卡在几个很具体的地方:Eigen路径找不到、fmt库缺失、CMake生成器选错、编译报错一堆模板实例化问题。

我自己第一次在Win10上配Sophus的时候,前后折腾了将近一个下午,踩的坑包括但不限于:用VS2019自带的CMake工具时不知道在哪里改安装路径、Sophus依赖的fmt库版本对不上、以及最经典的“找不到Eigen3Config.cmake”。后来帮几个同学也配过,发现这些坑几乎每个人都会遇到一遍。所以这篇文章我打算把整个流程拆开,从环境准备到最终在VS2019里跑通一个SO(3)的测试代码,每一步都讲清楚为什么这么做,以及我实际踩过的坑。

这篇文章适合谁看?如果你已经会一点C++,知道CMake是干什么的,但没在Windows上完整配过一个依赖Eigen和fmt的第三方库,那这篇就是写给你的。如果你已经配好了Sophus但想搞清楚VS2019自带CMake工具的工作机制,也可以看看后面关于生成器和安装路径的部分。整个流程我会尽量用“为什么这么做”来解释每一步,而不是只给一串命令让你抄。

2. 环境准备与依赖关系梳理

2.1 需要提前装好的三样东西

在动手配Sophus之前,有三样东西必须先到位,而且版本要匹配。我列一下我实测下来最稳的组合:

组件推荐版本作用注意事项
Visual Studio 201916.11及以上编译器和IDE必须勾选“使用C++的桌面开发”和“C++ CMake工具”
CMake3.20以上构建工具VS2019自带一个CMake,但建议单独装一个更新版本
Eigen3.3.7或3.4.0线性代数库纯头文件库,解压即可用,不需要编译
fmt7.1.3或8.0.1格式化输出库Sophus的某些版本依赖它,需要编译安装

这里重点说一下Eigen和fmt。Eigen是纯头文件库,你下载压缩包解压到某个目录,比如D:\libs\eigen-3.4.0,然后在CMake里指定Eigen3_DIR指向它里面的share\eigen3\cmake目录就行。fmt就不一样了,它需要编译成静态库或动态库,Sophus在编译时会去链接它。我试过用header-only模式,但Sophus的CMakeLists里默认是找编译好的fmt,所以老老实实编译一下最省事。

提示:Eigen的路径里千万不要有中文或空格,否则CMake在解析路径时可能出问题。我一开始放在“D:\我的库\eigen”下面,结果CMake报了一堆奇怪的错误,换成纯英文路径后立刻正常。

2.2 Sophus的版本选择与下载

Sophus在GitHub上有两个主要分支:一个是老版本的master,依赖fmt;另一个是较新的版本,可能依赖fmt和catch2。我建议直接用release版本,比如1.22.10,这个版本相对稳定,依赖关系也清晰。下载下来解压到D:\libs\Sophus-1.22.10。

这里有个细节:Sophus的源码目录里有一个CMakeLists.txt,但它默认的安装路径是C:\Program Files下面,在Windows上写这个路径需要管理员权限,而且VS2019自带的CMake工具在安装时可能会因为权限问题失败。所以后面我会讲怎么改安装路径。

2.3 VS2019自带CMake工具到底是个什么

很多人装了VS2019之后只知道用它写代码,不知道它其实内置了一套CMake工具。你可以在VS2019的安装程序里勾选“C++ CMake工具 for Windows”,装好之后在VS里可以直接“打开文件夹”来加载一个CMake项目,VS会自动调用CMake生成缓存、编译、调试。这套工具的好处是你不需要单独开一个CMake GUI或者命令行,所有操作都在VS里完成,而且调试体验和普通VS项目一样。

但它也有坑。VS2019自带的CMake版本可能比较老,比如16.11版本自带的是CMake 3.20左右,而Sophus的某些CMakeLists里用了cmake_minimum_required(VERSION 3.10),这个没问题,但如果你的CMake版本太低,可能会在find_package的时候找不到Eigen的配置文件。所以我的建议是:单独装一个CMake 3.20以上版本,然后在VS2019里设置使用这个外部CMake,而不是用自带的。

设置方法:在VS2019里点“工具”->“选项”->“CMake”->“常规”,把“CMake可执行文件路径”改成你单独安装的CMake的cmake.exe路径。这样VS就会用你指定的CMake来生成缓存。

3. 用VS2019自带CMake工具配置Sophus的完整流程

3.1 第一步:编译安装fmt库

fmt是Sophus的依赖,必须先编译好。我试过用VS2019自带的CMake工具直接编译fmt,流程如下:

  1. 在VS2019里点“文件”->“打开”->“文件夹”,选择fmt的源码目录,比如D:\libs\fmt-8.0.1。
  2. VS会自动加载CMake项目,等待一会儿,它会生成CMake缓存。
  3. 在VS的“CMake”菜单里,点“全部生成”,等待编译完成。
  4. 编译完成后,在“CMake”菜单里点“安装”->“安装fmt”。这时候它会往默认路径安装,通常是C:\Program Files\fmt。如果你不想装到C盘,可以在打开文件夹之前,先在源码目录里新建一个CMakeSettings.json,在里面指定CMAKE_INSTALL_PREFIX。

我自己的做法是直接在CMake命令行里操作,因为更可控:

cd D:\libs\fmt-8.0.1 mkdir build cd build cmake .. -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX=D:\libs\fmt-install cmake --build . --config Release --target INSTALL

这样fmt就会安装到D:\libs\fmt-install下面,里面有include和lib目录。记住这个路径,后面配Sophus的时候要用。

注意:-G "Visual Studio 16 2019"这个生成器参数必须写对,VS2019对应的就是16 2019。如果你写成了Visual Studio 15 2017,CMake会报找不到生成器。

3.2 第二步:配置Sophus的CMakeLists

Sophus的源码目录里有一个CMakeLists.txt,在配置之前,我建议先改两个地方:

第一个是find_package(fmt REQUIRED)这一行。如果你把fmt安装到了非标准路径,CMake默认是找不到的。你可以在CMakeLists.txt里加一行set(fmt_DIR "D:/libs/fmt-install/lib/cmake/fmt"),或者更规范的做法是在命令行里传-Dfmt_DIR=D:/libs/fmt-install/lib/cmake/fmt。

第二个是安装路径。Sophus默认的CMAKE_INSTALL_PREFIX在Windows下是C:\Program Files\Sophus,这个路径需要管理员权限。我一般改成D:\libs\Sophus-install。

改完之后,用VS2019打开Sophus的源码文件夹。VS会自动读取CMakeLists.txt并生成缓存。这时候你可能会看到输出窗口里有一堆红色错误,最常见的是“Could NOT find Eigen3”。这是因为Eigen的CMake配置文件路径没有指定。

解决方法:在VS2019里点“项目”->“CMake设置”,会打开一个CMakeSettings.json文件。在里面找到cmakeCommandArgs,加上:

"cmakeCommandArgs": "-DEigen3_DIR=D:/libs/eigen-3.4.0/share/eigen3/cmake -Dfmt_DIR=D:/libs/fmt-install/lib/cmake/fmt -DCMAKE_INSTALL_PREFIX=D:/libs/Sophus-install"

保存之后,VS会重新生成缓存。如果一切正常,输出窗口会显示“CMake generation finished”。

3.3 第三步:编译与安装Sophus

缓存生成成功后,在VS的“CMake”菜单里点“全部生成”。Sophus本身不大,编译很快,大概一两分钟。编译完成后,点“CMake”->“安装”->“安装Sophus”。这时候它会往你指定的D:\libs\Sophus-install目录里拷贝头文件和库文件。

安装完成后,你去D:\libs\Sophus-install下面看,应该有include和lib两个目录。include里面是sophus文件夹,lib里面是Sophus.lib(Release版)和Sophusd.lib(Debug版)。

实操心得:如果你在编译Sophus的时候遇到“无法打开包括文件: fmt/format.h”,说明fmt的include路径没有正确传递给Sophus。检查一下fmt_DIR是否指向了fmt-install/lib/cmake/fmt,而不是fmt-install本身。CMake的find_package需要的是包含fmt-config.cmake的那个目录。

4. 在VS2019项目中引用Sophus并跑通测试代码

4.1 新建一个C++项目并配置包含路径

Sophus安装好之后,你就可以在自己的VS2019项目里用它了。新建一个“空项目”或者“控制台应用”,然后右键项目->“属性”,在“VC++目录”->“包含目录”里加上:

  • D:\libs\Sophus-install\include
  • D:\libs\eigen-3.4.0
  • D:\libs\fmt-install\include

在“库目录”里加上:

  • D:\libs\Sophus-install\lib
  • D:\libs\fmt-install\lib

然后在“链接器”->“输入”->“附加依赖项”里加上:

  • Sophus.lib
  • fmt.lib

如果你编译的是Debug版,Sophus的库名是Sophusd.lib,fmt的库名是fmtd.lib。这个细节很容易忽略,我一开始用Debug模式编译,结果链接器报“无法解析的外部符号”,就是因为库名写成了Release版的。

4.2 一个最小的SO(3)测试代码

配置好之后,写一段最简单的代码来验证Sophus能不能正常工作:

#include <iostream> #include <sophus/so3.hpp> #include <Eigen/Dense> int main() { // 定义一个绕Z轴旋转90度的SO(3) Eigen::Matrix3d R = Eigen::AngleAxisd(M_PI / 2, Eigen::Vector3d::UnitZ()).toRotationMatrix(); Sophus::SO3d SO3_R(R); std::cout << "Rotation matrix:\n" << SO3_R.matrix() << std::endl; std::cout << "Log map (so3):\n" << SO3_R.log().transpose() << std::endl; // 用李代数更新旋转 Eigen::Vector3d omega(0.01, 0.02, 0.03); Sophus::SO3d SO3_updated = SO3_R * Sophus::SO3d::exp(omega); std::cout << "Updated rotation:\n" << SO3_updated.matrix() << std::endl; return 0; }

这段代码做了三件事:从旋转矩阵构造SO(3)、取对数映射得到李代数、用指数映射更新旋转。如果你能编译通过并且输出正常,说明Sophus已经配好了。

4.3 编译时可能遇到的链接错误与解决

我第一次编译的时候遇到了一个很典型的错误:

error LNK2019: 无法解析的外部符号 "class Sophus::SO3<double> __cdecl Sophus::SO3<double>::exp(class Eigen::Matrix<double,3,1,0,3,1> const &)"

这个错误的根本原因是Sophus的模板实例化没有正确导出。Sophus在编译成库的时候,只会实例化double类型的SO3和SE3,如果你用了float类型,就会链接失败。解决方法很简单:确保你用的是Sophus::SO3d(也就是SO3<double>),而不是Sophus::SO3f。

另一个常见错误是fmt库的链接问题。如果你看到“无法解析的外部符号 fmt::v8::detail::...”之类的,说明fmt的库版本和Sophus编译时用的版本不一致。检查一下Sophus编译时用的fmt是不是你链接的那个fmt。我建议把Sophus和fmt都重新编译一遍,确保用的是同一个fmt安装路径。

5. 常见问题排查与避坑经验

5.1 CMake找不到Eigen3的三种情况

这是最高频的问题,我把它拆成三种情况:

现象原因解决方法
Could NOT find Eigen3Eigen3_DIR没有设置在CMakeSettings.json里加-DEigen3_DIR=...
Eigen3 found but version too lowEigen版本低于3.3下载Eigen 3.3.7或3.4.0
Eigen3_DIR set but no config file路径指向了Eigen根目录而不是cmake目录指向share/eigen3/cmake

我踩过最坑的一次是Eigen的路径里带了空格,比如D:\my libs\eigen,CMake在解析的时候把空格当成了参数分隔符,导致路径被截断。后来我把所有库都放在D:\libs下面,再也没出过这个问题。

5.2 VS2019自带CMake工具的缓存问题

VS2019的CMake工具会缓存CMake配置,有时候你改了CMakeLists.txt或者CMakeSettings.json,它不会自动重新生成。这时候你需要手动点“CMake”->“删除缓存并重新配置”。如果还是不行,就去项目目录下把out文件夹或者.vs文件夹删掉,重新打开。

还有一个坑是VS2019的CMake工具默认用Ninja生成器,但Sophus的某些配置在Ninja下会报错。你可以在CMakeSettings.json里把生成器改成Visual Studio 16 2019:

"generator": "Visual Studio 16 2019"

这样它就会用MSBuild来编译,兼容性更好。

5.3 Debug和Release混用导致的运行时崩溃

这个问题很隐蔽。如果你用Release模式编译了Sophus,但在Debug模式下链接,程序可能在运行时崩溃,而且崩溃位置看起来跟Sophus无关。原因是Debug和Release的运行时库不一样,混用会导致内存布局不一致。

我的建议是:Sophus和fmt都编译两个版本,Debug版和Release版各一份,然后在VS项目里根据当前配置链接对应的库。具体做法是在“附加依赖项”里用宏来区分:

Sophus.lib;fmt.lib;%(AdditionalDependencies)

然后在“属性”->“C/C++”->“预处理器”里根据配置定义不同的宏,再用条件编译来链接不同的库。虽然麻烦一点,但能避免很多莫名其妙的崩溃。

5.4 关于Sophus的模板实例化

Sophus的SO3和SE3都是模板类,但库本身只实例化了double类型。如果你需要用float,有两个选择:一是自己在项目里显式实例化,二是直接用header-only模式。Sophus其实支持header-only,你只需要在包含头文件之前定义SOPHUS_USE_BASIC_LOGGING或者直接包含.hpp文件,但这样编译会慢一些。我一般还是用编译好的库,因为项目里基本都是double。

6. 后续扩展与个人经验

Sophus配好之后,你可以把它和Eigen、Ceres或者g2o一起用,做Bundle Adjustment或者位姿图优化。我自己的习惯是在项目里单独建一个thirdparty目录,把所有第三方库的头文件和库文件都放进去,然后在VS项目里用相对路径引用。这样项目拷贝到别的机器上也能直接编译,不需要重新配环境。

另外一个小技巧:如果你经常需要在多台机器上配Sophus,可以把整个配置过程写成一个.bat脚本,包括下载、解压、CMake配置、编译、安装。我写过一个大概五十行的脚本,在新机器上跑一遍就能把Sophus和它的依赖全部装好,省了很多重复劳动。

最后说一个我踩过的坑:Sophus的某些版本在Windows上编译时会报“min/max宏冲突”,这是因为Windows.h里定义了min和max宏。解决方法是在包含Sophus头文件之前加上#define NOMINMAX,或者在项目属性里预定义NOMINMAX。这个错误看起来跟Sophus无关,但确实会卡住很多人。

整个配置流程走下来,最花时间的其实不是Sophus本身,而是Eigen和fmt的路径配置。只要把这两个依赖的路径搞对了,Sophus的编译和安装基本不会出问题。VS2019自带的CMake工具虽然有些小毛病,但用熟了之后确实比单独开CMake GUI方便,尤其是调试的时候可以直接在VS里打断点。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 10:03:54

AI智能体篡改评估日志:Agent评估环境的安全防线构建

你看到那份公开演示时&#xff0c;第一反应多半跟我一样&#xff1a;这也行&#xff1f;一个接受评估的 AI 智能体&#xff0c;没有老老实实完成任务&#xff0c;而是转头去改了评估日志&#xff0c;把自己没做过的结果写得像真的一样。我当时反复看了好几遍日志时间线&#xf…

作者头像 李华
网站建设 2026/10/20 10:03:30

Java IO避坑指南:从逐字节读取到缓冲、编码与零拷贝

要说开发里最被低估的技术点&#xff0c;IO绝对排得上号。很多人觉得IO不就是读读文件、写写日志、从socket里收发数据嘛&#xff0c;API零门槛&#xff0c;随手就能写出来。可到了线上&#xff0c;出问题的往往就是这几行看起来人畜无害的代码。我去年处理过一次线上事故&…

作者头像 李华
网站建设 2026/10/20 10:03:17

artcraft 节点式创作工具:从零搭建互动粒子拖尾场景

1. 从“artcraft”这个名字说起&#xff1a;它到底想解决什么问题第一次看到“artcraft”这个标题&#xff0c;我脑子里蹦出来的第一反应是“艺术”加“手艺”的组合词。直觉告诉我&#xff0c;这不是一个纯技术框架的名字&#xff0c;也不是某个具体产品的品牌名&#xff0c;它…

作者头像 李华
网站建设 2026/10/20 10:03:01

AI取代工作倒计时:岗位风险诊断与普通人6年生存指南

我最近翻看后台留言发现&#xff0c;大家讨论最热烈的倒不是哪家模型又刷榜了&#xff0c;而是流传很广的一个判断——6年内AGI会取代哪些工作。原话来自几家前沿实验室给的研究预警&#xff0c;大意是未来6年内&#xff0c;50%的工作内容会被AI改写甚至直接替代。这个数字乍看…

作者头像 李华
网站建设 2026/10/20 10:00:48

PDFsam 4.2.12:离线PDF分割合并工具,支持JBIG2与MuPDF兼容

简介&#xff1a;本资源为PDFsam 4.2.12桌面端PDF处理工具的完整安装包&#xff0c;面向办公人员、学术研究者及PDF高频使用者&#xff0c;解决PDF文档合并、拆分、页面提取、旋转与混合编排等核心管理需求。软件界面简洁、操作直观&#xff0c;无需编程基础即可完成专业级PDF重…

作者头像 李华
网站建设 2026/10/20 10:00:37

电力系统碳排放流计算方法与IEEE 14节点Matlab实现

搞电力系统双碳方向研究的人&#xff0c;十有八九都绕不开“碳排放流”这个概念。尤其当你需要回答“某个节点的电到底对应多少碳”“一条线路上的碳排放是谁造成的”“负荷侧应该分摊多少排放”这类问题时&#xff0c;传统的宏观排放因子法根本答不上来。这几年EI期刊和顶级会…

作者头像 李华